Module:User:AmazingJus/ga

local export = {}

local lang = require("Module:languages").getByCode("ga") local sc = require("Module:scripts").getByCode("Latn")

function export.tag_text(text, face) return require("Module:script utilities").tag_text(text, lang, sc, face) end

function export.link(term, face) return require("Module:links").full_link( { term = term, lang = lang, sc = sc }, face ) end

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

local CONS = "[bcdfghjklLmnNŋpqrRstvwxyz]h?" -- consonants local FRNT = "eiéí" -- front vowels local BACK = "aouáóúòù" -- back vowels local VOWL = FRNT .. BACK -- all vowels local SYLL = "[^" .. VOWL .. "]" -- syllable boundary (should not be a vowel) local BROD = "ˠ" -- broad mark local SLND = "ʲ" -- slender mark

--	list of various spelling-to-phoneme correspondences	dialect order: ulster, connacht, munster -- vowel substitutions local vowel_rules = { -- mixed vowel + consonant forms ["mixed"] = { ["e?abhai?"] = {"oː", "əu", "əu"}, ["e?a[dg]hai?"] = {"eː", "əi", "əi"}, ["ai?[dg]hai?"] = "əi", ["e?amhai?"] = "ə̃ũ", ["ei[dg]hi?"] = {"eː", "əi", "əi"}, ["ei[dg]hea"] = {"eː", "əi", "əi"}, ["oi[dg]hi?"] = "əi", ["oi[dg]hea"] = "əi", ["e?o[bdg]hai?"] = {"oː", "əu", "əu"}, ["e?omhai?"] = "õː", ["i?ubh"] = {"uː", "ʊ(w)", "ʊw"}, ["i?umhai?"] = "ũː" },	-- vowel-only forms ["vowels"] = { -- a		["aei?"] = "eː", ["aoi"] = "iː", ["aío?"] = "iː", ["ai"] = { ["r[dln]"] = "aː", ["R"] = "aː", ["[LN]"] = {"a", "aː", "əi"}, [false] = "a" },		["ao"] = {"iː", "iː", "eː"}, ["a"] = { ["r[dlnr]"] = "aː", ["[LmN]" .. SYLL] = {"a", "aː", "əu"}, [false] = "a" },		-- e		["eai?"] = { ["r[dln]"] = "aː", ["R"] = "aː", ["[LN]"] = {"a", "aː", "əu"}, [false] = "a", },		["eoi?"] = "oː", ["eái?"] = "aː", ["eòi?"] = "ɔ", ["ei?"] = { ["r[dln]"] = "eː", ["[mN]" .. SYLL] = {"ɪ", "iː", "əi"}, ["mh?"] = "ɪ", ["n"] = "ɪ", [false] = "ɛ" },		-- i		["iai?"] = "iə", ["iói?"] = "iːoː", ["iúi?"] = "uː", ["io"] = { ["th"] = "ɪ", ["[dlnrst]"] = "ɪ", ["N" .. SYLL] = {"ɪ", "ʊ", "uː"}, [false] = {"ɪ", "ʊ", "ʊ"}, },		["iu"] = "ʊ", ["i"] = { ["[LmN]"] = {"ɪ", "iː", "iː"}, [false] = "ɪ", },		-- o		["oío?"] = "iː", ["o"] = { ["r[dln]"] = "oː", ["[nm]"] = {"ɔ", "ʊ", "ʊ"}, ["[mN]" .. SYLL] = {"ɔ", "uː", "əu"}, ["ng" .. SYLL] = {"ɔ", "uː", "əu"}, [false] = "ɔ", },		-- u		["uai?"] = "uə", ["uái?"] = "uːaː", ["uío?"] = "iː", ["uói?"] = "uːoː", ["ui"] = { ["r[dln]"] = {"ɪ", "uː", "uː"}, ["[LmN]" .. SYLL] = {"ɪ", "iː", "iː"}, [false] = "ɪ", },		["u"] = { ["r[dln]"] = "uː", [false] = "ʊ", },		["ù"] = "ɔ",

-- á ["ái?"] = {"æː", "ɑː", "ɑː"}, -- é ["é[ai]?"] = "eː", -- í ["ío?"] = "iː", -- ó ["ói?"] = "oː", -- ú ["úi?"] = "uː" } }

-- consonant substitutions local cons_rules = { -- initial mutation forms ["mut"] = { ["bhf"] = "mh", -- eclipsis of f		["bp"] = "b", -- eclipsis of p		["dt"] = "d", -- eclipsis of t		["gc"] = "g", -- eclipsis of c		["mb"] = "m", -- eclipsis of b		["nd"] = "n", -- eclipsis of d		["ng"] = "ŋ", -- eclipsis of g		["ph"] = "f", -- lenition of f		["ts"] = "t", -- lenition of s after 'an' ["l"] = "L", -- /l/ is always fortis word-initially ["n"] = "N", -- /n/ is always fortis word-initially ["r"] = "R" -- /ɾ/ is always fortis word-initially },	-- general respelling forms ["respell"] = { ["j"] = "dz", ["[kq]"] = "c", ["ll"] = "L", -- respell ll for more efficient parsing ["nn"] = "N", -- respell nn for more efficient parsing ["rr"] = "R", -- respell rr for more efficient parsing ["w"] = "v", ["x"] = "cs", ["y"] = "i", ["n([cg])"] = "ŋ%1", -- n is velarised before velar consonants ["r([dlnst])"] = "R%1", -- r is always broad before coronal consonants },	-- parse rules (broad, slender) ["parse"] = { ["[bm]h"] = {"w", "v" .. SLND}, ["ch"] = {"x", "ç"}, ["[dg]h"] = {"ɣ", "j"}, ["fh"] = "", ["[st]h"] = "h", ["b"] = {"b" .. BROD, "b" .. SLND}, ["c"] = {"k", "c"}, ["d"] = {"d̪" .. BROD, "d" .. SLND}, ["f"] = {"f" .. BROD, "f" .. SLND}, ["g"] = {"ɡ", "ɟ"}, ["h"] = "h", ["l"] = {"l" .. BROD, "l" .. SLND}, ["L"] = {"l̪" .. BROD, "l̠" .. SLND}, ["m"] = {"m" .. BROD, "m" .. SLND}, ["n"] = {"n" .. BROD, "n" .. SLND}, ["N"] = {"n̪" .. BROD, "n̠" .. SLND}, ["ŋ"] = {"ŋ", "ɲ"}, ["p"] = {"p" .. BROD, "p" .. SLND}, ["r"] = {"ɾ".. BROD, "ɾ" .. SLND}, ["R"] = "ɾ" .. BROD, ["s"] = {"s" .. BROD, "ʃ"}, ["t"] = {"t̪" .. BROD, "t" .. SLND}, ["v"] = {"w", "v" .. SLND}, ["z"] = {"z" .. BROD, "ʒ"}, } } -- rules applied after parse local after_parse = { ["brsl"] = { ["^s" .. SLND .. "([fmpɾ])"] = "s" .. BROD .. "%1", -- /s/ is always broad word-initially before /f, m, p, ɾ/ ["([dlnɾst]h?)ˠ (" .. CONS .. ")ʲ"] = "%1ʲ %2ʲ", -- broad word-final coronal consonants turn slender before a slender word-initial consonant ["([dlnɾst]h?)ʲ (" .. CONS .. ")ˠ"] = "%1ˠ %2ˠ", -- same vice versa } }

-- prioritise longer matches for each table local function sort_table(tbl) local sorted_patterns = {}

for pattern in pairs(tbl) do		table.insert(sorted_patterns, pattern) end table.sort(sorted_patterns, function(a, b) return #a > #b end)

return sorted_patterns end

-- sort those tables local vowels_sorted = sort_table(vowel_rules.vowels) local mixed_sorted = sort_table(vowel_rules.mixed) local cons_sorted = sort_table(cons_rules.parse)

-- determine whether following consonant is broad/slender local function get_brsl(vowel) return find(BACK, vowel) and "br" or "sl" end

-- parse phonemes local function parse(term) local phones = {} local i = 1 local brsl = get_brsl(match(term, "[" .. VOWL .. "]") or "")

-- loop over every character until reached word-final token while sub(term, i, i) ~= "#" do		local pattern_matched = nil local matched = false

-- match mixed forms first for _, pattern in ipairs(mixed_sorted) do			local value = vowel_rules.mixed[pattern] pattern_matched = match(sub(term, i), "^" .. pattern) if pattern_matched then matched = true -- retrieve appropriate dialectal pronunciation local replacement = type(value) == "table" and value[2] or value table.insert(phones, replacement) i = i + len(pattern_matched) brsl = get_brsl(sub(pattern_matched, -1)) break end end

-- match vowel-only forms if not matched then for _, pattern in ipairs(vowels_sorted) do				local value = vowel_rules.vowels[pattern] pattern_matched = match(sub(term, i), "^" .. pattern) if pattern_matched then matched = true local replacement = type(value) == "table" and value[2] or value if type(value) == "table" then -- lookahead for consonant(s) for subpattern, subvalue in pairs(value) do if subpattern == false or match(sub(term, i + len(pattern_matched)), "^" .. subpattern) then replacement = type(subvalue) == "table" and subvalue[2] or subvalue break end end end table.insert(phones, replacement) i = i + len(pattern_matched) brsl = get_brsl(sub(pattern_matched, -1)) break end end end

-- match a consonant if not matched then for _, pattern in ipairs(cons_sorted) do				local value = cons_rules.parse[pattern] pattern_matched = match(sub(term, i), "^" .. pattern) if pattern_matched then matched = true -- apply broad/slender rules to consonant local replacement = type(value) == "table" and value[brsl == "br" and 1 or 2] or value table.insert(phones, replacement) i = i + len(pattern_matched) break end end end

-- otherwise return error if not matched then error("Invalid character at position" .. i .. ": " .. sub(term, i, i)) end end

return table.concat(phones) end

-- main export function function export.toIPA(term) if type(term) == "table" then term = term.args[1] end

-- add word-final token # for parsing and make all text lowercase term = lower(gsub(term, "[^ ]+", "%1#"))

-- loop over every word in the string return gsub(term, "[^ ]+", function(word)		-- apply word-initial mutation rules		for k, v in pairs(cons_rules.mut) do			word = gsub(word, "^" .. k, v)		end

-- apply general respelling forms word = gsub(word, "..?", cons_rules.respell)

-- parse string word = parse(word)

-- apply further mutation rules for k, v in pairs(after_parse.brsl) do			word = gsub(word, k, v)		end

return word end) end

return export