Module:User:Santi2222/ryu-pron

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

local lang = require("Module:languages").getByCode("ryu") local m_ryu = require("Module:ryu") local m_accent = require("Module:accent qualifier") -- also Module:qualifier

local PAGENAME = mw.title.getCurrentTitle.text

local function quote(text) return "“" .. text .. "”" end

local ref_template_name_data = { ['OJ'] = 'R:Okinawago Jiten', }

local function generate_ref_tag(ref_name) local ref_template_name = ref_template_name_data[ref_name] if not ref_template_name then -- Special:WhatLinksHere/Wiktionary:Tracking/ja-pron/unrecognized ref require("Module:debug").track("ja-pron/unrecognized ref") return nil end

local ref_tag = mw.getCurrentFrame:extensionTag{ name = 'ref', args = { name = ref_name }, content = '', }

return ref_tag end

local function add_acc_refs(text) local output = {}

if mw.ustring.match(text, 'ref') then table.insert(output, mw.getCurrentFrame:preprocess(text)) else for ref_name in mw.text.gsplit(text, '%s*,%s*') do			table.insert(output, generate_ref_tag(ref_name)) end end

return table.concat(output) end

function export.show(frame) local params = { [1] = {default = PAGENAME, list = true}, ["y"] = {alias_of = "yomi"}, ["yomi"] = {}, ["accent"] = {list = true}, ["accent=_loc"] = {list = true}, ["accent=_ref"] = {list = true}, ["accent=_note"] = {list = true}, ["acc"] = {alias_of = "accent", list = true}, ["acc=_loc"] = {alias_of = "accent_loc", list = true},	-- using "accent=_loc" (etc.) doesn't work ["acc=_ref"] = {alias_of = "accent_ref", list = true}, ["acc=_note"] = {alias_of = "accent_note", list = true}, ["noipa"] = {}, ["a"] = {alias_of = "audio"}, ["audio"] = {} }	local args = require("Module:parameters").process(frame:getParent.args, params) local yomi, au = args.yomi, args.audio local maxindex = table.getn(args[1]) local html_list_main = mw.html.create('ul') local html_list_yomi local text local yomi_types = { o = "on", on = "on", go = "goon", goon = "goon", ko = "kanon", kan = "kanon", kanon = "kanon", so = "soon", soon = "soon", to = "toon", toon = "toon", ky = "kanyoon", kanyo = "kanyoon", kanyoon = "kanyoon", k = "kun", kun = "kun", j = "ju", ju = "ju", y = "yu", yu = "yu", i = "irregular", irr = "irregular", irreg = "irregular", irregular = "irregular", }	--FIXME local yomi_text = { on = "On’yomi", goon = "On’yomi: Goon", kanon = "On’yomi: Kan’on", soon = "On’yomi: Sōon", toon = "On’yomi: Tōon", kanyoon = "Kan’yōyomi", kun = "Kun’yomi", ju = "Jūbakoyomi", yu = "Yutōyomi", irregular = require("Module:qualifier").format_qualifier("Irregular reading") }	-- Deals with the yomi if yomi then if yomi_types[yomi] then yomi = yomi_types[yomi] else error("The yomi type " .. quote(yomi) .. " is not recognized. See Template:ryu-pron/documentation for recognized types") end local kanji = mw.ustring.gsub(PAGENAME, "[^" .. require("Module:scripts").getByCode("Hani"):getCharacters .. "]+", "") if mw.ustring.len(kanji) ~= 2 and (yomi == "ju" or yomi == "yu") then require("Module:debug").track("ryu-pron/incorrect yutou or juubako") end html_list_yomi = mw.html.create('ul'):tag('li'):wikitext(yomi_text[yomi]):done:done end -- Deals with the accents local a, al, ar, an = args.accent, args.accent_loc, args.accent_ref, args.accent_note for i, position in ipairs(a) do		local result

text = args[1][math.min(maxindex,i)] if not al[i] then al[i] = "Shuri-Nara" end result = m_accent.format_qualifiers(lang, {al[i]}) .. " "		result = result .. export.accent(text, position) if ar[i] then result = result .. add_acc_refs(ar[i]) end result = result .. (an[i] and (" " .. an[i]) or "")

html_list_main:tag('li'):wikitext(			result		) end -- Deals with the IPA if not noipa then local m_IPA = require("Module:IPA") for i, text in ipairs(args[1]) do			local sortkey = m_ryu.jsort(text) html_list_main:tag('li'):wikitext(				m_IPA.format_IPA_full { lang = lang, items =, sort_key = sortkey }			) end end -- Deals with the audio if au then sortkey = m_ryu.jsort(args[1][1]) html_list_main:tag('li'):wikitext(			' '		) end return '\n' .. tostring(html_list_yomi and html_list_yomi:node(html_list_main) or html_list_main) end

function export.ipa(text) if type(text) == "table" then text = text.args[1] end

local position_mora = {} for i=1,len(text) do		if not match(sub(text,i,i), "[ ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒%.]") then if sub(text,i+1,i+1) and match(sub(text,i+1,i+1), "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]") then table.insert(position_mora, i+1) else table.insert(position_mora, i)			end end end text = m_ryu.kana_to_romaji(text, { keep_period = true }) -- canonicalize multiple spaces and remove leading and trailing spaces local function rsub(term, foo, bar) 	-- version of rsubn that discards all but the first return value local retval = gsub(term, foo, bar) return retval end local function canon_spaces(text) text = rsub(text, "%s+", " ") text = rsub(text, "^ ", "") text = rsub(text, " $", "") return text end text = canon_spaces(text) -- put # at word beginning text = "#" .. rsub(text, " ", "# #") text = gsub(text, "ー", "ː") text = gsub(text, "&#39;", "ʔ") text = gsub(text, "#([aeiou])", "#ʔ%1") text = rsub(text, "#", "")

text = gsub(text, "[ptkbjgzsdr][ptckbjgzsdr][hs]?", {		["pp"] = "p̚p", ["tch"] = "t̚ch", ["kk"] = "k̚k", ["bb"] = "b̚b̥", ["jj"] = "d̚j",		["dd"] = "d̚d", ["gg"] = "g̚g", ["zz"] = "zː", ["tt"] = "t̚t", ["tts"] = "t̚ts",		["rr"] = "r̚r", ["ssh"] = "ɕː", ["ss"] = "sː"}) --FIXME does Okinawan have double consonants? text = gsub(text, "[āēīōūfjry]", {		["ā"] = "aː", ["ē"] = "eː", ["ī"] = "iː", ["ō"] = "oː", ["ū"] = "uː", 		["f"] = "ɸ", ["j"] = "d͡ʑ", ["r"] = "ɾ", ["y"] = "j"}) text = gsub(text, "[sct][hs]", {		["sh"] = "ɕ", 		["ch"] = "t͡ɕ", 		["ts"] = "t͡s" }) text = gsub(text, "([aeiouː])d͡([zʑ])", "%1%2") --FIXME text = gsub(text, "([ʔkgnmɾ])j", "%1ʲ") text = gsub(text, "([ʔkg])w", "%1ʷ") text = gsub(text, "nʲ", "ɲ̟") text = gsub(text, "hʲ", "ç") for i, args in pairs{ { "n( ?)([pbmɸ])", "m̩%1%2" }, { "n( ?)([ntdszɾɕ])", "n̩%1%2"}, { "n( ?)([jçɲ])̟", "ɲ̩%1%2" }, { "n( ?)([kgwhʔ])", "ŋ̍%1%2" }, { "n'", "ŋ̍" }, { "(ː?)n$", "%1ŋ̍" }, } do		text = gsub(text, args[1], args[2]) end text = gsub(text, "h([çɸ])", "%1%1") text = gsub(text, "([snhçɸmɾjw])%1", "%1ː") text = gsub(text, "ːʲ", "ʲː") text = gsub(text, "̚(.[̥̊]?)ʲ", "̚ʲ%1ʲ") text = gsub(text, "%.", "") text = gsub(text, "'", ".") text = gsub(text, "g", "ɡ") return text end

function export.rise_and_fall(word, rftype) word = m_ryu.kana_to_romaji(word)

if rftype == "rise" then word = gsub(word, ".", {			["a"] = "á", ["e"] = "é", ["i"] = "í", ["o"] = "ó", ["u"] = "ú", 			["ā"] = "áá", ["ē"] = "éé", ["ī"] = "íí", ["ō"] = "óó", ["ū"] = "úú" }) word = gsub(gsub(word, "n([bcdfghjkmnprstvw%'z ])", "ń%1"), "n$", "ń") elseif rftype == "fall" then word = gsub(word, ".", {			["a"] = "à", ["e"] = "è", ["i"] = "ì", ["o"] = "ò", ["u"] = "ù", 			["ā"] = "àà", ["ē"] = "èè", ["ī"] = "ìì", ["ō"] = "òò", ["ū"] = "ùù" }) word = gsub(gsub(word, "n([bcdfghjkmnprstvw%'z ])", "ǹ%1"), "n$", "ǹ") else return error("Type not recognised.") end return word end

-- Module:ja-ojad and Module:ja-infl-demo rely on the output format of this function function export.accent(text, class) local result

if(type(text)) == "table" then text, class = text.args[1], text.args[2] end text = gsub(text, "([おこごそぞとどのほぼぽもよろぉょオコゴソゾトドノホボポモヨロォョ])[うウ]", "%1ー") text = gsub(text, "([えけげせぜてでねへべぺめれゑぇエケゲセゼテデネヘベペメレェ])[いイ]", "%1ー") text = gsub(text, "%.", "") local down_first = "" local down_last = "&#8203; " local high_first = "" local start = "" local romaji_start = "  [" local romaji_last = "] " local last = " " local position_kana = {}      --position of each kana (ぁ counted), text without space local position_mora = {}      --position of each mora (ぁ not counted), text without space local position_mora_space = {} --position of each mora (ぁ not counted), text with space for i=1,mw.ustring.len(text) do		if not mw.ustring.match(sub(text,i,i), "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒 ]") then local extra = mw.ustring.len(mw.ustring.match(sub(text,i+1), "^[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]*")) table.insert(position_mora_space, i+extra) end end local space_removed = mw.ustring.gsub(text," ","") for i=1,mw.ustring.len(space_removed) do		table.insert(position_kana, i)		if not mw.ustring.match(sub(space_removed,i,i), "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]") then local extra = mw.ustring.len(mw.ustring.match(sub(space_removed,i+1), "^[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]*")) table.insert(position_mora, i+extra) end end if match(class, "^[h0]$") then acc_type, acc_number = "h", 0 elseif match(class, "^[a1]$") then acc_type, acc_number = "a", 1 elseif match(class, "^o$") then acc_type = "o" end if match(class, "^[0-9]+$") and not match(class,"^[01]$") then class = gsub(class, "[on]", "") acc_number = tonumber(class) morae_count = len(gsub(text, "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒 ]", "")) if morae_count == acc_number then acc_type = "o" elseif morae_count < acc_number then return error(("Mora count (%d) is smaller than position of downstep mora (%d).")				:format(morae_count, acc_number)) else acc_type = "n" end elseif not acc_number then acc_number = class end local start_index = 1 while match(sub(text, start_index+1, start_index+1), "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]") do		start_index = start_index + 1 end local kanas = {} local single_mora for i=1,mw.ustring.len(text) do		if not mw.ustring.match(sub(text,i,i), "[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒 ]") then single_mora = gsub(sub(text, i, -1), "^(.[ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ𛅑𛅐𛅒]*).*", "%1") table.insert(kanas, single_mora) end end romaji_text = gsub(text, "([おこそとのほもよろをごぞどぼぽょぉオコソトノホモヨロヲゴゾドボポョォ])ー", "%1お") romaji_text = gsub(romaji_text, "([えけせてねへめれゑげぜでべぺぇエケセテネヘメレヱゲゼデベペェ])ー", "%1え") romaji_text = gsub(romaji_text, "([うくすつぬふむゆるぐずづぶぷゅうウクスツヌフムユルグズヅブプュゥゔヴ])ー", "%1う") romaji_text = gsub(romaji_text, "([いきしちにひみりゐぎじぢびぴぃイキシチニヒミリヰギジヂビピィ])ー", "%1い") romaji_text = gsub(romaji_text, "([あかさたなはまやらわんがざだばぱゃぁアカサタナハマヤラワンガザダバパャァ])ー", "%1あ") local romajis = mw.text.split(romaji_text, "") local function count_nspaces(text, index) local i, sample, nspaces = 0, "", 0 while len(sample) < index do			i = i + 1 sample, nspaces = gsub(sub(text, 1, i), " ", "") end return nspaces end if acc_type == "n" then r_start_index = start_index + count_nspaces(romaji_text, start_index) local r_index = position_mora_space[acc_number] local k_index = acc_number r_parts = { [1] = table.concat(romajis, "", 1, r_start_index), [2] = table.concat(romajis, "", r_start_index + 1, r_index), [3] = table.concat(romajis, "", r_index + 1, #romajis) }		k_parts = { [1] = table.concat(kanas, "", 1, 1), [2] = table.concat(kanas, "", 2, k_index), [3] = table.concat(kanas, "", k_index + 1, #kanas) }		result = start .. k_parts[1] .. down_first .. k_parts[2] .. down_last .. k_parts[3] .. last .. romaji_start .. export.rise_and_fall(r_parts[1], "fall") .. export.rise_and_fall(r_parts[2], "rise") .. "ꜜ" .. export.rise_and_fall(r_parts[3], "fall") .. romaji_last .. "(Nakadaka – [" .. acc_number .. "])" else r_start_index = start_index + count_nspaces(romaji_text, start_index) r_parts = { [1] = table.concat(romajis, "", 1, r_start_index), [2] = table.concat(romajis, "", r_start_index + 1, #romajis) }		k_parts = { [1] = table.concat(kanas, "", 1, 1), [2] = table.concat(kanas, "", 2, #kanas) }		if acc_type == "h" then result = start .. k_parts[1] .. high_first .. k_parts[2] .. last .. last .. romaji_start .. export.rise_and_fall(r_parts[1], "fall") .. export.rise_and_fall(r_parts[2], "rise") .. romaji_last .. "(Heiban – [" .. acc_number .. "])" elseif acc_type == "a" then result = start .. down_first .. k_parts[1] .. down_last .. k_parts[2] .. last .. romaji_start .. export.rise_and_fall(r_parts[1], "rise") .. "ꜜ" .. export.rise_and_fall(r_parts[2], "fall") .. romaji_last .. "(Atamadaka – [" .. acc_number .. "])" elseif acc_type == "o" then result = start .. k_parts[1] .. down_first .. k_parts[2] .. down_last .. last .. romaji_start .. export.rise_and_fall(r_parts[1], "fall") .. export.rise_and_fall(r_parts[2], "rise") .. "ꜜ" .. romaji_last .. "(Odaka – [" .. acc_number .. "])" else return error("Accent type not recognised.") end end result = gsub(result, "(.)̥", " %1 ") return result end

return export