Module:zlw-opl-IPA

From Wiktionary, the free dictionary
Jump to navigation Jump to search


local export = {}

local m_IPA = require("Module:IPA")
local m_table = require("Module:table")
local lang = require("Module:languages").getByCode("zlw-opl")

local rsub = mw.ustring.gsub
local rlower = mw.ustring.lower
local rfind = mw.ustring.find

local consonants = "bdfɡxjkɫlmnprstvzʒʃɲɕʑʲ"
local C = "[" .. consonants .. "]"
local vowels = "aiɨuɛɔæ̃ɑ̃"
local V = "[" .. vowels .. "]"
local voiceless_consonant = "ptsʃɕkx"
local voiced_consonant = "bdzʒʑɡ"

local function track(page)
	require("Module:debug").track("zlw-opl-IPA/" .. page)
	return true
end

local function rsub_repeatedly(term, foo, bar)
	while true do
		local new_term = rsub(term, foo, bar)
		if new_term == term then
			return term
		end
		term = new_term
	end
end

local digraphs = {
	["ch"] = "x",
	["cz"] = "tʃ",
	["b́"] = "bʲ",
	["rz"] = "R",
	["sz"] = "ʃ"
}

local devoicing = {
	["b"] = "p",
	["d"] = "t",
	["z"] = "s",
	["ʒ"] = "ʃ",
	["ʑ"] = "ɕ",
	["ɡ"] = "k",
	["v"] = "f"
}

local voicing = {
	["p"] = "b",
	["t"] = "d",
	["s"] = "z",
	["ʃ"] = "ʒ",
	["ɕ"] = "ʑ",
	["k"] = "ɡ",
	["f"] = "v"
}

local function flatmap(items, fun)
	local new = {}
	for _, item in ipairs(items) do
		local results = fun(item)
		for _, result in ipairs(results) do
			table.insert(new, result)
		end
	end
	return new
end

local phon = {
	["a"] = "a",
	["ą"] = "ɑ̃",
	["b"] = "b",
	["c"] = "ts",
	["ć"] = "tɕ",
	["d"] = "d",
	["e"] = "ɛ",
	["ę"] = "æ̃",
	["f"] = "f",
	["g"] = "ɡ",
	["h"] = "x",
	["i"] = "i",
	["j"] = "j",
	["k"] = "k",
	["l"] = "lʲ",
	["ł"] = "ɫ",
	["m"] = "m",
	["ḿ"] = "mʲ",
	["n"] = "n",
	["ń"] = "ɲ",
	["o"] = "ɔ",
	["ó"] = "ɔː",
	["p"] = "p",
	["ṕ"] = "pʲ",
	["r"] = "r",
	["s"] = "s",
	["ś"] = "ɕ",
	["t"] = "t",
	["u"] = "u",
	["w"] = "v",
	["ẃ"] = "vʲ",
	["y"] = "ɨ",
	["z"] = "z",
	["ż"] = "ʒ",
	["ź"] = "ʑ",
	[":"] = "ː",
	["?"] = "(ː)"
}

function export.phonemic(text, post)
	text = rlower(text)

	text = rsub(text, " | ", "# | #")
	text = "##" .. rsub(text, " ", "# #") .. "##"

	-- basic phonology
	text = rsub(text, "ts", "tss")
	for digraph, replacement in pairs(digraphs) do
		text = rsub(text, digraph, replacement)
	end
	text = rsub(text, "r̝", "R")
	text = rsub(text, ".", phon)
	text = rsub(text, "si(" .. V .. ")", "ɕ%1")
	text = rsub(text, "zi(" .. V .. ")", "ʑ%1")
	text = rsub(text, "si", "ɕi")
	text = rsub(text, "zi", "ʑi")
	-- palatalisation
	text = rsub(text, "(" .. C .. ")i(" .. V .. ")", "%1j%2")
	text = rsub(text, "Ri(" .. V .. ")", "Rj%1")
	text = rsub(text, "ni(" .. C .. ")", "ɲi%1")
	text = rsub(text, "nʲ", "ɲ")
	text = rsub(text, "nj", "ɲ")
	text = rsub(text, "sʲ", "ɕ")
	text = rsub(text, "zʲ", "ʑ")
	text = rsub(text, "jʲ", "j")

	local function voice_backward(sound, following)
		return voicing[sound] .. following
	end

	local function devoice_backward(sound, following)
		return devoicing[sound] .. following
	end

	local function voice_forward(preceding, sound)
		return preceding .. voicing[sound]
	end

	local function devoice_forward(preceding, sound)
		return preceding .. devoicing[sound]
	end

	local function final_devoicing(sound, following)
		return devoicing[sound] .. following .. "#"
	end

	text = rsub_repeatedly(text, "([" .. voiced_consonant .. "v])([Rʲ]?)#", final_devoicing)
	text = rsub_repeatedly(text, "v([" .. voiceless_consonant .. "])", "f%1")
	text = rsub_repeatedly(text, "f([" .. voiced_consonant .. "])", "v%1")

	text = rsub_repeatedly(text, "([" .. voiced_consonant .. "])([f])", voice_forward)
	text = rsub_repeatedly(text, "([" .. voiceless_consonant .. "])([v])", devoice_forward)

	text = rsub_repeatedly(text, "([" .. voiced_consonant .. "])([" .. voiceless_consonant .. "])", devoice_backward)
	text = rsub_repeatedly(text, "([" .. voiceless_consonant .. "])([" .. voiced_consonant .. "])", voice_backward)

	-- rzy
	text = rsub(text, "Rɨ", "Ri")

	text = rsub(text, "(" .. V .. ")'", "'%1")
	text = rsub(text, "#(" .. C .. "+ʲ?)'", "#'%1")
	text = rsub(text, " (" .. C .. "+ʲ?)'", " '%1")
	text = rsub(text, "(" .. C .. "ʲ?)'", "'%1")
	text = rsub(text, "t's", "'ts")
	text = rsub(text, "'", "ˈ")
	text = rsub(text, "-", "");
	-- affricates
	text = rsub(text, "[ʃʒ]", "%1ʲ")
	-- affricates
	text = rsub(text, "t([sɕʃ])", "t͡%1")
	text = rsub(text, "d([zʑʒ])", "d͡%1")
	-- suffixes
	text = rsub(text, "^ˈ%-", "-")
	-- resolution
	text = rsub(text, "jʲ", "j")
	text = rsub(text, "ʃʲ#", "ʃ#")

	text = rsub(text, "R", "r̝")

	local variants = {text}

	local function flatmap_and_sub_pre(from, to1, to2)
		variants =
			flatmap(
			variants,
			function(item)
				if rfind(item, from) then
					local retval = {rsub_repeatedly(item, from, to1)}
					if to2 then
						m_table.insertIfNot(retval, rsub_repeatedly(item, from, to2))
					end
					return retval
				else
					return {item}
				end
			end
		)
	end

	if post ~= nil then
		flatmap_and_sub_pre("iː", "i")
		flatmap_and_sub_pre("ɨː", "ɨ")
		flatmap_and_sub_pre("uː", "u")
		flatmap_and_sub_pre("ɔː", "o")
		flatmap_and_sub_pre("ɛː", "e")
		flatmap_and_sub_pre("aː", "ɒ")
		flatmap_and_sub_pre("i%(ː%)", "i")
		flatmap_and_sub_pre("ɨ%(ː%)", "ɨ")
		flatmap_and_sub_pre("u%(ː%)", "u")
		flatmap_and_sub_pre("a%(ː%)", "a", "ɒ")
		flatmap_and_sub_pre("ɔ%(ː%)", "ɔ", "o")
		flatmap_and_sub_pre("ɛ%(ː%)", "ɛ", "e")
	end

	flatmap_and_sub_pre("#", "")

	return variants
end

function export.IPA(frame)
	local terms = {}

	local args = frame:getParent().args
	local currentTitle = mw.title.getCurrentTitle().text

	for _, term in ipairs(args) do
		if term == currentTitle then track("redundant") end
		table.insert(terms, term)
	end

	if #terms == 0 then
		terms = {currentTitle}
	end

	local results1, results2 = {}, {}

	for _, term in ipairs(terms) do
		local variantsPre = export.phonemic(term)
		for _, variant in ipairs(variantsPre) do
			table.insert(results1, {pron = "/" .. variant .. "/"})
		end
		local variantsPost = export.phonemic(term, true)
		for _, variant in ipairs(variantsPost) do
			table.insert(results2, {pron = "/" .. variant .. "/"})
		end
	end

	results1[1].qualifiers = {"10<sup>th</sup>–15<sup>th</sup> CE"}
	results2[1].qualifiers = {"15<sup>th</sup> CE"}

	return "*" .. m_IPA.format_IPA_full { lang = lang, items = results1 }
		.. "\n*" .. m_IPA.format_IPA_full { lang = lang, items = results2 }
end

return export