Module:Kru-IPA
Appearance
local export = {}
-- Helper function to strip whitespace and clean up raw template string inputs
local function clean_input(str)
if not str then return "" end
-- Remove leading/trailing spaces and strip out literal wiki formatting if accidentally passed
str = str:gsub("^%s*(.-)%s*$", "%1")
return str:lower()
end
function export.generate(frame)
-- Fetch parameters from either direct invoke or parent template context
local args = frame.args[1] and frame.args or frame:getParent().args
local raw_text = args[1] or ""
local ipa = clean_input(raw_text)
if ipa == "" then
return "<span class='error'>Error: No text string provided to Module:kru-IPA</span>"
end
-- 1. VOWELS (ISO 15919 long vowels mapped to standard IPA length marks)
ipa = ipa:gsub("ā", "aː")
:gsub("ī", "iː")
:gsub("ū", "uː")
:gsub("ē", "eː")
:gsub("ō", "oː")
-- 2. COMPLEX CONSONANT CLUSTERS, FRICATIVES & ALLOPHONIC AFFRICATES
ipa = ipa:gsub("k͟h", "x")
:gsub("kh", "x")
:gsub("c", "t͡ɕ~t͡ʃ")
:gsub("j", "d͡ʑ~d͡ʒ")
:gsub("d̪", "t̪") -- Multi-grapheme dental allophone collapses straight to /t̪/
-- 3. SEGREGATION MATRIX (Isolators for Alveolars and Custom Approximants)
-- Protects your true Alveolar phonemes and their exact allophones from clashing with dental rules
ipa = ipa:gsub("r̤", "D") -- Custom r̤ -> Placeholder D (will become /ɻ/)
ipa = ipa:gsub("ṯ", "A") -- Voiceless Alveolar Phoneme ṯ -> Placeholder A (will become /t/)
ipa = ipa:gsub("ḏ", "A") -- Voiced Alveolar Allophone ḏ -> Placeholder A (collapses to /t/)
ipa = ipa:gsub("ṉ", "B") -- Alveolar Nasal ṉ -> Placeholder B (will become /n/)
ipa = ipa:gsub("ṟ", "C") -- Alveolar Trill ṟ -> Placeholder C (will become /r/)
-- 4. PRIMARY REPLACEMENTS (Dentals, Retroflex Plosives, Nasals, and Taps)
-- Bilabial & Velar Allophone to Phoneme Collapse
ipa = ipa:gsub("b", "p")
ipa = ipa:gsub("g", "k")
-- Dental Group: Plain 't' is phoneme /t̪/. Plain 'd' is allophone, collapsing to /t̪/
ipa = ipa:gsub("t", "t̪")
ipa = ipa:gsub("d", "t̪")
-- Retroflex Group: Plain 'ṭ' is phoneme /ʈ/. Plain 'ḍ' is allophone, collapsing to /ʈ/
ipa = ipa:gsub("ṭ", "ʈ")
ipa = ipa:gsub("ḍ", "ʈ")
-- Nasals, Liquids & Flaps (Using unique wrapper for ṇ to block dental 'n' interference)
ipa = ipa:gsub("n", "n̪")
ipa = ipa:gsub("r", "ɾ")
ipa = ipa:gsub("ṇ", "<b>ɳ</b>")
ipa = ipa:gsub("ḷ", "ɭ")
ipa = ipa:gsub("ñ", "ɲ")
ipa = ipa:gsub("ṅ", "ŋ")
ipa = ipa:gsub("ṛ", "ɽ")
-- Rest of the Consonants from your Global Matrix
ipa = ipa:gsub("m", "m") -- Bilabial Nasal
ipa = ipa:gsub("w", "w") -- Bilabial Central Approximant
ipa = ipa:gsub("s", "s") -- Alveolar Fricative
ipa = ipa:gsub("l", "l") -- Alveolar Lateral Approximant
ipa = ipa:gsub("y", "j") -- Palatal Central Approximant (y -> /j/)
ipa = ipa:gsub("h", "h") -- Glottal Fricative
-- 5. MATRIX RESOLUTION (Converting tokens back into targeted true phonemes)
ipa = ipa:gsub("A", "t") -- Pure Voiceless Alveolar Stop Phoneme /t/ (from ṯ and ḏ)
ipa = ipa:gsub("B", "n") -- Pure Alveolar Nasal Phoneme /n/ (from ṉ)
ipa = ipa:gsub("C", "r") -- Pure Alveolar Trill Phoneme /r/ (from ṟ)
ipa = ipa:gsub("D", "ɻ") -- Pure Retroflex Approximant Phoneme /ɻ/ (from r̤)
ipa = ipa:gsub("<b>#</b>", "ɳ") -- Restores retroflex nasal safely
ipa = ipa:gsub("<b>ɳ</b>", "ɳ")
-- Wrap output in standard phonetic slashes for dictionary use
return "/" .. ipa .. "/"
end
return export