This module implements the {{ee-IPA}}
template.
local export = {}
local m_str_utils = require("Module:string utilities")
local decomp = mw.ustring.toNFD
local gsplit = m_str_utils.gsplit
local gsub = m_str_utils.gsub
local lower = m_str_utils.lower
local match = m_str_utils.match
local lang = require("Module:languages").getByCode("ee") -- Ewe language object
local ipa = require("Module:IPA") -- IPA display module
-- Store accents as Unicode variables
local U = require("Module:string/char") -- Unicode character retrieval module
local acute = U(0x0301) -- acute accent (high tone)
local grave = U(0x0300) -- grave accent (low tone)
local circ = U(0x0302) -- circumflex (rising tone)
local caron = U(0x030C) -- caron (rising tone)
local nasal = U(0x0303) -- tilde (nasal)
local tie = U(0x0361) -- tie bar (consonant combinations)
local fortis = U(0x0348) -- fortis mark (fortis consonants)
local dental = U(0x032A) -- dental bar (dental consonants)
local alveolar = U(0x033A) -- alveolar bar (alveolar consonants)
-- Store lists of chars
local CONS = "bcdɖfƒgɣhjklmnŋpqrstvʋwxyzBCDƉFƑGƔHJKLMNŊPQRSTVƲWXYZ" -- consonants
local VOWL = "aeɛioɔuAEƐIOƆU" -- vowels
local TONE = acute .. grave .. circ .. caron -- tone marks
-- Store syllabification markers and boundaries
local syll = "‧" -- syllabification marker
local bound = "#" .. syll -- syllable boundary
-- NOTE: Keep both single and multiple substitutions separate to ensure consistency
-- Store list of single substitutions (STEP 1)
local subs_1 = {
-- "m" = phoneMic, "t" = phoneTic
{ "", "ɰ", "m" }, -- and are allophones of /ɰ/
{ "()()", function(a, b) -- add tie bars between gb, kp, dz and ts
if (a == "g" and b == "b") or
(a == "k" and b == "p") or
(a == "d" and b == "z") or
(a == "t" and b == "s") then
return a .. tie .. b
end
return a .. b
end, "mt" },
{ "()", "%1" .. nasal, "mt" }, -- /l/ and /r/ become nasal in consonant clusters
{ "" .. nasal, "l", "m" }, -- /r/ is actually an allophone of /l/ in consonant clusters
{ "r" .. nasal, "ɾ" .. nasal, "t" }, -- /r/ is actually tapped in consonant clusters
{ "()()", "%1" .. dental .. "%2", "t" }, -- /d/ and /t/ are dental (but not /d͡z/ and t͡s/)
{ "()", "%1" .. fortis, "t" }, -- /f/ and /v/ are fortis
{ "ny", "ɲ", "mt" }, -- substitute ⟨ny⟩ with /ɲ/
{ "n", "n" .. alveolar, "t" }, -- /n/ is alveolar
{ ".", {
= "ɸ",
= "ɡ",
= "β",
= "j"
}, "mt" }, -- sub_single letters with IPA values
{ "()i", function(a) -- palatalise /s/ and /z/ (and /t͡s/ and /d͡z/) before /i/
if a == "s" then
return "ʃi"
end
return "ʒi"
end, "t" }
}
-- Store list of multiple substitutions (STEP 2)
local subs_2 = {
{ "h", { "ʁ", "ʕ", "ɦ" }, " ~ ", "t" }, -- /h/ is actually voiced either as , or
{ "()" .. nasal, { "%1" .. nasal, "%1" }, ",", "t" }, -- and in consonant clusters can also be non-nasal
{ alveolar, { alveolar, dental }, ",", "t" } -- alveolar can also be dental
}
-- STEP 1: Perform single substitutions on a term
local function sub_single(term, is_phonetic)
-- Iterate through single substitutions
for _, sub in ipairs(subs_1) do
local foo, bar, mode = sub, sub, sub
-- Apply substitution given mode corresponds to is_phonetic
if (is_phonetic and match(mode, "t")) or (not is_phonetic and match(mode, "m")) then
term = gsub(term, foo, bar)
end
end
return term
end
-- STEP 2: Perform multiple unique substitutions given a table of at least two items
local function sub_multiple(term, is_phonetic)
-- Iterate through multiple substitutions
for _, sub in ipairs(subs_2) do
local foo, bar, sep, mode = sub, sub, sub, sub
-- Apply substitution given mode corresponds to is_phonetic
if (is_phonetic and match(mode, "t")) or (not is_phonetic and match(mode, "m")) then
-- Check if the pattern exists in the term
if match(term, foo) then
local results = ""
local base = term
-- Join each variant together
for i, var in ipairs(bar) do
local result = gsub(base, foo, var)
results = results .. (i == 1 and result or sep .. result)
end
term = results
end
end
end
return term
end
-- Syllabify given term
local function syllabify(term, hide_borders)
-- Mark all word borders with #
term = gsub(term, "(+)", "#%1#")
-- Add syllabification after tone marks
term = gsub(term, "()()", "%1" .. syll .. "%2")
-- Remove syllabification markers from leading consonants
term = gsub(term, syll .. "(+#)", "%1")
-- Remove word borders if requested
return hide_borders and gsub(term, "#", "") or term
end
-- Get pronunciation from syllablified term
function export.toIPA(term, is_phonetic)
-- Decompose entry
term = decomp(term)
-- Syllabify the term
term = syllabify(term, false)
-- Make it lowercase
term = lower(term)
-- Perform both sets of substitutions
term = sub_single(term, is_phonetic) -- single substitutions
term = sub_multiple(term, is_phonetic) -- multiple substitutions
-- Convert syllable boundaries to dots and remove word borders
return gsub(gsub(term, syll, "."), "#", "")
end
function export.show(frame)
-- Get language and arguments from frame, return error otherwise
local args = frame:getParent().args
if not args then
error("Please provide an entry with tone marks.")
end
-- Initialise results tables
local results_m, results_t = {}, {}
-- Process each non-empty argument
for _, term in ipairs(args) do
if term ~= "" then
local phonemic = export.toIPA(term, false)
local phonetic = export.toIPA(term, true)
-- Initialise parameters and results
local phonemic_results, phonetic_results = {}, {}
-- Split phonemic and phonetic variants
for variant in gsplit(phonemic, ",") do
table.insert(phonemic_results, { pron = "/" .. variant .. "/" })
end
if phonemic ~= phonetic then
for variant in gsplit(phonetic, ",") do
table.insert(phonetic_results, { pron = "" })
end
end
-- Add all variants to results
for _, variant in ipairs(phonemic_results) do
table.insert(results_m, variant)
end
for _, variant in ipairs(phonetic_results) do
table.insert(results_t, variant)
end
end
end
-- Combine results with phonemic first, then phonetic
local results = {}
for _, result in ipairs(results_m) do
table.insert(results, result)
end
for _, result in ipairs(results_t) do
table.insert(results, result)
end
return ipa.format_IPA_full { lang = lang, items = results }
end
return export