晉語發音模組/模塊。參見{{zh-pron}}


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

local gsub = m_string_utils.gsub
local sub = m_string_utils.sub
local len = m_string_utils.len
local match = m_string_utils.match

local initialConv = {
	["b"] = "p", ["p"] = "pʰx", ["m"] = "m", ["f"] = "f", ["v"] = "v",
	["d"] = "t", ["t"] = "tʰx", ["n"] = "n", ["l"] = "l", 
	["z"] = "t͡s", ["c"] = "t͡sʰ", ["s"] = "s", ["r"] = "ʐ",
	["j"] = "t͡ɕ", ["q"] = "t͡ɕʰ", ["x"] = "ɕ",
	["g"] = "k", ["k"] = "kʰx", ["gh"] = "ɣ", ["ng"] = "ŋ",
	["h"] = "x", [""] = ""
}

local finalConv = {
	["r"] = "z̩",
	["i"] = "i",
	["u"] = "u", 
	["y"] = "y", 
	["er"] = "əɻ", 
	["a"] = "a", ["ia"] = "ia", ["ua"] = "ua", 
	["e"] = "ɤ", ["ue"] = "uɤ", 
	["ie"] = "ie", ["ye"] = "ye", 
	["ai"] = "ai", ["uai"] = "uai", 
	["ei"] = "ei", ["ui"] = "uei", 
	["au"] = "au", ["iau"] = "iau", 
	["ou"] = "əu", ["iou"] = "iəu", 
	["an"] = "æ̃", ["uan"] = "uæ̃",
	["on"] = "ɒ̃", ["ion"] = "iɒ̃", ["uon"] = "uɒ̃",
	["ang"] = "aŋ", ["iang"] = "iaŋ", ["uang"] = "uaŋ", 
	["eng"] = "ə̃ŋ", 
	["ing"] = "ĩŋ", 
	["ung"] = "ũŋ", 
	["yng"] = "ỹŋ", 
	["ah"] = "aʔ", ["iah"] = "iaʔ", ["uah"] = "uaʔ", 
	["eh"] = "əʔ", ["ieh"] = "iəʔ", ["ueh"] = "uəʔ", ["yeh"] = "yəʔ",
	["rr"] = "z̩ɻ",
	["ir"] = "iɻ",
	["ur"] = "uɻ",
	["yr"] = "yɻ",
	["ar"] = "ɑɻ", ["iar"] = "iɑɻ", ["uar"] = "uɑɻ", 
	["e'r"] = "ɤɻ", ["uer"] = "uɤɻ", 
	["ier"] = "ieɻ", ["yer"] = "yeɻ", 
	["air"] = "ɐɻ", ["uair"] = "uɐɻ", 
	["eir"] = "əɻ", ["uir"] = "uəɻ", 
	["aur"] = "ɒoɻ", ["iaur"] = "iɒoɻ", 
	["our"] = "əuɻ", ["iour"] = "iəuɻ", 
	["anr"] = "æ̃ɻ", ["uanr"] = "uæ̃ɻ",
	["onr"] = "ɒ̃ɻ", ["ionr"] = "iɒ̃ɻ", ["uonr"] = "uɒ̃ɻ",
	["engr"] = "ʌ̃ɻ", 
	["ingr"] = "ĩɻ", 
	["ungr"] = "ũɻ", 
	["yngr"] = "ỹɻ", 
	["ahr"] = "ɐɻ", ["iahr"] = "iɐɻ", ["uahr"] = "uɐɻ", 
	["ehr"] = "əɻ", ["iehr"] = "ieɻ", ["uehr"] = "uəɻ", ["yehr"] = "yeɻ",
}

local toneConv = {
	["1"] = "¹¹", ["2"] = "⁵³", ["3"] = "⁴⁵", ["4"] = "²", ["5"] = "⁵⁴", ["6"] = "¹", ["-"] = "⁻"
}

local toneSandhi = {
	["2+2"] = "2-1", ["2+5"] = "2-1",
	["4+1"] = "4-5", ["4+4"] = "4-5",
	["4+2"] = "4-3", ["4+5"] = "4-3",
	["5+2"] = "5-4", ["5+3"] = "5-4",
}

local neutral = {
	["⁴⁵"] = "⁴", ["²"] = "³", ["¹¹"] = "²"
}

function export.ipa(text, feature)
	if type(text) == "table" then
		text = text.args[1]
	end
	local syllables, initial, final, tone, ipa, result = {}, {}, {}, {}, {}, {}
	local words = mw.text.split(text, "/")
	for _, word in ipairs(words) do
		syllables = mw.text.split(word, " ")
		for index, syllable in ipairs(syllables) do
			initial[index] = match(syllable, "^[bpmfvdtnlzcsrjqxgkh]?[hg]?")
			final[index] = match(sub(syllable, len(initial[index]) + 1, -1), "^[^1-6%-]*")
			tone[index] = match(syllable, "[1-5%-]+$") or (index ~= 1 and "6" or "")
		end
		for index = 1, #syllables do
			initial[index] = initialConv[initial[index]] or error(("Unrecognised initial: \"%s\""):format(initial[index]))
			final[index] = (match(initial[index], "[sz]") and final[index] == "i") and "r" or final[index]
			final[index] = finalConv[final[index]] or error(("Unrecognised final: \"%s\""):format(final[index]))
			tone[index] = tone[index] == "6" and neutral[tone[index-1]] or tone[index]
			tone[index] = feature ~= "no_sandhi" and toneSandhi[tone[index].."+"..(tone[index+1] or "")] or tone[index]
			tone[index] = gsub(tone[index], "[1-6%-]", toneConv)
			ipa[index] = initial[index] .. final[index] .. tone[index]
		end
		table.insert(result, table.concat(ipa, " "))
	end
	return table.concat(result, "/, /")
end

function export.rom(text)
	return (text
		:gsub("/", " / ")
		:gsub("([%d-]+)", "<sup>%1</sup>"))
end

return export