Module:Vi-pron

local export = {} local gsub = mw.ustring.gsub local sub = mw.ustring.sub local match = mw.ustring.match --àằầèềìòồờùừỳ áắấéếíóốớúứý ảẳẩẻểỉỏổởủửỷ ãẵẫẽễĩõỗỡũữỹ ạặậẹệịọộợụựỵ local tone_diacritics = { ["̀"] = 2, ["́"] = 3, ["̉"] = 4, ["̃"] = 5, ["̣"] = 6 }

local tone_contour = { ["hn"] = { [1] = "˧˧", [2] = "˨˩", ["3a"] = "˧˦", [3] = "˧˦", [4] = "˧˩", [5] = "˦ˀ˥", [6] = "˧˨ʔ" }, ["hue"] = { [1] = "˧˧", [2] = "˦˩", ["3a"] = "˦˧˥", [3] = "˨˩˦", [4] = "˧˨", [5] = "˧˨", [6] = "˨˩ʔ" }, ["hcmc"] = { [1] = "˧˧", [2] = "˨˩", ["3a"] = "˦˥", [3] = "˦˥", [4] = "˨˩˦", [5] = "˨˩˦", [6] = "˨˩˨" }, }

local initial_ipa = { ["b"] = { "ʔɓ", "ʔɓ", "ʔɓ" }, ["c"] = { "k", "k", "k" }, ["ch"] = { "t͡ɕ", "t͡ɕ", "c" }, ["d"] = { "z", "j", "j" }, ["đ"] = { "ʔɗ", "ʔɗ", "ʔɗ" }, ["g"] = { "ɣ", "ɣ", "ɣ" }, ["gh"] = { "ɣ", "ɣ", "ɣ" }, ["gi"] = { "z", "j", "j" }, ["gy"] = { "z", "j", "j" }, ["h"] = { "h", "h", "h" }, ["k"] = { "k", "k", "k" }, ["kh"] = { "x", "kʰ", "kʰ" }, ["l"] = { "l", "l", "l" }, ["m"] = { "m", "m", "m" }, ["n"] = { "n", "n", "n" }, ["ng"] = { "ŋ", "ŋ", "ŋ" }, ["ngh"] = { "ŋ", "ŋ", "ŋ" }, ["nh"] = { "ɲ", "ɲ", "ɲ" }, ["p"] = { "p", "p", "p" }, -- foreign ["ph"] = { "f", "f", "f" }, ["q"] = { "k", "k", "k" }, ["qu"] = { "kw", "kw", "w" }, ["r"] = { "z", "ʐ", "ɹ" }, ["ŕ"] = { "ɹ", "ɹ", "ɹ" }, ["s"] = { "s", "ʂ", "ʂ" }, ["t"] = { "t", "t", "t" }, ["th"] = { "tʰ", "tʰ", "tʰ" }, ["tr"] = { "t͡ɕ", "ʈ", "ʈ" }, ["v"] = { "v", "v", "v" }, ["x"] = { "s", "s", "s" }, ["z"] = { "z", "z", "z" }, [""] = { "ʔ", "ʔ", "ʔ" }, ["-"] = { "", "", "" }, }

local mvi_initial_ipa = { ["ꞗ"] = "β", ["Ꞗ"] = "β", ["b"] = "ɓ", ["c"] = "k", ["ch"] = "c", ["d"] = "ð", ["đ"] = "ɗ", ["g"] = "ɣ", ["gh"] = "ɣ", ["gi"] = "ʝ", ["h"] = "h", ["k"] = "k", ["kh"] = "kʰ", ["l"] = "l", ["m"] = "m", ["n"] = "n", ["ng"] = "ŋ", ["ngh"] = "ŋ", ["nh"] = "ɲ", ["p"] = "p", ["ph"] = "pʰ", ["r"] = "ɹ", ["s"] = "ʂ", ["t"] = "t", ["th"] = "tʰ", ["tr"] = "ʈ", ["v"] = "w", ["x"] = "ɕ", }

local final_ipa = { ["a"] = { "aː", "aː", "aː" }, ["ac"] = { "aːk̚", "aːk̚", "aːk̚" }, ["ach"] = { "ajk̟̚", "at̚", "at̚" }, ["ai"] = { "aːj", "aːj", "aːj" }, ["am"] = { "aːm", "aːm", "aːm" }, ["an"] = { "aːn", "aːŋ", "aːŋ" }, ["ań"] = { "aːn", "aːn", "aːn" }, ["ang"] = { "aːŋ", "aːŋ", "aːŋ" }, ["anh"] = { "ajŋ̟", "ɛɲ", "an" }, ["ao"] = { "aːw", "aːw", "aːw" }, ["ao᷄"] = { "awŋ͡m", "", "" }, ["ap"] = { "aːp̚", "aːp̚", "aːp̚" }, ["at"] = { "aːt̚", "aːk̚", "aːk̚" }, ["au"] = { "aw", "aw", "a(ː)w" }, ["ay"] = { "aj", "aj", "a(ː)j" }, ["ăc"] = { "ak̚", "ak̚", "ak̚" }, ["ăm"] = { "am", "am", "am" }, ["ăn"] = { "an", "aŋ", "aŋ" }, ["ăng"] = { "aŋ", "aŋ", "aŋ" }, ["ăp"] = { "ap̚", "ap̚", "ap̚" }, ["ăt"] = { "at̚", "ak̚", "ak̚" }, ["â"] = { "ə", "ə", "ə" }, ["âc"] = { "ək̚", "ək̚", "ək̚" }, ["âm"] = { "əm", "əm", "əm" }, ["ân"] = { "ən", "əŋ", "əŋ" }, ["âng"] = { "əŋ", "əŋ", "əŋ" }, ["âp"] = { "əp̚", "əp̚", "əp̚" }, ["ât"] = { "ət̚", "ək̚", "ək̚" }, ["âu"] = { "əw", "əw", "əw" }, ["ây"] = { "əj", "əj", "əj" }, ["e"] = { "ɛ", "ɛ", "ɛ" }, ["ec"] = { "ɛk̚", "ɛk̚", "ɛk̚" }, ["em"] = { "ɛm", "ɛm", "ɛm" }, ["en"] = { "ɛn", "ɛŋ", "ɛŋ" }, ["eń"] = { "ɛn", "ɛn", "ɛn" }, ["eng"] = { "ɛŋ", "ɛŋ", "ɛŋ" }, ["eo"] = { "ɛw", "ɛw", "ɛw" }, ["ep"] = { "ɛp̚", "ɛp̚", "ɛp̚" }, ["et"] = { "ɛt̚", "ɛt̚", "ɛk̚" }, ["ê"] = { "e", "ej", "ej" }, ["êc"] = { "ek̚", "ek̚", "ek̚" }, ["êch"] = { "əjk̟̚", "et̚", "əːt̚" }, ["êm"] = { "em", "em", "em" }, ["ên"] = { "en", "en", "əːn" }, ["êng"] = { "eŋ", "eŋ", "eŋ" }, ["ênh"] = { "əjŋ̟", "en", "əːn" }, ["êp"] = { "ep̚", "ep̚", "ep̚" }, ["êt"] = { "et̚", "et̚", "əːt̚" }, ["êu"] = { "ew", "ew", "ew" }, ["i"] = { "i", "ɪj", "ɪj" }, ["ia"] = { "iə", "iə", "iə" }, ["ic"] = { "ïk̟̚", "ïk̟̚", "ïk̟̚" }, ["ich"] = { "ïk̟̚", "ɨt̚", "ɨt̚" }, ["iêc"] = { "iək̚", "iək̚", "iək̚" }, ["iêm"] = { "iəm", "iəm", "im" }, ["iên"] = { "iən", "iəŋ", "iəŋ" }, ["iêng"] = { "iəŋ", "iəŋ", "iəŋ" }, ["iêp"] = { "iəp̚", "iəp̚", "ip̚" }, ["iêt"] = { "iət̚", "iək̚", "iək̚" }, ["iêu"] = { "iəw", "iw", "iw" }, ["im"] = { "im", "im", "im" }, ["in"] = { "in", "in", "ɨn" }, ["inh"] = { "ïŋ", "ɨn", "ɨn" }, ["ip"] = { "ip̚", "ip̚", "ip̚" }, ["it"] = { "it̚", "it̚", "ɨt̚" }, ["iu"] = { "iw", "iw", "iw" }, ["o"] = { "ɔ", "ɔ", "ɔ" }, ["oa"] = { "waː", "waː", "waː" }, ["oac"] = { "waːk̚", "waːk̚", "waːk̚" }, ["oach"] = { "wajk̟̚", "wat̚", "wat̚" }, ["oai"] = { "waːj", "waːj", "waːj" }, ["oam"] = { "waːm", "waːm", "waːm" }, ["oan"] = { "waːn", "waːŋ", "waːŋ" }, ["oang"] = { "waːŋ", "waːŋ", "waːŋ" }, ["oanh"] = { "wajŋ̟", "wɛɲ", "wan" }, ["oao"] = { "waːw", "waːw", "waːw" }, ["oap"] = { "waːp̚", "waːp̚", "waːp̚" }, ["oat"] = { "waːt̚", "waːk̚", "waːk̚" }, ["oay"] = { "waj", "waj", "waj" }, ["oă"] = { "wa", "wa", "wa" }, ["oăc"] = { "wak̚", "wak̚", "wak̚" }, ["oăm"] = { "wam", "wam", "wam" }, ["oăn"] = { "wan", "waŋ", "waŋ" }, ["oăng"] = { "waŋ", "waŋ", "waŋ" }, ["oăt"] = { "wat̚", "wak̚", "wak̚" }, ["oc"] = { "awk͡p̚", "awk͡p̚", "awk͡p̚" }, ["oe"] = { "wɛ", "wɛ", "wɛ" }, ["oem"] = { "wɛm", "wɛm", "wɛm" }, ["oen"] = { "wɛn", "wɛŋ", "wɛŋ" }, ["oeo"] = { "wɛw", "wɛw", "wɛw" }, ["oet"] = { "wɛt̚", "wɛk̚", "wɛk̚" }, ["oi"] = { "ɔj", "ɔj", "ɔj" }, ["om"] = { "ɔm", "ɔm", "ɔm" }, ["on"] = { "ɔn", "ɔŋ", "ɔŋ" }, ["ong"] = { "awŋ͡m", "awŋ͡m", "awŋ͡m" }, ["ooc"] = { "ɔk̚", "ɔk̚", "ɔk̚" }, ["oong"] = { "ɔŋ", "ɔŋ͡m", "ɔŋ" }, ["op"] = { "ɔp̚", "ɔp̚", "ɔp̚" }, ["ot"] = { "ɔt̚", "ɔk̚", "ɔk̚" }, ["ô"] = { "o", "ow", "ow" }, ["ôc"] = { "əwk͡p̚", "əwk͡p̚", "əwk͡p̚" }, ["ôi"] = { "oj", "oj", "oj" }, ["ôm"] = { "om", "om", "om" }, ["ôn"] = { "on", "oŋ", "oŋ" }, ["ôń"] = { "on", "on", "on" }, ["ông"] = { "əwŋ͡m", "əwŋ͡m", "əwŋ͡m" }, ["ôôc"] = { "ok̚", "ok̚", "ok̚" }, ["ôông"] = { "oŋ", "oŋ", "oŋ" }, ["ôp"] = { "op̚", "op̚", "op̚" }, ["ôt"] = { "ot̚", "ok̚", "ok̚" }, ["ơ"] = { "əː", "əː", "əː" }, ["ơi"] = { "əːj", "əːj", "əːj" }, ["ơm"] = { "əːm", "əːm", "əːm" }, ["ơn"] = { "əːn", "əːŋ", "əːŋ" }, ["ơng"] = { "əːŋ", "əːŋ", "əːŋ" }, ["ơp"] = { "əːp̚", "əːp̚", "əːp̚" }, ["ơt"] = { "əːt̚", "əːk̚", "əːk̚" }, ["u"] = { "u", "ʊw", "ʊw" }, ["ua"] = { "uə", "uə", "uə" }, ["uac"] = { "waːk̚", "waːk̚", "waːk̚" }, ["uach"] = { "wajk̟̚", "wat̚", "wat̚" }, ["uai"] = { "waːj", "waːj", "waːj" }, ["uan"] = { "waːn", "waːŋ", "waːŋ" }, ["uang"] = { "waːŋ", "waːŋ", "waːŋ" }, ["uanh"] = { "wajŋ̟", "wɛɲ", "wan" }, ["uao"] = { "waːw", "waːw", "waːw" }, ["uat"] = { "waːt̚", "waːk̚", "waːk̚" }, ["uau"] = { "waw", "waw", "wa(ː)w" }, ["uay"] = { "waj", "waj", "waj" }, ["uă"] = { "wa", "wa", "wa" }, ["uăc"] = { "wak̚", "wak̚", "wak̚" }, ["uăm"] = { "wam", "wam", "wam" }, ["uăn"] = { "wan", "waŋ", "waŋ" }, ["uăng"] = { "waŋ", "waŋ", "waŋ" }, ["uăp"] = { "wap̚", "wap̚", "wap̚" }, ["uăt"] = { "wat̚", "wak̚", "wak̚" }, ["uâ"] = { "wə", "wə", "wə" }, ["uâc"] = { "wək̚", "wək̚", "wək̚" }, ["uân"] = { "wən", "wəŋ", "wəŋ" }, ["uâng"] = { "wəŋ", "wəŋ", "wəŋ" }, ["uât"] = { "wət̚", "wək̚", "wək̚" }, ["uây"] = { "wəj", "wəj", "wəj" }, ["uc"] = { "ʊwk͡p̚", "ʊwk͡p̚", "ʊwk͡p̚" }, ["ue"] = { "wɛ", "wɛ", "wɛ" }, ["uen"] = { "wɛn", "wɛŋ", "wɛŋ" }, ["ueo"] = { "wɛw", "wɛw", "wɛw" }, ["uep"] = { "wɛp̚", "wɛp̚", "wɛp̚" }, ["uet"] = { "wɛt̚", "wɛt̚", "wɛt̚" }, ["uê"] = { "we", "wej", "wej" }, ["uêch"] = { "wəjk̟̚", "wet̚", "wəːt̚" }, ["uên"] = { "wen", "wen", "wəːn" }, ["uênh"] = { "wəjŋ̟", "wen", "wəːn" }, ["uêt"] = { "wet̚", "wet̚", "wəːt̚" }, ["uêu"] = { "weu", "weu", "wew" }, ["ui"] = { "uj", "uj", "uj" }, ["uin"] = { "win", "win", "wɨn" }, ["uit"] = { "wit̚", "wit̚", "wit̚" }, ["um"] = { "um", "um", "ʊm" }, ["un"] = { "un", "un", "ʊwŋ͡m" }, ["ung"] = { "ʊwŋ͡m", "ʊwŋ͡m", "ʊwŋ͡m" }, ["unh"] = { "ujŋ̟", "un", "uwn" }, ["uô"] = { "uə", "uə", "uə" }, ["uôc"] = { "uək̚", "uək̚", "uək̚" }, ["uôi"] = { "uəj", "uj", "uj" }, ["uôm"] = { "uəm", "uəm", "uəm" }, ["uôn"] = { "uən", "uəŋ", "uəŋ" }, ["uông"] = { "uəŋ", "uəŋ", "uəŋ" }, ["uôt"] = { "uət̚", "uək̚", "uək̚" }, ["uơ"] = { "wəː", "wəː", "wəː" }, ["uơi"] = { "wəːj", "wəːj", "wəːj" }, ["uơn"] = { "uən", "wəŋ", "wəŋ" }, ["uơt"] = { "uət̚", "wək̚", "wək̚" }, ["up"] = { "up̚", "up̚", "ʊp̚" }, ["ut"] = { "ut̚", "ʊk̚", "ʊk͡p̚" }, ["uy"] = { "wi", "wɪj", "wɪj" }, ["uya"] = { "wiə", "wiə", "wiə" }, ["uych"] = { "wïk̟̚", "wɨk̟̚", "wɨt̚" }, ["uyn"] = { "win", "win", "wɨn" }, ["uich"] = { "wïk̟̚", "wɨk̟̚", "wɨt̚" }, ["uyê"] = { "wiə", "wiə", "wiə" }, ["uyên"] = { "wiən", "wiəŋ", "wiəŋ" }, ["uyênh"] = { "wiəŋ̟", "wiən", "wən" }, ["uyêt"] = { "wiət̚", "wiək̚", "wiək̚" }, ["uynh"] = { "wïŋ̟", "wɨn", "wɨn" }, ["uyp"] = { "wip̚", "wip̚", "wip̚" }, ["uyt"] = { "wit̚", "wɨt̚", "wɨt̚" }, ["uyu"] = { "wiw", "wiw", "wiw" }, ["ư"] = { "ɨ", "ɨ", "ɨ" }, ["ưa"] = { "ɨə", "ɨə", "ɨə" }, ["ưc"] = { "ɨk̚", "ɨk̚", "ɨk̚" }, ["ưi"] = { "ɨj", "ɨj", "ɨj" }, ["ưm"] = { "ɨm", "ɨm", "ɨm" }, ["ưn"] = { "ɨn", "ɨŋ", "ɨŋ" }, ["ưng"] = { "ɨŋ", "ɨŋ", "ɨŋ" }, ["ươc"] = { "ɨək̚", "ɨək̚", "ɨək̚" }, ["ươi"] = { "ɨəj", "ɨj", "ɨj" }, ["ươm"] = { "ɨəm", "ɨəm", "ɨəm" }, ["ươn"] = { "ɨən", "ɨəŋ", "ɨəŋ" }, ["ương"] = { "ɨəŋ", "ɨəŋ", "ɨəŋ" }, ["ươp"] = { "ɨəp̚", "ɨəp̚", "ɨəp̚" }, ["ươt"] = { "ɨət̚", "ɨək̚", "ɨək̚" }, ["ươu"] = { "iəw", "ɨəw", "ɨəw" }, ["ưt"] = { "ɨt̚", "ɨk̚", "ɨk̚" }, ["ưu"] = { "iw", "ɨw", "ɨw" }, ["y"] = { "i", "ɪj", "ɪj" }, ["yêc"] = { "iək̚", "iək̚", "iək̚" }, ["yêm"] = { "iəm", "iəm", "iəm" }, ["yên"] = { "iən", "iəŋ", "iəŋ" }, ["yêng"] = { "iəŋ", "iəŋ", "iəŋ" }, ["yêp"] = { "iəp̚", "iəp̚", "iəp̚" }, ["yêt"] = { "iət̚", "iək̚", "iək̚" }, ["yêu"] = { "iəw", "iw", "iw" }, }

local varieties = { ["hn"] = { "Hà Nội", 1 }, ["hue"] = { "Huế", 2 }, ["hcmc"] = { "Hồ Chí Minh City", 3 }, }

local hcmc_opt_w = { ["ch"] = true, ["d"] = true, ["l"] = true, ["s"] = true, ["t"] = true, ["th"] = true, ["tr"] = true, ["x"] = true, }

local variations = { ["hn"] = { { "^ɹ", "z" }, { " ɹ", " z" } }, ["hue"] = { { "z", "j" }, { "kʰ", "x" } }, ["hcmc"] = { { "ʂ", "s" }, { "v", "j" }, { "kʰ", "x" }, { "z", "j" } }, }

function export.ipa(frame) local p, output = {}, { ["hn"] = {}, ["hue"] = {}, ["hcmc"] = {} } local output_text = {} local pronunciations = { ["hn"] = {}, ["hue"] = {}, ["hcmc"] = {} } local pagename = gsub(gsub(mw.ustring.lower(mw.title.getCurrentTitle.subpageText), "%-", " "), "%,", "") local args = frame:getParent.args local mvi = frame.args["mvi"] or nil if args[1] then for index, item in ipairs(args) do			table.insert(p, (item ~= "") and mw.ustring.lower(gsub(gsub(item, "%-", " "), "%,", "")) or nil) end else table.insert(p, pagename) end for variety, _ in ipairs(varieties) do		table.insert(pronunciations[variety], (args[variety] ~= "") and args[variety] or nil) end for i, word in ipairs(p) do		local pronunciations = { ["hn"] = {}, ["hue"] = {}, ["hcmc"] = {} } for syllable in mw.text.gsplit(word, " ", true) do			local ipa = {} local initial, final, tone = nil, nil, nil, nil tone = 1 syllable = mw.ustring.toNFD(syllable) syllable = gsub(syllable, "([nr]́)", mw.ustring.toNFC) for diac_pattern, tone_num in pairs(tone_diacritics) do				if match(syllable, diac_pattern) then tone = tone_num break end end syllable = mw.ustring.toNFC(gsub(syllable, "[̣̀́̉̃]", "")) if syllable == "gi" or syllable == "gin" then syllable = gsub(syllable, "gi", "gii") end initial = match(syllable, "^g[ꞗꞖbcdđgklmnpqrŕstvx]+") or match(syllable, "^(g[hiy])[^cmnpt]") or match(syllable, "^g") or match(syllable, "^[ꞗꞖbcdđghklmnpqrŕstvxz]+") or "" initial = (match(syllable, "^giê.") and syllable ~= "giên") and "d" or initial initial = match(syllable, "qu$") and "qu" or initial final = sub(syllable, mw.ustring.len(initial) + 1, -1) for loc, location in pairs(varieties) do				local ipa, seq, detoned = {}, location[2], "" if mvi then if mvi_initial_ipa[initial] then table.insert(ipa, mvi_initial_ipa[initial]) else local initial_cluster = "" for cc in mw.ustring.gcodepoint(initial) do							local ch = mw.ustring.char(cc) initial_cluster = initial_cluster .. mvi_initial_ipa[ch] end table.insert(ipa, initial_cluster) end elseif initial_ipa[initial] then table.insert(ipa, initial_ipa[initial][seq]) else local initial_cluster = "" initial = gsub(initial, "r$", "ŕ") for cc in mw.ustring.gcodepoint(initial) do						local ch = mw.ustring.char(cc) initial_cluster = initial_cluster .. initial_ipa[ch][seq] end initial_cluster = gsub(initial_cluster, "([cgknpt]h)", function(digraph)						return initial_ipa[digraph][seq] end) table.insert(ipa, initial_cluster) end if final_ipa[final] then detoned = gsub(final_ipa[final][seq], "^([wu].+)", function(nucleus)						if initial .. final == "qua" then							nucleus = final_ipa["oa"][seq]						elseif initial .. final == "qui" then							nucleus = final_ipa["uy"][seq]						end						if loc == "hcmc" then							if initial == "-" then								nucleus = gsub(nucleus, "^u", "w")								end							if hcmc_opt_w[initial] then								nucleus = gsub(nucleus, "^w", "⁽ʷ⁾")							end						end						return nucleus end) table.insert(ipa, detoned) else error(("Unrecognised final: \"%s\""):format(final)) end if tone == 3 and match(final, "[chmngpt]") then tone = "3a" end table.insert(ipa, tone_contour[loc][tone]) table.insert(pronunciations[loc], table.concat(ipa, "")) end end for loc, location in pairs(varieties) do			table.insert(output[loc], table.concat(pronunciations[loc], " ")) end end for loc, location in pairs(varieties) do		if mvi then if loc == "hn" then location[1] = "Đông Kinh" end args["hue"], args["hcmc"] = "-", "-" end if args[loc] ~= "-" then if not args[loc] then args[loc] = table.concat(output[loc], "], [") local alternative = args[loc] for _, variation in ipairs(variations[loc]) do					alternative = gsub(alternative, variation[1], variation[2]) end if alternative ~= args[loc] then args[loc] = args[loc] .. "] ~ [" .. alternative end end if loc == "hcmc" then args[loc] = gsub(args[loc], "[hk]w", "w") args[loc] = gsub(args[loc], "ʔw", "(ʔ)w") end table.insert(output_text, location[2], "* (" .. location[1] .. ") " .. 				"IPA(key): [" ..					args[loc] .. "] ") end end if table.concat(p, "") ~= mw.ustring.lower(pagename) then table.insert(output_text, #output_text + 1, "* Phonetic: " .. gsub(table.concat(p, ", "), "ŕ", "R")) end return table.concat(output_text, "\n") end

return export