Module:gan-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ʰ", ["m"] = "m", ["f"] = "f", ["d"] = "t", ["t"] = "tʰ", ["l"] = "l", ["z"] = "t͡s", ["c"] = "t͡sʰ", ["s"] = "s", ["j"] = "t͡ɕ", ["q"] = "t͡ɕʰ", ["x"] = "ɕ", ["ny"] = "n̠ʲ", ["g"] = "k", ["k"] = "kʰ", ["ng"] = "ŋ", ["h"] = "h", [""] = "" }

local finalConv = { ["z"] = "z̩", ["i"] = "i", ["u"] = "u", ["y"] = "y", ["a"] = "a", ["ia"] = "ia", ["ua"] = "ua", ["o"] = "o", ["uo"] = "uo", ["e"] = "e", ["ie"] = "ie", ["ue"] = "ue", ["ye"] = "ye", ["eo"] = "ɵ", ["ai"] = "ai", ["uai"] = "uai", ["oi"] = "oi", ["ei"] = "ei", ["ii"] = "ɨi", ["ui"] = "ui", ["au"] = "au", ["eu"] = "ɛu", ["ieu"] = "iɛu", ["iu"] = "iu", ["iiu"] = "ɨu", ["an"] = "an", ["uan"] = "uan", ["on"] = "ɵn", ["uon"] = "uɵn", ["yon"] = "yɵn", ["en"] = "ɛn", ["ien"] = "iɛn", ["in"] = "in", ["iin"] = "ɨn", ["un"] = "un", ["yn"] = "yn", ["ang"] = "aŋ", ["iang"] = "iaŋ", ["uang"] = "uaŋ", ["ong"] = "ɔŋ", ["iong"] = "iɔŋ", ["uong"] = "uɔŋ", ["ung"] = "uŋ", ["iung"] = "iuŋ", ["at"] = "at̚", ["uat"] = "uat̚", ["ot"] = "ɵt̚", ["uot"] = "uɵt̚", ["yot"] = "yɵt̚", ["et"] = "ɛt̚", ["iet"] = "iɛt̚", ["uet"] = "uɛt̚", ["it"] = "it̚", ["iit"] = "ɨt̚", ["ut"] = "ut̚", ["yt"] = "yt̚", ["ah"] = "aʔ", ["iah"] = "iaʔ", ["uah"] = "uaʔ", ["oh"] = "ɔʔ", ["ioh"] = "iɔʔ", ["uoh"] = "uɔʔ", ["uh"] = "uʔ", ["iuh"] = "iuʔ", ["m"] = "m̩", ["n"] = "n̩", ["ng"] = "ŋ̍" }

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

function export.ipa(text) if type(text) == "table" then text = text.args[1] end local syllables, stress, initial, final, tone, ipa, result = {}, {}, {}, {}, {}, {}, {} local has_stress, has_neutral, attention = false, false, "" local words = mw.text.split(text, "/") for _, word in ipairs(words) do		syllables = mw.text.split(word, " ") for index, syllable in ipairs(syllables) do			stress[index] = match(syllable, "^'") and "ˈ" or "" has_stress = has_stress or stress[index] == "ˈ" syllable = gsub(syllable, "^'", "") initial[index] = match(syllable, "^[bpmfdtlnzcsjqxgkh]?[gy]?") if match(initial[index], "^.y$") and initial[index] ~= "ny" then initial[index] = sub(initial[index], 1, 1) end initial[index] = initial[index] == "y" and "" or initial[index] final[index] = match(sub(syllable, len(initial[index]) + 1, -1), "^[^1-8%*]*") if final[index] == "" then final[index] = initial[index] initial[index] = "" end tone[index] = match(syllable, "[1-7]+$") or (index ~= 1 and "8" or "") has_neutral = has_neutral or tone[index] == "8" -- checks validity of the syllable local aspirated = match(initial[index], "^[ptcqkh]$") local checked = match(final[index], "[th]$") if tone[index] == "2" and not aspirated then error("The 2nd tone can only go with aspirated initials. Use the 4th tone instead.") elseif tone[index] == "4" and aspirated then error("The 4th tone can only go with unaspirated initials. Use the 2nd tone instead.") elseif match(tone[index], "^[67]$") and not checked then error(string.format("Tone %s can only go with checked finals.", tone[index])) elseif match(tone[index], "^[12345]$") and checked then error(string.format("Tone %s cannot go with a checked final.", tone[index])) end end for index = 1, #syllables do			initial[index] = initialConv[initial[index]] or error(("Unrecognised initial: \"%s\""):format(initial[index])) final[index] = (match(initial[index], "s") and final[index] == "i") and "z" or final[index] final[index] = (initial[index] == "f" and final[index] == "i") and "ii" or final[index] final[index] = (match(initial[index], "s") and final[index] == "iu") and "iiu" or final[index] final[index] = finalConv[final[index]] or error(("Unrecognised final: \"%s\""):format(final[index])) if tone[index] == "3" then if match(tone[index+1] or "", "[1246]") then tone[index] = "3-1" elseif match(tone[index+1] or "", "[357]") then tone[index] = "3-2" elseif tone[index+1] then -- tone[index+1] == "8" tone[index] = "3-3" end elseif tone[index] == "8" then if tone[index-1] == "²¹³⁻²¹" or tone[index-1] == "¹¹" or tone[index-1] == "²" then tone[index] = "8-1" else tone[index] = "8-2" end end tone[index] = toneConv[tone[index]] or error(("Unrecognised tone: \"%s\""):format(tone[index])) ipa[index] = stress[index] .. initial[index] .. final[index] .. tone[index] end table.insert(result, table.concat(ipa, " ")) end -- check for stress if needed if #syllables > 1 and not has_neutral and not has_stress then attention = "" end return table.concat(result, "/, /") .. attention end

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

return export