模組:nan-pron-Hainan

可在模組:nan-pron-Hainan/doc建立此模組的說明文件

local export = {}

local gsub = mw.ustring.gsub
local sub = mw.ustring.sub
local len = mw.ustring.len
local match = mw.ustring.match
local split = mw.text.split
local gsplit = mw.text.gsplit

local initial_ipa = {
	["b"] = "ɓ", ["p"] = "pʰ", ["m"] = "m", ["v"] = "b",
	["d"] = "t", ["dd"] = "ɗ", ["dh"] = "d", ["n"] = "n", ["l"] = "l",
	["g"] = "k", ["gh"] = "ɡ", ["ng"] = "ŋ", ["h"] = "x", ["hh"] = "ɦ",
	["z"] = "t͡ɕ", ["s"] = "s", ["y"] = "d͡ʑ",
	[""] = "ʔ"
}

local final_ipa = {
	["i"] = "i", ["u"] = "u",
	["a"] = "a", ["ia"] = "ia", ["ua"] = "ua",
	["o"] = "o", ["io"] = "io",
	["e"] = "e", ["ue"] = "ue",
	["ai"] = "ai", ["uai"] = "uai",
	["oi"] = "oi", ["ui"] = "ui",
	["ao"] = "au", ["iao"] = "iau",
	["ou"] = "ou", ["iu"] = "iu",
	["am"] = "am", ["iam"] = "iam",
	["om"] = "om", ["im"] = "iom",
	["an"] = "an", ["uan"] = "uan",
	["in"] = "ien", ["un"] = "uon",
	["ang"] = "aŋ", ["iang"] = "iaŋ", ["uang"] = "uaŋ",
	["eng"] = "eŋ",
	["ong"] = "oŋ", ["iong"] = "ioŋ",
	["ab"] = "ap", ["iab"] = "iap",
	["ob"] = "op", ["ib"] = "iop",
	["ad"] = "at", ["uad"] = "uat",
	["id"] = "iet", ["ud"] = "uot",
	["ag"] = "ak", ["iag"] = "iak", ["uag"] = "uak",
	["eg"] = "ek",
	["og"] = "ok", ["iog"] = "iok",
	["ih"] = "iʔ", ["uh"] = "uʔ",
	["ah"] = "aʔ", ["iah"] = "iaʔ", ["uah"] = "uaʔ",
	["oh"] = "oʔ", ["ioh"] = "ioʔ",
	["eh"] = "eʔ", ["ueh"] = "ueʔ",
	["oih"] = "oiʔ"
}

local tone_chao = {
	["1"] = "³³", ["2"] = "²²", ["3"] = "³¹",
	["4"] = "¹¹", ["5"] = "⁴²", ["6"] = "⁵³",
	["7A"] = "⁵", ["7B"] = "⁵³", ["8"] = "³", ["8B"] = "⁴²",
	["4S"] = "⁵⁵", ["8S"] = "¹"
}

-- find the tone of the first syllable in a two-syllable word
-- returns nil if the tone of the first syllable does not change
local function tone_sandhi(tone1, tone2)
	if (tone1 == "1") or (tone1 == "4" and match(tone2, "[67]")) or (tone1 == "6" and match(tone2, "[67]")) then
		return "5"
	elseif match(tone1, "[25]") and tone2 ~= "4" then
		return "4"
	elseif tone1 == "3" and match(tone2, "[1-48]") then
		return "6"
	elseif (tone1 == "3" and match(tone2, "[5-7]")) or (tone1 == "7" and match(tone2, "[67]")) then
		return "1"
	elseif tone1 == "4" and match(tone2, "[1-4]") then
		return "4S"
	elseif tone1 == "4" and match(tone2, "[58]") then
		return "7B"
	elseif tone1 == "8" then
		return "8S"
	end
end

-- convert Hainanese Pinyin to IPA
function export.ipa(text)
	if type(text) == "table" then
		text = text.args[1]
	end
	
	local result = {}
	
	for word in gsplit(text, "/") do
		local syllables = split(word, " ")
		local initial, final, tone, sandhi, ipa = {}, {}, {}, {}, {}
		for i, syllable in ipairs(syllables) do
			initial[i], final[i], tone[i] = match(syllable, "^([bpmvdnlghzsy]?[dhg]?)([aeiou][aeioumnbdgh]?[iomnbdgh]?g?)([1-8])$")
			if match(tone[i], "[78]") then
				tone[i] = tone[i] .. (match(final[i], "h$") and "B" or "A")
			end
		end
		for i=#syllables,1,-1 do
			if i > 1 then
				sandhi[i-1] = tone_sandhi(tone[i-1], sandhi[i] or tone[i])
			end
			actual_tone = tone_chao[tone[i]] .. (sandhi[i] and "⁻" .. tone_chao[sandhi[i]] or "")
			ipa[i] = initial_ipa[initial[i]] .. final_ipa[final[i]] .. actual_tone
		end
		table.insert(result, table.concat(ipa, " "))
	end
	
	return "/" .. table.concat(result, "/, /") .. "/"
end

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

return export