Module:fa-headword

Hello, you have come here looking for the meaning of the word Module:fa-headword. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:fa-headword, but we will also tell you about its etymology, its characteristics and you will know how to say Module:fa-headword in singular and plural. Everything you need to know about the word Module:fa-headword you have here. The definition of the word Module:fa-headword will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:fa-headword, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.

This is the module for Persian headword templates. Currently, only the noun and adjective function is working and being used (and verb function in {{fa-verb/new}}).


-- Credit: Fenakhay for base of the module, adjectives, and verb functions
-- Saam-andar for nouns function and expansion of adjectives and verbs
-- Also Theknightwho and Benwing2

local lang = require("Module:languages").getByCode("fa")
local fa_cls = require("Module:fa-cls-translit")
local fa_ira = require("Module:fa-translit")
local m_parameters = require("Module:parameters")

local export = {}
local pos_functions = {}

local u = mw.ustring.char
local unpack = unpack or table.unpack -- Lua 5.2 compatibility

-- Diacritics
local A = u(0x064E) -- fatha/fathe
local AN = u(0x064B) -- fatHatan (tanwīn-i fatha/tanvin-e fathe or nasb)
local U = u(0x064F) -- zamma/zamme
local UN = u(0x064C) -- Dammatan (tanwīn-i zamma/tanwin-e zamme or raf')
local I = u(0x0650) -- kasra/kasre
local IN = u(0x064D) -- kasratan (tanwīn-i kasra/tanwin-e kasre or jarr)
local SK = u(0x0652) -- sukūn/sokun or jazm
local SH = u(0x0651) -- šadda/tašdid
local DAGGER_ALIF = u(0x0670)
local DIACRITICS = ""

-----------------------
-- Utility functions --
-----------------------

-- version of mw.ustring.gsub() that discards all but the first return value
local function rsub(term, foo, bar)
    local retval = mw.ustring.gsub(term, foo, bar)
    return retval
end

-- Tracking functions
local trackfn = require("Module:debug/track")

local function track(page)
    trackfn("fa-headword/" .. page)
    return true
end

-- Clean up translit strings by removing HTML spans and normalizing
local function clean_translit(tr)
    if not tr then return nil end
    -- Remove HTML spans that might be added by {{fa-xlit}}
    tr = rsub(tr, "</?span*>", "")
    -- Normalize whitespace around separators
    tr = rsub(tr, "%s*/%s*", " / ")
    tr = rsub(tr, "%s*<i>or</i>%s*", " <i>or</i> ")
    tr = mw.text.trim(tr)
    return tr ~= "" and tr or nil
end

-- Check if a parameter is disabled 
local function is_disabled(param)
    return param == "-" or param == "—" or param == "–" or param == "false"
end

-- Check if ی is a vowel based on transliteration
local function is_vowel_ye(word, cls_list, ir_list)
    if not mw.ustring.match(word, "ی$") then
        return false
    end
    
    local has_vowel_indication = false
    
    for j = 1, 3 do
        local cls_tr = cls_list
        local ir_tr = ir_list
        
        if cls_tr and cls_tr ~= "" then
            if mw.ustring.match(cls_tr, "$") then
                has_vowel_indication = true
            end
        end
        
        if ir_tr and ir_tr ~= "" then
            if mw.ustring.match(ir_tr, "i$") then
                has_vowel_indication = true
            end
        end
    end
    
    return has_vowel_indication
end

function export.ZWNJ(word)
    word = rsub(word, DIACRITICS .. "+$", "")
    if mw.ustring.match(word, "", -1) then
        return "\226\128\140" -- U+200C
    end
    return ""
end

-- Define parameter specifications
local function get_param_spec(poscat)
    local base_params = {
         = {},
         = {list = true, allow_holes = true},
         = {},
         = {},
         = {list = true, allow_holes = true},
         = {list = true, allow_holes = true},
         = {list = true, allow_holes = true},
         = {list = true, allow_holes = true},
         = {list = true, allow_holes = true},
         = {type = "boolean"},
    }
    
    -- Add qualifier parameters for Tajik forms
    for i = 1, 4 do
        base_params = {}
    end
    
    if poscat == "nouns" then
        base_params = {list = true, allow_holes = true}
        base_params = {list = true, allow_holes = true}
        
        for i = 1, 4 do
            local base_key = "pl" .. (i == 1 and "" or tostring(i))
            base_params = {}
            base_params = {}
            for j = 2, 3 do
                base_params = {}
            end
        end
        
    elseif poscat == "verbs" then
        base_params = {list = true, allow_holes = true}
        base_params = {list = true, allow_holes = true}
        base_params = {list = true, allow_holes = true}
        
        for i = 1, 3 do
            local stem_key = "prstem" .. tostring(i)
            base_params = {}
            base_params = {}
            base_params = {}
        end
        
    elseif poscat == "adjectives" then
        base_params = {}
        base_params = {}
        base_params = {}
    end
    
    return base_params
end

-- Process transliterations for heads or forms
local function process_translits(forms, cls_list, ir_list, tr_list)
    local results = {}
    
    for i = 1, #forms do
        local tr_overrides = {}
        for j = 1, 3 do
            local tr = tr_list
            if tr and tr ~= "" then
                table.insert(tr_overrides, tr)
            end
        end

        local cls_filtered, ira_filtered = {}, {}
        for j = 1, 3 do
            if not (tr_list and tr_list ~= "") then
                if cls_list and cls_list ~= "" then
                    table.insert(cls_filtered, cls_list)
                end
                if ir_list and ir_list ~= "" then
                    table.insert(ira_filtered, ir_list)
                end
            end
        end

        local cls_str = table.concat(cls_filtered, ", ")
        local ira_str = table.concat(ira_filtered, ", ")

        local base_tr = ""
        if cls_str ~= "" and ira_str ~= "" then
            base_tr = (cls_str == ira_str) and cls_str or (cls_str .. " / " .. ira_str)
        elseif cls_str ~= "" then
            base_tr = cls_str
        elseif ira_str ~= "" then
            base_tr = ira_str
        end

        local final_tr = base_tr
        if #tr_overrides > 0 then
            local overrides_str = table.concat(tr_overrides, " <i>or</i> ")
            final_tr = (final_tr ~= "") and (final_tr .. " <i>or</i> " .. overrides_str) or overrides_str
        end

        results = final_tr
    end
    
    return results
end

-- The main entry point.
function export.show(frame)
    local PAGENAME = mw.loadData("Module:headword/data").pagename
    local poscat = frame.args or error(
        "Part of speech has not been specified. Please pass parameter 1 to the module invocation.")

    local params = get_param_spec(poscat)
    local args = m_parameters.process(frame:getParent().args, params)

    -- Gather parameters
    local data = {
        lang = lang,
        pos_category = poscat,
        categories = {},
        heads = {},
        translits = {},
        inflections = {},
        id = args,
        sort_key = args,
        nomultiwordcat = args
    }

    -- Process heads
    local heads = {}
    if args then
        for i, head in ipairs(args) do
            if head then
                table.insert(heads, head)
            end
        end
    elseif args then
        table.insert(heads, args)
    else
        table.insert(heads, PAGENAME)
    end
    
    if #heads == 0 then
        heads = {PAGENAME}
    end

    -- Process head transliterations
    local cls_list = {}
    local ir_list = {}
    local tr_list = {}

    for i = 1, math.max(#heads, 3) do
        local cls_raw = args
        local ir_raw = args
        local tr = clean_translit(args)

        local cls_tr = cls_raw and fa_cls.tr(cls_raw) or ""
        local ir_tr = ""
        
        -- Check if IR is disabled for this index
        if ir_raw and not is_disabled(ir_raw) then
            ir_tr = fa_ira.IRA_tr(ir_raw) or ""
        elseif not ir_raw and cls_raw and not is_disabled(args) then
            ir_tr = fa_ira.IRA_tr(cls_raw) or ""
        end

        cls_list = cls_tr
        ir_list = ir_tr
        tr_list = tr
    end

    if #heads == 1 then
        -- Single head: combine all transliterations
        local translits = process_translits(heads, cls_list, ir_list, tr_list)
        data.heads = heads
        data.translits = translits
    else
        -- Multiple heads: assign translit to head
        data.heads = heads
        for i = 1, #heads do
            local tr = tr_list
            if tr and tr ~= "" then
                data.translits = tr
            else
                local cls_tr = cls_list or ""
                local ir_tr = ir_list or ""
                if cls_tr ~= "" and ir_tr ~= "" then
                    data.translits = (cls_tr == ir_tr) and cls_tr or (cls_tr .. " / " .. ir_tr)
                else
                    data.translits = cls_tr .. ir_tr
                end
            end
        end
    end

    data.no_redundant_head_cat = (#heads > 1)

    -- Call POS-specific function
    if pos_functions then
        pos_functions.func(args, data)
    end

    return require("Module:headword").full_headword(data)
end

-- Helper function to add Tajik forms
local function add_tajik_forms(args, data)
    local tajik_forms = {}
    
    for i = 1, 3 do
        local cls = args
        local tg = args
        local tgq = args or args

        if not is_disabled(tg) then
            if not tg and cls then
                tg = require("Module:tg-Latn-Cyrl-translit").tr(fa_cls.tr(cls))
            end
            if tg then
                table.insert(tajik_forms, {
                    term = tg,
                    qualifier = tgq
                })
            end
        end
    end
    
    -- Tajik labeling
    for i, form in ipairs(tajik_forms) do
        local label
        if i == 1 then
            label = "Tajik spelling"
        else
            label = "<i>or</i>"
        end
        if form.qualifier then
            label = label .. " <span style=\"font-style: italic;\">(" .. form.qualifier .. ")</span>"
        end
        table.insert(data.inflections, {
            label = label,
            { term = form.term, lang = require("Module:languages").getByCode("tg") }
        })
    end
end

-- Generate automatic plural transliteration
local function generate_auto_plural_translit(base, base_zwnj, plural, cls_list, ir_list)
    local suffix_map = {
         = {"-hā", "-hâ"},
         = {"āt", "ât"}, 
         = {"ān", "ân"},
         = {"yān", "yân"}
    }
    
    -- Determine applied suffix
    local applied_suffix
    
    for suffix, _ in pairs(suffix_map) do
        if plural == base .. suffix or plural == base .. base_zwnj .. suffix then
            applied_suffix = suffix
            break
        end
    end
    
    if not applied_suffix or not suffix_map then
        return nil
    end
    
    local cls_suffix = suffix_map
    local ir_suffix = suffix_map
    
    local cls_tr_list = {}
    local ir_tr_list = {}
    
    for j = 1, 3 do
        local cls_tr = cls_list
        local ir_tr = ir_list
        
        if cls_tr and cls_tr ~= "" then
            if mw.ustring.match(cls_tr, "$") then
                if applied_suffix == "ان" then
                    table.insert(cls_tr_list, cls_tr .. "yān")
                elseif applied_suffix == "ات" then
                    table.insert(cls_tr_list, cls_tr .. "yāt")
                else
                    table.insert(cls_tr_list, cls_tr .. cls_suffix)
                end
            else
                table.insert(cls_tr_list, cls_tr .. cls_suffix)
            end
        end
        
        if ir_tr and ir_tr ~= "" then
            if mw.ustring.match(ir_tr, "i$") then
                if applied_suffix == "ان" then
                    table.insert(ir_tr_list, ir_tr .. "yân")
                elseif applied_suffix == "ات" then
                    table.insert(ir_tr_list, ir_tr .. "yât")
                else
                    table.insert(ir_tr_list, ir_tr .. ir_suffix)
                end
            else
                table.insert(ir_tr_list, ir_tr .. ir_suffix)
            end
        end
    end
    
    local cls_str = table.concat(cls_tr_list, ", ")
    local ir_str = table.concat(ir_tr_list, ", ")
    
    if cls_str ~= "" and ir_str ~= "" then
        return (cls_str == ir_str) and cls_str or (cls_str .. " / " .. ir_str)
    elseif cls_str ~= "" then
        return cls_str
    elseif ir_str ~= "" then
        return ir_str
    end
    
    return nil
end

pos_functions = {
    func = function(args, data)
        data.pos_category = "nouns"

        for i = 1, 4 do
            local pl = args
            if not pl then break end
            
            local plq = (args and args) or args
            
            local tr_variants = {}
            
            -- Main translit parameter
            local main_tr_key = "pl" .. (i == 1 and "" or tostring(i)) .. "tr"
            local main_tr = clean_translit(args)
            
            local alt_tr2 = clean_translit(args)
            local alt_tr3 = clean_translit(args)
            
            local base = data.heads
            local base_zwnj = export.ZWNJ(base)
            
            local cls_list = {}
            local ir_list = {}
            for j = 1, 3 do
                local cls_raw = args
                local ir_raw = args
                
                if cls_raw then
                    cls_list = fa_cls.tr(cls_raw) or ""
                end
                
                if ir_raw and not is_disabled(ir_raw) then
                    ir_list = fa_ira.IRA_tr(ir_raw) or ""
                elseif not ir_raw and cls_raw then
                    ir_list = fa_ira.IRA_tr(cls_raw) or ""
                end
            end
            
            local auto_tr = generate_auto_plural_translit(base, base_zwnj, pl, cls_list, ir_list)
            if auto_tr then
                table.insert(tr_variants, auto_tr)
            end
            
            if main_tr and not auto_tr then
                table.insert(tr_variants, main_tr)
            end
            
            if alt_tr2 then
                table.insert(tr_variants, alt_tr2)
            end
            if alt_tr3 then
                table.insert(tr_variants, alt_tr3)
            end
            
            local final_tr = (#tr_variants > 0) and table.concat(tr_variants, " <i>or</i> ") or nil
            
            local label = (i == 1 and "plural" or "<i>or</i>")
            if plq then
                label = label .. " <span style=\"font-style: italic;\">(" .. plq .. ")</span>"
            end
            
            table.insert(data.inflections, {
                label = label,
                {term = pl, translit = final_tr}
            })
        end

        -- Add Tajik forms
        add_tajik_forms(args, data)
    end
}

pos_functions = {
    func = function(args, data)
        data.pos_category = "verbs"
        
        local prstems = {}
        for i = 1, 3 do
            local stem = args
            if stem then
                table.insert(prstems, stem)
            end
        end
        
        if #prstems > 0 then
            for i, stem in ipairs(prstems) do
                local prstemq = (args and args) or args
                local tr = clean_translit((args and args) or args)
                
                local label = (i == 1 and "present stem" or "<i>or</i>")
                if prstemq then
                    label = label .. " <span style=\"font-style: italic;\">(" .. prstemq .. ")</span>"
                end
                
                table.insert(data.inflections, {
                    label = label,
                    {term = stem, translit = tr}
                })
            end
        end
        
        -- Add Tajik forms
        add_tajik_forms(args, data)
    end
}

pos_functions = {
    func = function(args, data)
        data.pos_category = "adjectives"
        local word = data.heads
        local zwnj = export.ZWNJ(word)

        -- Handle comparative/superlative
        if args == "+" then
            local cmp_forms = {{term = word .. zwnj .. "ت" .. A .. "ر"}}
            local sup_forms = {{term = word .. zwnj .. "ت" .. A .. "رین"}}
            
            -- Handle alternative stem
            if args then
                local alt = args
                local alt_zwnj = (args ~= "-") and export.ZWNJ(alt) or ""
                
                local tr_cls = fa_cls.tr(alt) or ""
                local tr_ir = fa_ira.IRA_tr(alt) or ""
                
                local cls_suffix_cmp = alt_zwnj ~= "" and "-tar" or "tar"
                local cls_suffix_sup = alt_zwnj ~= "" and "-tarīn" or "tarīn"
                local ir_suffix_cmp = alt_zwnj ~= "" and "-tar" or "tar"
                local ir_suffix_sup = alt_zwnj ~= "" and "-tarin" or "tarin"
                
                local function combine_translit(cls, ira, cls_suffix, ir_suffix)
                    if cls == ira or ira == "" then
                        return cls .. cls_suffix
                    elseif cls == "" then
                        return ira .. ir_suffix
                    else
                        return cls .. cls_suffix .. " / " .. ira .. ir_suffix
                    end
                end
                
                local tr_cmp = combine_translit(tr_cls, tr_ir, cls_suffix_cmp, ir_suffix_cmp)
                local tr_sup = combine_translit(tr_cls, tr_ir, cls_suffix_sup, ir_suffix_sup)
                
                table.insert(cmp_forms, {
                    term = alt .. alt_zwnj .. "ت" .. A .. "ر",
                    translit = tr_cmp
                })
                table.insert(sup_forms, {
                    term = alt .. alt_zwnj .. "ت" .. A .. "رین",
                    translit = tr_sup
                })
            end
            
            table.insert(data.inflections, {
                label = "comparative",
                accel = {form = "comparative"},
                unpack(cmp_forms)
            })
            
            table.insert(data.inflections, {
                label = "superlative", 
                accel = {form = "superlative"},
                unpack(sup_forms)
            })
        end

        -- Add Tajik forms
        add_tajik_forms(args, data)
    end
}

return export