Module:hak-pron

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

local gsub = m_string_utils.gsub local sub = mw.ustring.sub local match = m_string_utils.match local find = m_string_utils.find local len = m_string_utils.len local lower = m_string_utils.lower local toNFD = mw.ustring.toNFD

function export.rom_display(text,convtype) if type(text) == 'table' then text,convtype = text.args[1],(text.args[2] or '') end local display = '' local show = { ['pfs'] = , ['gd'] =  } local decomp = mw.text.split(gsub(text,'/',' / '),';',true) local TableTools = require('Module:table') for i = 1,#decomp,1 do		if match(decomp[i],'pfs') then decomp[i] = gsub(decomp[i],'pfs=','') local pfs_readings = { ['n'] = {}, ['s'] = {} } local hrs_readings = { ['n'] = {}, ['s'] = {} } local hpy_readings = { ['n'] = {}, ['s'] = {} } local ipa_readings = { ['n'] = {}, ['s'] = {} } local function display_format(style) local label = { ['n'] = 'Northern ', ['s'] = 'Southern ', ['ns'] = '' } local city = { ['n']	= 'Miaoli', ['s']	= 'Meinong', ['ns']	= 'Miaoli and Meinong' }				local text = string.format("\n** (%sSixian, incl. %s) ", label[style], city[style]) text = text .. "\n*** Pha̍k-fa-sṳ : " .. table.concat(pfs_readings[style:sub(1,1)], ' / ') .. ' '				text = text .. "\n*** Hakka Romanization System : " .. table.concat(hrs_readings[style:sub(1,1)], ' / ') .. ' '				text = text .. "\n*** Hagfa Pinyim : " .. table.concat(hpy_readings[style:sub(1,1)], ' / ') .. ' '				local ipa = '\n*** Sinological IPA' local span = ' : /' text = text .. ipa if style == 'ns' then local north = table.concat(ipa_readings['n'], '/, /') local south = table.concat(ipa_readings['s'], '/, /') if north == south then text = text .. span .. north .. '/ '					else text = text .. " (Northern, incl. " .. city['n'] .. ")" .. span .. north .. "/ "						text = text .. ipa .. " (Southern, incl. " .. city['s'] .. ")" .. span .. south .. "/ "					end else text = text .. span .. table.concat(ipa_readings[style], '/, /') .. '/ '				end return text end local function southern(text) local function convert(a, b, c)					local e_a = { ['e'] = 'a', ['ê'] = 'â', ['é'] = 'á', ['è'] = 'à' } return a .. e_a[b] .. c				end text = gsub(text, '([yY])([eéèê])(̍?[nt])', convert) text = gsub(text, '([nN]gi)([eéèê])(̍?[nt])', convert) text = gsub(text, '([kK]h?i)([eéèê])(̍?[nt])', convert) text = gsub(text, '^([hH]i)([eéèê])(̍?[nt])', convert) text = gsub(text, '([%-%s][hH]i)([eéèê])(̍?[nt])', convert) return text end local function add(style, reading) pfs_readings[style][#pfs_readings[style] + 1] = reading hrs_readings[style][#hrs_readings[style] + 1] = export.hrs(reading, style) hpy_readings[style][#hpy_readings[style] + 1] = export.pfs_to_hpy(reading) ipa_readings[style][#ipa_readings[style] + 1] = export.ipa(reading, style) end local ns = true for _, reading in ipairs(mw.text.split(decomp[i], ' / ')) do				if match(reading,':') then local pair = mw.text.split(reading, ':') if pair[1] == 'ns' then add('n', pair[2]) add('s', pair[2]) else ns = false add(pair[1], pair[2]) end elseif match(reading,'[yY]') or reading ~= southern(reading) then ns = false add('n', reading) add('s', southern(reading)) else add('n', reading) add('s', reading) end end if convtype == '' then if ns then display = display .. display_format('ns') else if #pfs_readings['n'] ~= 0 then display = display .. display_format('n') end if #pfs_readings['s'] ~= 0 then display = display .. display_format('s') end end else for i, reading in ipairs(pfs_readings['s']) do					pfs_readings['n'][#pfs_readings['n'] + 1] = pfs_readings['s'][i] end show['pfs'] = table.concat(TableTools.removeDuplicates(pfs_readings['n']), ' / ') end end if match(decomp[i],'gd') then if convtype == '' then display = display .. "\n** (Meixian) " display = display .. "\n*** Guangdong : " .. gsub(gsub(decomp[i],'gd=',''),'([1-6])','%1') .. ' '				display = display .. '\n*** Sinological IPA : /' .. export.gd_to_ipa(decomp[i]) .. "/ "			else show['gd'] = gsub(gsub(decomp[i], 'gd=', ''), '([1-6])', '%1') end end end if convtype ~= '' then local pfs = " (Sixian, PFS) : " .. show['pfs'] .. ' '		local gd = " (Meixian, Guangdong) : " .. show['gd'] .. ' '		if show['pfs'] ~=  and show['gd'] ~=  then display = display .. '\n*:' .. pfs .. '\n*:' .. gd		elseif show['pfs'] ~= '' then display = display .. pfs elseif show['gd'] ~= '' then display = display .. gd		end end return display end

local function find_tone(text) text = toNFD(text) if find(text, '̂') then return 1 elseif find(text, '̀') then return 2 elseif find(text, '́') then return 3 elseif find(text, '̍') then return 6 elseif find(text, '[^n][ptkbdg]$') then return 5 else return 4 end end

function export.ipa(text, dialect) local syllables, initial, final, tone, tone_conv = {}, {}, {}, {}, {} local ipa = {} if type(text) == 'table' then text = text.args[1] end text = gsub(gsub(gsub(lower(text), '%.', ), '%s+$', ), '%s+', '-') syllables = mw.text.split(text, "-") for i, syllable in ipairs(syllables) do		syllable = gsub(syllable, ",", "") syllable = gsub(syllable,'o̍[ae]',{['o̍a']='ua̍',['o̍e']='ue̍'}) syllable = gsub(syllable,'[oóòôō][ae]',{['oa']='ua',['óa']='uá',['òa']='uà',['ôa']='uâ',['ōa']='uā',['oe']='ue',['óe']='ué',['òe']='uè',['ôe']='uê',['ōe']='uē'}) initial[i] = match(syllable, '^[mnptkcfvshyl]?[gh]?h?') final[i] = sub(syllable, len(initial[i]) + 1, -1) local initial_ipa = { ['ng'] = 'ŋ', ['ph'] = 'pʰ', ['th'] = 'tʰ', ['kh'] = 'kʰ', ['ch'] = 't͡s', ['chh'] = 't͡sʰ', ['y'] = 'i'		} initial[i] = initial_ipa[initial[i]] or initial[i] tone[i] = find_tone(final[i]) local final_conv = { ['á'] = 'a', ['é'] = 'e', ['í'] = 'i', ['ó'] = 'o', ['ú'] = 'u', ['́'] = '', ['à'] = 'a', ['è'] = 'e', ['ì'] = 'i', ['ò'] = 'o', ['ù'] = 'u', ['̀'] = '', ['â'] = 'a', ['ê'] = 'e', ['î'] = 'i', ['ô'] = 'o', ['û'] = 'u', ['̂'] = '', ['ń'] = 'n', ['ǹ'] = 'n', ['̍'] = '',			['ṳ'] = 'ɨ', }		final[i] = gsub(final[i], '[âêîôû̂àèìòù̀áéíóú́ńǹ̍ṳ]', final_conv) if initial[i] == 'i' then final[i] = (find(final[i], '^i[mnpt]?$') and '' or 'i') .. final[i] initial[i] = dialect == 's' and '(j)' or '' end final[i] = gsub(final[i], '([ptk])$', '%1̚') final[i] = gsub(final[i], 'ng$', 'ŋ') final[i] = final[i] == 'ŋ' and 'ŋ̍' or final[i] final[i] = gsub(final[i], 'er$', 'ə') final[i] = gsub(final[i], '([aeiouɨ])([aeiouɨ])([aeiouɨ]?)', function(first, second, third)				if third ~= '' then					first = first .. '̯'					third = third .. '̯'				elseif first == 'i' or first == 'u' then					first = first .. '̯'				elseif second == 'i' or second == 'u' then					second = second .. '̯'				end			return first .. second .. third end) end for i, syllable in ipairs(syllables) do		local tone_ipa = { [1] = '²⁴',			[2] = '¹¹',			[3] = '³¹',			[4] = '⁵⁵',			[5] = '²',			[6] = '⁵',		}		tone_conv[i] = tone_ipa[tone[i]] if (tone[i] == 1 and find(tostring(tone[i+1]), '[146]') and not find(syllable, ",")) or (syllable == 'é' and dialect == 'n' and find(mw.title.getCurrentTitle.text, '仔') and find(text, '-é') and find(tostring(tone[i-1]), '[35]')) then tone_conv[i] = tone_conv[i] .. '⁻¹¹'		end ipa[i] = initial[i] .. final[i] .. tone_conv[i] end return gsub(table.concat(ipa, " "), ",", "") end

function export.hrs(text, dialect) if type(text) == 'table' then text = text.args[1] end local syllables = mw.text.split(gsub(lower(text), ' ', '-'), "-") for i, syllable in ipairs(syllables) do		-- check for commas local comma = '' if find(syllable, ',') then comma = ',' syllable = sub(syllable, 1, -2) end -- change consonants syllable = gsub(syllable,'[ptky]',{['p']='b',['t']='d',['k']='g',['y']=dialect == 's' and '(r)i' or 'i'}) syllable = gsub(syllable,'[bdgc]h',{['bh']='p',['dh']='t',['gh']='k',['ch']='z'}) syllable = gsub(syllable,'zh','c') local palatal = {['z']='j',['c']='q',['s']='x',['i']=''} syllable = gsub(syllable,'([zcsi])([iíìî])', function(a,b) return palatal[a]..b end) -- find tones local marks = { [1] = '´', [2] = 'ˇ', [3] = '`', [5] = '`' } local tone = marks[find_tone(syllable)] or '' -- remove tone marks and fix vowels syllable = gsub(syllable, 'ṳ', 'ii') syllable = gsub(toNFD(syllable), '[́̀̂̍]', '') syllable = gsub(syllable, 'o([ae])', 'u%1') -- add new tone marks syllables[i] = syllable .. tone .. comma end return table.concat(syllables, " ") end

function export.pfs_to_hpy(text) if type(text) == 'table' then text = text.args[1] end local syllables = mw.text.split(gsub(lower(text), ' ', '-'), "-") for i, syllable in ipairs(syllables) do		if syllable == '...' then syllables[i] = syllable else -- check for commas local comma = '' if find(syllable, ',') then comma = ',' syllable = sub(syllable, 1, -2) end -- change consonants syllable = gsub(syllable,'[ptk]',{['p']='b',['t']='d',['k']='g'}) syllable = gsub(syllable,'[bdgc]h',{['bh']='p',['dh']='t',['gh']='k',['ch']='z'}) syllable = gsub(syllable,'zh','c') local palatal = {['z']='j',['c']='q',['s']='x'} syllable = gsub(syllable,'([zcs])([iíìî])', function(a,b) return palatal[a]..b end) -- find tones local tone = find_tone(syllable) -- remove tone marks and fix vowels syllable = gsub(syllable, 'ṳ', 'i') syllable = gsub(toNFD(syllable), '[́̀̂̍]', '') syllable = gsub(syllable, 'o([ae])', 'u%1') syllable = syllable == 'yu' and 'yiu' or syllable syllable = gsub(syllable, '([iy])e([nd])', '%1a%2') -- put everything together syllables[i] = syllable .. '' .. tone .. '' .. comma end end return table.concat(syllables, " ") end

function export.gd_to_ipa(text) local initial_conv = { ["b"] = "p", ["p"] = "pʰ", ["m"] = "m", ["f"] = "f", ["v"] = "ʋ", ["d"] = "t", ["t"] = "tʰ", ["n"] = "n", ["l"] = "l", ["g"] = "k", ["k"] = "kʰ", ["ng"] = "ŋ", ["h"] = "h", ["z"] = "t͡s", ["c"] = "t͡sʰ", ["s"] = "s", ["j"] = "t͡s", ["q"] = "t͡sʰ", ["x"] = "s", [""] = "",	}	local final_conv = { ["ii"] = "z̩", ["i"] = "i", ["u"] = "u", ["a"] = "a", ["ia"] = "ia", ["ua"] = "ua", ["ê"] = "e", ["iê"] = "ie", ["uê"] = "ue", ["o"] = "o", ["io"] = "io", ["uo"] = "uo", ["m"] = "m̩", ["n"] = "n̩", ["ai"] = "aɪ", ["iai"] = "iaɪ", ["uai"] = "uaɪ", ["oi"] = "oɪ", ["ui"] = "uɪ", ["iui"] = "iuɪ", ["au"] = "au", ["iau"] = "iau", ["êu"] = "eu", ["iu"] = "iu", ["em"] = "əm", ["im"] = "im", ["am"] = "am", ["iam"] = "iam", ["êm"] = "ɛm", ["en"] = "ən", ["in"] = "in", ["an"] = "an", ["ian"] = "ian", ["uan"] = "uan", ["ên"] = "ɛn", ["iên"] = "iɛn", ["uên"] = "uɛn", ["on"] = "ɔn", ["ion"] = "iɔn", ["uon"] = "uɔn", ["un"] = "un", ["iun"] = "iun", ["ang"] = "aŋ", ["iang"] = "iaŋ", ["uang"] = "uaŋ", ["ong"] = "ɔŋ", ["iong"] = "iɔŋ", ["uong"] = "uɔŋ", ["ung"] = "ʊŋ", ["iung"] = "iʊŋ", ["eb"] = "əp̚", ["ib"] = "ip̚", ["ab"] = "ap̚", ["iab"] = "iap̚", ["êb"] = "ɛp̚", ["ed"] = "ət̚", ["id"] = "it̚", ["ad"] = "at̚", ["iad"] = "iat̚", ["uad"] = "uat̚", ["êd"] = "ɛt̚", ["iêd"] = "iɛt̚", ["uêd"] = "uɛt̚", ["od"] = "ɔt̚", ["ud"] = "ut̚", ["iud"] = "iut̚", ["ag"] = "ak̚", ["iag"] = "iak̚", ["uag"] = "uak̚", ["og"] = "ɔk̚", ["iog"] = "iɔk̚", ["uog"] = "uɔk̚", ["ug"] = "ʊk̚", ["iug"] = "iʊk̚", }	local tone_conv = { ["1"] = "⁴⁴", ["2"] = "¹¹",		["3"] = "³¹",		["4"] = "⁵³",		["5"] = "¹", ["6"] = "⁵",		["1*"] = "⁴⁴⁻³⁵",		["4*"] = "⁵³⁻⁵⁵",	}	if type(text) == 'table' then text = text.args[1] end local words = mw.text.split(text, " / ") local result = {} for _, word in ipairs(words) do		word = gsub(gsub(gsub(word, 'gd=', ), '[%.,]', ), '%s+$', '') local syllables = mw.text.split(word, '%s+') local initial, final, tone, ipa = {}, {}, {}, {} for i, syllable in ipairs(syllables) do			initial[i] = match(syllable, "^[bpmfvdtnlgkhzcsjqx]?g?") final[i] = match(sub(syllable, len(initial[i]) + 1, -1), "^[^1-6]*") if initial[i] == "" and find(final[i], "^i") then error('Syllables starting with "i" need a "y" in front.') end final[i] = gsub(gsub(final[i], "^yi", "i"), "^y", "i") if find(initial[i], "[zcs]") and final[i] == "i" then final[i] = "ii" end if final[i] == "" then final[i] = initial[i] initial[i] = "" end tone[i] = match(syllable, "[1-6]$") end for i, syllable in ipairs(syllables) do			local ortho_pal = { --orthographic palatalization ["z"] = "j", ["c"] = "q", ["s"] = "x", }			local ortho_alv = { --orthographic alveolars ["j"] = "z", ["q"] = "c", ["x"] = "s", }			if find(initial[i], "^[zcs]$") and find(final[i], "^i[^i]") then error("Initial should be " .. ortho_pal[initial[i]] .. "?") end if find(initial[i], "^[jqx]$") and find(final[i], "^[^i]") then error("Initial should be " .. ortho_alv[initial[i]] .. "?") end initial[i] = initial_conv[initial[i]] or error(("Unrecognised initial: \"%s\""):format(initial[i])) final[i] = final_conv[final[i]] or error(("Unrecognised final: \"%s\""):format(final[i])) if match(tone[i], "[14]") and match(tone[i+1] or "", "[2345]") then tone[i] = tone[i] .. "*"			end if initial[i] == "" and final[i] == "e" and tone[i] == "3" and find(mw.title.getCurrentTitle.text, '仔') then initial[i] = match(final[i-1] or '', '([mnŋpti])̚?$') or initial[i] initial[i] = find(final[i-1] or '', 'u$') and 'ʋ' or initial[i] initial[i] = find(final[i-1] or '', '[ao]$') and '(ʋ)' or initial[i] initial[i] = find(final[i-1] or '', 'e$') and '(i)' or initial[i] end tone[i] = tone_conv[tone[i]] ipa[i] = initial[i] .. final[i] .. tone[i] end table.insert(result, table.concat(ipa, " ")) end return table.concat(result, "/, /") end

return export