Jump to content

Module:ltc-pron

From Wiktionary, the free dictionary

Middle Chinese pronunciation module. See {{zh-pron}}. Data located at Module:zh/data/ltc-pron and its subpages. Also see Appendix:Middle Chinese for more detailed tables.

Initials

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Rhymes

東一 1
東三 2
屋一 3
屋三 4
5
6
7
8
9
10
支三開 11
支三合 12
支重鈕三開 13
支重鈕三合 14
脂三開 15
脂重鈕四開 15
脂三合 16
脂重鈕四合 16
脂重鈕三開 17
脂重鈕三合 18
19
微開 20
微合 21
22
23
24
泰開 25
泰合 26
廢開 27
廢合 28
夬開 29
夬合 30
佳開 31
佳合 32
皆開 33
皆合 34
祭三開 35
祭重鈕四開 35
祭三合 36
祭重鈕四合 36
祭重鈕三開 37
祭重鈕三合 38
齊開 39
齊合 40
41
42
眞三 43
眞重鈕四 43
眞開 44
眞合 45
46
47
質三 48
質重鈕四 48
質開 49
質合 50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
元開 65
元合 66
月開 67
月合 68
刪開 69
刪合 70
黠開 71
黠合 72
山開 73
山合 74
鎋開 75
鎋合 76
仙三開 77
仙三合 78
仙重鈕三開 79
仙重鈕三合 80
薛三開 81
薛三合 82
薛重鈕三開 83
薛重鈕三合 84
先開 85
先合 86
屑開 87
屑合 88
89
90
宵三 91
宵重鈕四 91
宵重鈕三 92
93
94
戈一合 95
戈三開 96
戈三合 97
麻二開 98
麻二合 99
麻三開 100
唐開 101
唐合 102
鐸開 103
鐸合 104
陽開 105
陽合 106
藥開 107
藥合 108
庚二開 109
庚二合 110
庚三開 111
庚重鈕三開 111
庚三合 112
庚重鈕三合 112
陌二開 113
陌二合 114
陌三開 115
陌三合 116
耕開 117
耕合 118
麥開 119
麥合 120
清開 121
清合 122
昔開 123
昔合 124
青開 125
青合 126
錫開 127
錫合 128
登開 129
登合 130
德開 131
德合 132
133
職開 134
職合 135
136
137
138
侵三 139
侵重鈕三 140
緝三 141
緝重鈕三 142
143
144
145
146
147
148
149
150
151
152
鹽三 153
鹽重鈕三 154
葉三 155
葉重鈕三 156
157
158
158
159
160

local export = {}
local m_string_utils = require("Module:string utilities")

local codepoint = m_string_utils.codepoint
local gsub = m_string_utils.gsub
local len = m_string_utils.len
local match = m_string_utils.match
local safe_require = require("Module:utilities").safe_require
local u = m_string_utils.char

local m_ltc_predict = require("Module:ltc-pron/predict")
local m_cmn_pron = require("Module:cmn-pron")
local m_baxter = require("Module:ltc-pron/baxter")
local data = mw.loadData("Module:ltc-pron/data")

function export.infer_categories(text)
	local t = mw.text.split(text, "", true)
	
	local initial, final, deng, openness, tone = t[1], t[2], t[3], t[4], t[6]
	if match(text, "-") then
		deng = mw.text.split(text, "-")[2] .. deng
	end
	if tone == "入" then final = data.fin_conv[final] or final end
	local initial_type = data.init_type[initial]
	local tone_label = data.tone_symbol[tone]
	local final_type
	
	if match(final, data.final_type_1) then
		final_type = data.fin_type_open[final..openness]
	
	elseif match(final, data.final_type_2) then
		final_type = data.final_deng[final..deng]
	
	elseif match(final, data.final_type_3) then
		final_type = data.fin_type_deng_open[final..deng..openness]
	
	elseif match(final, data.final_type_4) then
		if deng == "重鈕三" then
			final_type = data.final_openness[final..openness]
		else
			final_type = data.final_deng[final..deng]
		end

	elseif match(final, data.final_type_5) then
		final_type = data.fin_type[final]
	
	else
		return error("Final not recognised.")
	end
	
	return initial_type, final_type, tone_label
end

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

local function ltc_table(titlechar, text, indiv_num, count)
	local people = { "Zhengzhang", "Pan", "Shao", "Pulleyblank", "Li", "Wang", "Karlgren" }
	local pronunciation = {}
	local t = mw.text.split(text, "", true)
	
	local initial, final, deng, openness, she, tone, fanqieA, fanqieB = t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]
	if tone == "入" then final = data.fin_conv[final] or final end
	local initial_type, final_type, tone_label = export.infer_categories(text)

	for ind, person in ipairs(people) do
		table.insert(pronunciation, '<span class="IPAchar" lang="zh">/' ..
			data.initialConv[person][initial_type] .. data.finalConv[person][final_type] .. "<sup>" .. tone_label .. "</sup>" .. "/</span>")
	end
	local baxter = '<span lang="zh">' ..
		m_baxter.baxter(initial_type, final_type, tone_label) .. "</span>"
	return {
		nil,
		'<b>'..zh_fmt(titlechar)..'</b>', 
		indiv_num .. "/" .. count,
		zh_fmt("[[Appendix:Middle Chinese#Initials|"..initial.."]]") .. " (" .. initial_type .. ")",
		zh_fmt("[[Appendix:Middle Chinese#Finals|"..final.."]]") .. " (" .. final_type .. ")",
		data.tonality[tone],
		data.open_closed[openness],
		data.division[deng],
		fanqieB and zh_fmt(gsub(fanqieA .. fanqieB, "(.)", "[[%1]]") .. "切") or "",
		baxter,
		nil,
		pronunciation[1],
		pronunciation[2],
		pronunciation[3],
		pronunciation[4],
		pronunciation[5],
		pronunciation[6],
		pronunciation[7],
		m_cmn_pron.py_number_to_mark(m_ltc_predict.predict_cmn(initial_type, final_type, data.tone_number[tone])),
		m_ltc_predict.predict_yue(initial_type, final_type, data.tone_number[tone]),
	}
end

function export.ipa(index_text, preview)
	local titlechar = mw.title.getCurrentTitle().text
	local reading_index = mw.text.split(index_text, ",")
	local ltc_indiv_pronunciation = {}
	local output_text = {}
	
	local fields = {
		"Rime",
		"<small>Character</small>",
		"<small>Reading #</small>",
		"<small>Initial</small> (" .. zh_fmt("聲") .. ")",
		"<small>Final</small> (" .. zh_fmt("韻") .. ")",
		"<small>Tone</small> (" .. zh_fmt("調") .. ")",
		"<small>Openness</small> (" .. zh_fmt("開合") .. ")",
		"<small>Division</small> (" .. zh_fmt("等") .. ")",
		"<small>[[w:Fanqie|Fanqie]]</small>",
		"<small>[[w:Baxter's_transcription_for_Middle_Chinese|Baxter]]</small>",
		"Reconstructions",
		"<small>[[w:Zhengzhang Shangfang|Zhengzhang<br>Shangfang]]</small>",
		"<small>[[w:Pan Wuyun|Pan<br>Wuyun]]</small>",
		"<small>[[w:zh:邵荣芬|Shao<br>Rongfen]]</small>",
		"<small>[[w:Edwin G. Pulleyblank|Edwin<br>Pulleyblank]]</small>",
		"<small>[[w:Li Rong (linguist)|Li<br>Rong]]</small>",
		"<small>[[w:Wang Li (linguist)|Wang<br>Li]]</small>",
		"<small>[[w:Bernhard Karlgren|Bernhard<br>Karlgren]]</small>",
		"<small>Expected<br>Mandarin<br>Reflex</small>",
		"<small>Expected<br>Cantonese<br>Reflex</small>",
	}
	
	for i, cp in ipairs { codepoint(titlechar, 1, -1) } do
		local ch = u(cp)
		local data_module = safe_require("Module:zh/data/ltc-pron/" .. ch)
		if data_module then
			local reading_number = reading_index[i] or "y"
			local count = 0
			for index, value in ipairs(data_module) do
				count = count   1
			end
			if reading_number == "y" then
				for ltc_reading_no, position in ipairs(data_module) do
					table.insert(ltc_indiv_pronunciation, ltc_table(ch, position, ltc_reading_no, count))
				end
			elseif reading_number == "n" then
				break
			else
				for indiv_number in mw.text.gsplit(reading_number, '% ') do
					table.insert(ltc_indiv_pronunciation, ltc_table(ch, data_module[tonumber(indiv_number)], indiv_number, count))
				end
			end
		end
	end

	if ltc_indiv_pronunciation[1] then
		local hash, results, value_eff = {}, {}
		for _, value in ipairs(ltc_indiv_pronunciation) do
			table.remove(value, 11)
			table.remove(value, 1)
			value_eff = table.concat(value)
			if (not hash[value_eff]) then
				hash[value_eff] = true
				table.insert(value, 1, nil)
				table.insert(value, 11, nil)
				results[#results   1] = value
   			end
		end
		local rand = require("Module:string utilities").gsub("mc-" .. value_eff, "[^A-Za-z0-9]", codepoint('%1'))
		local fmt = {
			fold = '\n* <div title="expand" class="mw-customtoggle-mc' .. rand .. '"> ' ..
					'[[w:Middle Chinese|Middle Chinese]]: <span style="font-family: Consolas, monospace;">' .. preview .. 
					'</span><span style="float:right; border:1px solid #ccc; border-radius:1px;' ..
					' padding:0 0; font-size:90%">▼</span></div>\n',
			header = '{| class="wikitable mw-collapsible mw-collapsed" id="mw-customcollapsible-mc' .. rand ..
				'" style="width:100%; margin:0; text-align:center; border-collapse: collapse; border-style: hidden; display: table;"',
			lv1 = '\n|-\n! style="background-color:' .. data.colour_1 .. '" colspan=' .. #results 1 .. '|',
			lv2 = '\n|-\n! style="background-color:' .. data.colour_2 .. '; width:8em"|',
			lv3 = '\n| style="background-color:' .. data.colour_3 .. '"|',
			closing = '\n|}'
		}
		for field_index, field in ipairs(fields) do
			if match(field, "small") then
				local field_set = {}
				for _, result in ipairs(results) do
					table.insert(field_set, result[field_index])
				end
				table.insert(output_text, fmt.lv2 .. field .. fmt.lv3 .. table.concat(field_set, fmt.lv3))
			else
				table.insert(output_text, fmt.lv1 .. field)
			end
		end
		return fmt.fold .. fmt.header .. table.concat(output_text) .. fmt.closing
	else
		return ""
	end
end

function export.retrieve_pron(text, reconstruction, index, no_intro)
	if type(text) == "table" then text = text.args[1] end
	local underline_format = "<span style=\"font-style: normal\">[[w:Middle Chinese|MC]]</span> "
	local separator = len(text) == 1 and (no_intro and ", ") or '<span style="padding-left:2px; padding-right:2px">|</span>'

	-- remove link brackets from text, at least
	-- as [[美姫#Etymology]]
	text = text:gsub("[%[%]]", "")
	
	if reconstruction then
		return underline_format .. reconstruction
	else
		local index_set, retrieve_result = {}, {}
		if index and index ~= "y" then
			index_set = mw.text.split(index, ",")
		end
		for char_index, cp in ipairs { codepoint(text, 1, -1) } do
			local char_pronunciation = {}
			local ch = u(cp)
			local data_module = safe_require("Module:zh/data/ltc-pron/" .. ch)
			if data_module then
				local reading_no = index_set[char_index] or "y"
				if reading_no == "n" then
					table.insert(char_pronunciation, "?")
				elseif reading_no == "y" then
					local initial, final, tone
					for _, reading in ipairs(data_module) do
						initial, final, tone = export.infer_categories(reading)
						table.insert(char_pronunciation, m_baxter.baxter(initial, final, tone))
					end
				else
					for number in mw.text.gsplit(reading_no, " ") do
						initial, final, tone = export.infer_categories(data_module[tonumber(number)])
						table.insert(char_pronunciation, m_baxter.baxter(initial, final, tone))
					end
				end
				table.insert(retrieve_result, table.concat(char_pronunciation, separator))
			end
		end
		return retrieve_result[1] and (no_intro and "" or underline_format) .. 
			table.concat(retrieve_result, " ") or nil
	end
end

function export.link(frame)
	local args = frame:getParent().args
	local 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["id"] or false, false),
		gloss = meaning, lit = lit }, mw.title.getCurrentTitle().subpageText)
end

return export