Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Kru-IPA

From Wikipedia, the free encyclopedia
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