Jump to content

Module:srn-IPA

From Wiktionary, the free dictionary


local export = {}

local m_IPA = require("Module:IPA")
local m_para = require("Module:parameters")
local lang = require("Module:languages").getByCode("srn")

local gsub = mw.ustring.gsub
local rlower = mw.ustring.lower

local LEN = "\203\144" -- length
local COART = "\205\161" -- coarticulation
local NSYL = "\204\175" -- nonsyllabic
local TILDE = "\204\131" -- nasal

--[=[

Author: saph (User:Saph668)

Implements {{Template:srn-IPA}}.

]=]--

local C = "bdfghklmnprstwjzNTDYScɟɡɾ"
local V = "aeɛioɔuãẽɛ̃ĩõɔ̃ũa̠ɪ̞ʊ̞ã̠ɪ̞̃ʊ̞̃ɑ̟e̝ɔ̝ɑ̟̃ẽ̝ɔ̝̃"
local VL = {
	["â"] = 'a', ["ê"] = 'e',
	["î"] = 'i', ["ô"] = 'o',
	["û"] = 'u',
}

local di_s = {
    -- digraphs, standard
    ["ò"] = 'ɔ', ["è"] = 'ɛ',

    ["ty"] = 'T', ["sy"] = 'S',
    ["dy"] = 'D', ["ny"] = 'Y',
}

local di_d = {
    -- digraphs, 'Dutch'
    -- note ò è, as above
    ["ò"] = 'ɔ', ["è"] = 'ɛ',
    ["ie"] = 'i', ["oe"] = 'u',
    ["a[ij]"] = 'ai' .. NSYL, ["ee"] = 'ei' .. NSYL,
    ["é"] = 'ei' .. NSYL, ["ei"] = 'ɛi' .. NSYL,
    ["ij"] = 'ɛi' .. NSYL, ["o[ij]"] = 'oi' .. NSYL,
    ["auw"] = 'au' .. NSYL, ["ou"] = 'ou' .. NSYL,
    -- o for ow dealt with later

    ["tj"] = 'T', ["tsj"] = 'T',
    ["dj"] = 'D', ["nj"] = 'Y',
    ["sj"] = 'S',
}

local function pron(text, system)
    text = rlower(text)
    for h,i in pairs(VL) do
    	text = text:gsub(h, i..LEN)
    end
    text = text:gsub("ng", "N")
    if system == 0 then
        for b,a in pairs(di_s) do
        	text = text:gsub(b, a)
        end
        text = text:gsub("y", "j")
        if not text:match("[aeɛo][wi][" .. V .. "]") then
        	text = text:gsub("[aeɛo]i", "%0" .. NSYL)
        		:gsub("([ao])w", "%1u" .. NSYL)
        end
    end
    if system == 1 then
        for b,a in pairs(di_d) do
        	text = text:gsub(b, a)
        		:gsub("([aeɛo])i([" .. V .. "])", "$1j$2")
        		:gsub("([aeɛo])u([" .. V .. "])", "$1w$2")
        end
        text = text:gsub("([bdkfmnpt])%1", ".%1")
        	:gsub("o([bdfghklmnprstwjzTDYS])[" .. LEN .. "]?([ɾl]?)([" .. V .. "])", "ou" .. NSYL .. "%1%2%3") -- o for ow in open syl; normalise to ô for ô, as above
    end
    text = text:gsub("u" .. NSYL .. "'?w", "ww")
    	:gsub("([" .. C .. "])[’']?%1", "%1" .. LEN)
    	:gsub("g", "ɡ")
    	:gsub("r", "ɾ")
    return text
end

local function phon(text, system)
	local results = {}
	text = pron(text, system)
	text = text:gsub("([" .. V .. "])([nN])[%.]?([" .. C .. "])", "%1" .. TILDE .. "%2%3")
		:gsub("([" .. V .. "])([nN])$", "%1" .. TILDE .. "%2")
	results[1] = gsub(text, "([" .. V .. "])" .. TILDE .. "?[nN]$", "%1" .. TILDE .. "N")
		:gsub("ɡ([ie])", "ɟ%1")
		:gsub("k([ie])", "c%1")
		:gsub("a", "a̠")
		:gsub("e", "ɪ̞")
		:gsub("o", "ʊ̞")
	results[2] = text:gsub("ɡ([ie])", "j%1")
		:gsub("k([ie])", "T%1")
		:gsub("a", "ɑ̟")
		:gsub("e", "e̝")
		:gsub("o", "ɔ̝")
	for i = 1,2,1 do
		results[i] = results[i]:gsub("n[%.]?([mpb])", "m%1")
		results[i] = gsub(results[i], "n[%.]?([kɡcɟ])", "N%1")
	end
	return results
end

local function stress(text)
	-- Manually specify stress in param 1 using _
	manual = text:gsub("_", "ˈ")
	if manual ~= text then return manual end
	
	local structure = "[" .. C .. "]?[" .. LEN .. "]?[ɾlw]?[" .. V .. "]+[" .. LEN .. "]?[" .. NSYL .. "]?"
	text = gsub(text, structure .. "[nN][%.]?$", "ˈ%0")
	if not text:match("-") then
		text = gsub(text, "^" .. structure .. "[^nN]?[%.]?$", "ˈ%0")
		if not text:match("ˈ") then
			text = gsub(text, structure .. "[" .. C .. "]?[" .. C .. "]?[%.]?" .. structure .. "[bdfghklprstwjzTDYSɡ]?[%.]?$", "ˈ%0") 
		end
	end

	return text
end

local function toIPA(text)
    text = text:gsub("", "")
    	:gsub("N", "ŋ")
    	:gsub("T", "t" .. COART .. "ʃ")
    	:gsub("D", "d" .. COART .. "ʒ")
    	:gsub("Y", "ɲ")
    	:gsub("S", "ʃ")
    	:gsub("[!:%–]", " |") -- remove punctuation
    	:gsub(",", "")
    	:gsub("%.", "")
    	:gsub("[’']", "")
    return text
end

function export.make_IPAs(term, system)
    local phonemic, phonetic_a, phonetic_b = {}, {}, {}
    term = term .. ""
    local words = mw.text.split(term, " ", true)
    for i, word in ipairs(words) do
    	phonemic[i] = stress(pron(word, system))
    	phonetic_a[i] = stress(phon(word, system)[1])
    	phonetic_b[i] = stress(phon(word, system)[2])
    end
    phonemic = toIPA(table.concat(phonemic, " "))
    phonetic_a = toIPA(table.concat(phonetic_a, " "))
    phonetic_b = toIPA(table.concat(phonetic_b, " "))
    return phonemic, phonetic_a, phonetic_b
end

function export.make(frame)
    if pcall(function() local args = frame:getParent().args end) 
		then parent_args = frame:getParent().args  
		else parent_args = frame end
    local params = {
        [1] = { default = mw.loadData("Module:headword/data").pagename},
        [2] = { type = "number", default = 0 }
    }
    local args = m_para.process(parent_args, params)
    local system = args[2]
    local results = {}
    phonemic, phonetic_a, phonetic_b = export.make_IPAs(args[1], system)
    table.insert(results, { pron = "/" .. phonemic .. "/" })
    if phonetic_a ~= phonemic then
        table.insert(results, { pron = "[" .. phonetic_a .. "]" })
        if phonetic_b ~= phonetic_a then
        	table.insert(results, { pron = "[" .. phonetic_b .. "]" })
        end
    end
    return m_IPA.format_IPA_full { lang = lang, items = results }
end

return export