呢個模組嘅解說可以喺模組:bo-pron/doc度開

local export = {}
local gsub = mw.ustring.gsub
local match = mw.ustring.match

function export.tidyRom(text)
	text = gsub(text, "([fhvw])(.?)", function(a, b) if b == "-" or b == "" or b == " " or b == "," then return "<sup>"..a.."</sup>"..b end end)
	return text
end

local iConv = {
	["b"] = "p", ["p"] = "ˀpʰ",
	["d"] = "t", ["t"] = "ˀtʰ",
	["gy"] = "c", ["ky"] = "ˀcʰ",
	["g"] = "k", ["k"] = "ˀkʰ",
	
	["z"] = "t͡s", ["c"] = "ˀt͡sʰ",
	["zh"] = "ʈ͡ʂ", ["ch"] = "ˀʈ͡ʂʰ",
	["j"] = "t͡ɕ", ["q"] = "ˀt͡ɕʰ",
	
	["m"] = "m", ["n"] = "n", ["ny"] = "ȵ", ["ng"] = "ŋ",
	["mh"] = "m̥", ["ngh"] = "ŋ̊", --limited
	
	["l"] = "l", ["lh"] = "ɬ",
	["f"] = "f", ["s"] = "s", ["h"] = "h",
	["sh"] = "ʂ", ["x"] = "ɕ", ["hy"] = "ç",
	
	["r"] = "ʐ",
	
	["w"] = "w", ["y"] = "j",
	
	[""] = "ʔ",
}

local fConv = {
	["i"] = "i", ["e"] = "e", ["a"] = "ɑ", ["ac"] = "ɤ", ["o"] = "o", ["u"] = "u",
	
	["ii"] = "iː", ["ee"] = "eː", ["aa"] = "ɑː", ["acc"] = "ɤː", ["oo"] = "oː", ["uu"] = "uː",
	["ae"] = "ɛː", ["oe"] = "øː", ["ue"] = "yː", ["ie"] = "ɪː", ["uo"] = "ʊː",
	
	["iu"] = "iu", ["eu"] = "eu", ["acu"] = "ɤu",
	["ao"] = "ɑo", ["ua"] = "uɑ", ["ei"] = "ei", ["io"] = "io",
	
	["im"] = "im", ["em"] = "em", ["am"] = "ɑm", ["acm"] = "ɤm", ["om"] = "om", ["um"] = "um",
	
	["in"] = "ĩ", ["en"] = "ẽ", ["an"] = "ɑn", ["on"] = "on", ["un"] = "un",
	["aen"] = "ɛ̃", ["oen"] = "ø̃", ["uen"] = "ỹ",

	["ing"] = "iŋ", ["eng"] = "eŋ", ["ang"] = "ɑŋ", ["acng"] = "ɤŋ", ["ong"] = "oŋ", ["ung"] = "uŋ",
	
	["ib"] = "ip̚", ["eb"] = "ep̚", ["ab"] = "ɑp̚", ["acb"] = "ɤp̚", ["ob"] = "op̚", ["ub"] = "up̚",
	
	["ig"] = "iʰ(k̚)ˀ", ["eg"] = "eʰ(k̚)ˀ", ["acg"] = "ɤʰ(k̚)ˀ", ["ag"] = "ɑʰ(k̚)ˀ", ["og"] = "oʰ(k̚)ˀ", ["ug"] = "uʰ(k̚)ˀ",
	
	["ir"] = "iː(ɹ)", ["er"] = "eː(ɹ)", ["ar"] = "ɑː(ɹ)", ["or"] = "oː(ɹ)", ["ur"] = "uː(ɹ)",
}

local tConv = {
	["f"] = "˥˥",
	["h"] = "˥˩",
	["v"] = "˩˧",
	["w"] = "˩˧˨",
	[""] = "ˑ",
}

function export.ipa(text)
	text = mw.ustring.lower(text)
	for word in mw.ustring.gmatch(text, "([a-z]+)") do
		local originalWord = word
		word = gsub(word, "^([^aeiou]*)([aeiou][aeioucmnbgr]*)([fhvw]?)$", function(initial, final, tone)
			return (iConv[initial] or initial) .. (fConv[final] or final) .. tConv[tone] end)
		text = gsub(text, originalWord, word, 1)
	end
	text = gsub(text, "-", ".")
	return text
end

function ipaFormat(word, no_intro)
	local part = mw.text.split(word, ",")
	return (no_intro and "" or "[[Wiktionary:國際音標|國際音標]]<sup>([[附錄:藏文讀音|解]])</sup>:") .. 
		'<span class=\"IPA\">/' .. table.concat(part, "/, /") .. '/</span>'
end

function export.show(frame)
	local args = frame:getParent().args
	local p, ipa, textShow, textHide = {}, {}, "", ""
	
	if args["otb"] ~= "-" then
		local otb_ipa = {}
		local m_translit = require("Module:bo-translit")
		local page_title = m_translit.tr(args["word"] or mw.title.getCurrentTitle().text)
		if page_title then
			local single_letter = {
				["kh"] = "ġ", ["ch"] = "ċ", ["th"] = "ṫ", ["ph"] = "ṗ",
				["ng"] = "ŋ", ["ny"] = "ñ",
				["ts"] = "ʒ", ["dz"] = "ž",
				["zh"] = "ż", ["sh"] = "ṡ"
			}
			
			local voiceless_lateral = {
				["lh"] = "ĺ", ["hr"] = "ŕ"
			}
			
			local function voice(text)
				return match(text, "[kġcċtṫpṗʒǯṡshĺŕ]") and "voiceless" or "voiced"
			end
			
			local base_ipa = {
				["g"] = "ɡ", ["ġ"] = "kʰ",
				["c"] = "t͡ɕ", ["ċ"] = "t͡ɕʰ", ["j"] = "d͡ʑ", ["ñ"] = "ȵ",
				["ṫ"] = "tʰ",
				["ṗ"] = "pʰ",
				["ʒ"] = "t͡s", ["ǯ"] = "t͡sʰ", ["ž"] = "d͡z",
				["ż"] = "ʑ", ["'"] = "ɣ",
				["y"] = "j", 
				["ṡ"] = "ɕ",
				["ĺ"] = "l̥", ["ŕ"] = "r̥"
			}
			
			local syllable_structure = "^(b?)([dkgbmz'srl]?)(%.?)([kġgŋcċjñtṫdnpṗbmʒǯžwżz'yrlṡshĺŕʔ])([yr]?)(w?)([aeiouI])([gdbŋnms'rl]?)([sd]?)$"
			local voicing = { ["s"] = "z" }
			local devoicing = { ["b"] = "p", ["d"] = "t", ["g"] = "k" }
				
			local function initial_process(prefix, superscript, base)
				local prenasal = { ["kġgŋ"] = "ᵑ", ["cċjñtṫdnʒǯžwżz'yrlṡshĺŕʔ"] = "ⁿ", ["pṗbm"] = "ᵐ" }
				if superscript == "'" then
					for ensuing, nasal in pairs(prenasal) do
						superscript = match(base, "[" .. ensuing .. "]") and nasal or superscript
					end
				end
				return gsub(prefix .. superscript, ".", (voice(base) == "voiced" and voicing or devoicing)) .. (base_ipa[base] or base)
			end
			
			local function vowel_process(glide_a, glide_b, vowel, sep)
				local glide_ipa = { ["y"] = "ʲ", ["w"] = "ʷ" }
				local glide_sep_ipa = { ["y"] = "j", ["w"] = "ʷ" }
				local vowel_ipa = { ["I"] = "ᵻ" }
				return gsub(gsub(glide_a .. glide_b, ".", sep ~= "." and glide_ipa or glide_sep_ipa), "rʷ", "ʷr") .. gsub(vowel, ".", vowel_ipa)
			end
			
			local function coda_process(coda, suffix)
				coda = gsub(coda, "'", "(ɣ)")
				return (devoicing[coda] or coda) .. suffix
			end
			
			page_title = gsub(page_title, "tsh", "ǯ")
			for original, replaced in pairs(single_letter) do
				page_title = gsub(page_title, original, replaced)
			end
			page_title = gsub(page_title, "[lh][hr]", voiceless_lateral)
			
			for syllable in mw.text.gsplit(page_title, " ") do
				syllable = gsub(syllable, "^([aeiouI])", "ʔ%1")
				
				if match(syllable, syllable_structure) then
					syllable = gsub(syllable, syllable_structure, function(prefix, superscript, sep, base, glide_a, glide_b, vowel, coda, suffix)
						if match(base, "[yrw]") and glide_a .. glide_b == "" and prefix .. superscript ~= "" then
							glide_a, glide_b = match(base, "[yr]") or "", match(base, "w") or ""
							base = prefix .. superscript
							prefix, superscript = "", ""
						end
						return
							initial_process(prefix, superscript, base) ..
							vowel_process(glide_a, glide_b, vowel, sep) ..
							coda_process(coda, suffix)
						end)
					
					table.insert(otb_ipa, syllable)
				else
					erroneous = true
					break
				end
			end
			textShow = textShow .. "\n* [[w:zh:中古藏語|中古藏文]]:" .. ipaFormat("*" .. table.concat(otb_ipa, "."), true)
			textHide = textHide .. (not erroneous and "* [[w:zh:中古藏語|中古藏文]]:\n** " .. ipaFormat("*" .. table.concat(otb_ipa, ".")) .. " <span style=\"font-size:80%\">(重建)</span>" or "")
		end
	end
	
	if args[1] then
		for index, item in ipairs(args) do
			table.insert(p, (item ~= "") and item or nil)
		end
		for _, transcription in ipairs(p) do
			table.insert(ipa, export.ipa(transcription))
		end
		textShow = textShow .. "\n* [[w:藏文|拉薩]]:" .. ipaFormat(table.concat(ipa, ","), true)
		textHide = textHide .. "\n* [[w:中部藏文|衛藏]]" ..
			"\n** [[w:zh:藏語拼音|藏文拼音]]:<span class=\"tr\"><tt>" .. export.tidyRom(table.concat(p, ", ")) .. "</tt></span>" ..
			"\n** ([[w:藏文|拉薩]]) " .. ipaFormat(table.concat(ipa, ","))
	end

	if args["batang"] or args["dege"] then
		textHide = textHide .. "\n* [[w:zh:康巴語|康]]"
		if args["batang"] then
			textShow = textShow .. "\n* [[w:zh:巴塘縣|巴塘]]:" .. ipaFormat(args["batang"], true)
			textHide = textHide .. "\n** ([[w:zh:巴塘縣|巴塘]]) " .. ipaFormat(args["batang"])
		end
		if args["dege"] then
			textShow = textShow .. "\n* [[w:zh:德格縣|德格]]:" .. ipaFormat(args["dege"], true)
			textHide = textHide .. "\n** ([[w:zh:德格縣|德格]]) " .. ipaFormat(args["dege"])
		end
	end
	
	if args["zeku"] or args["labrang"] then
		textHide = textHide .. "\n* [[w:zh:安多語|安多]]"
		if args["zeku"] then
			textShow = textShow .. "\n* [[w:zh:澤庫縣|澤庫]]:" .. ipaFormat(args["zeku"], true)
			textHide = textHide .. "\n** ([[w:zh:澤庫縣|澤庫]]) " .. ipaFormat(args["zeku"])
		end
		if args["labrang"] then
			textShow = textShow .. "\n* [[w:zh:夏河縣|拉卜楞]]:" .. ipaFormat(args["labrang"], true)
			textHide = textHide .. "\n** ([[w:zh:夏河縣|拉卜楞]]) " .. ipaFormat(args["labrang"])
		end
	end

	if args["spiti"] then
		textShow = textShow .. "\n* [[w:zh:拉胡爾-斯皮提語|拉胡爾-斯皮提]]:" .. ipaFormat(args["spiti"], true)
		textHide = textHide .. "\n* [[w:zh:拉胡爾-斯皮提語|拉胡爾-斯皮提]]"
		textHide = textHide .. "\n** ([[w:zh:拉胡爾和斯皮提縣|斯皮提]]) " .. ipaFormat(args["spiti"])
	end
	
	
	
	return '<div class="toccolours mw-collapsible mw-collapsed" style="width:400px; font-size:100%">' .. textShow ..
	'\n<div class="mw-collapsible-content">\n----\n' .. textHide .. '</div></div>'
end

return export