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 m_table = require("Module:table")

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) -- fatḥa
local AN = u(0x064B) -- fatḥatān (fatḥa tanwīn)
local U = u(0x064F) -- ḍamma
local I = u(0x0650) -- kasra
local SK = u(0x0652) -- sukūn 
local SH = u(0x0651) -- šadda

-----------------------
-- 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

local function remove_links(text)
    text = rsub(text, "%]*|", "")
    text = rsub(text, "%[%[", "")
    text = rsub(text, "%]%]", "")
    return text
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

function export.ZWNJ(word)
    word = mw.ustring.gsub(word, "+$", "")
    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 = {
         = {}, -- legacy head parameter
         = {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"},
    }
    
    if poscat == "nouns" then
        base_params = {list = true, allow_holes = true}
        -- Each plural can have main translit + 3 alternatives
        for i = 1, 4 do
            local base_key = "pl" .. (i == 1 and "" or tostring(i)) .. "tr"
            base_params = {}
            base_params = {} -- alias for main
            for j = 2, 3 do
                base_params = {}
            end
        end
        -- Legacy parameter support
        base_params = {}
        base_params = {}
        base_params = {}
        base_params = {}
        base_params = {}
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}
        base_params = {list = true, allow_holes = true}
        
        for i = 1, 3 do
            local stem_key = "prstem" .. tostring(i)
            base_params = {}
            
            for j = 1, 3 do
                base_params = {}
                base_params = {}
                base_params = {}
            end
            
            base_params = {}
            base_params = {}
            base_params = {}
        end
    elseif poscat == "adjectives" then
        base_params = {}
        base_params = {}
        base_params = {}
    end
    
    return base_params
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)
    
    -- Handle legacy parameter mapping for nouns
    if poscat == "nouns" then
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
    elseif poscat == "verbs" then
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
        
        if args and not args then
            args = args
        end
    end

    -- 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 transliterations
    local function process_translits(heads, args)
        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 or cls_raw
            local tr = clean_translit(args)

            local cls_tr = ""
            local ir_tr = ""

            if cls_raw then
                cls_tr = fa_cls.tr(cls_raw) or ""
            end
            if ir_raw then
                ir_tr = fa_ira.IRA_tr(ir_raw) or ""
            end

            cls_list = cls_tr
            ir_list = ir_tr
            tr_list = tr
        end

        return cls_list, ir_list, tr_list
    end

    local cls_list, ir_list, tr_list = process_translits(heads, args)

    if #heads == 1 then
        -- Single head: combine all transliterations
        local tr_overrides = {}
        for i = 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 i = 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

        data.heads = heads
        data.translits = final_tr
    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)
    for i = 1, 3 do
        local cls = args
        local tg = args

        if 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(data.inflections, {
                    label = (i == 1 and "Tajik spelling" or "<i>or</i>"),
                    { term = tg, lang = require("Module:languages").getByCode("tg") }
                })
            end
        end
    end
end

-- Get inflection forms helper
local function get_inflection_forms(args, prefix)
    local forms = {}
    for i = 1, 4 do
        local key = prefix .. (i == 1 and "" or tostring(i))
        local form = args
        if form then
            local translit_key = key .. "tr"
            local translit = clean_translit(args)
            table.insert(forms, {term = form, translit = translit})
        end
    end
    return forms
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 tr_variants = {}
            
            -- Main translit parameter
            local main_tr_key = "pl" .. (i == 1 and "" or tostring(i)) .. "tr"
            local main_tr = clean_translit(args)
            if not main_tr then
                main_tr = clean_translit(args)
            end
            
            local alt_tr2 = clean_translit(args)
            local alt_tr3 = clean_translit(args)
            
            if not main_tr then
                local base = data.heads
                local base_zwnj = export.ZWNJ(base)
                local has_zwnj = (base_zwnj ~= "")
                
                local suffix_map = {
                     = {has_zwnj and "-hā" or "hā", has_zwnj and "-hâ" or "hâ"},
                     = {"āt", "ât"}, 
                     = {"ān", "ân"},
                     = {"yān", "yân"}
                }
                
                local applied_suffix
                for suffix, _ in pairs(suffix_map) do
                    if pl == base .. suffix or pl == base .. base_zwnj .. suffix then
                        applied_suffix = suffix
                        break
                    end
                end
                
                if applied_suffix and suffix_map then
                    local cls_suffix = suffix_map
                    local ir_suffix = suffix_map
                    
                    local cls_tr_list = {}
                    local ir_tr_list = {}
                    local seen_cls = {}
                    local seen_ir = {}
                    
                    for j = 1, 3 do
                        local cls_raw = args
                        local ir_raw = args
                        
                        if cls_raw then
                            -- Handle comma-separated values
                            for _, form in ipairs(mw.text.split(cls_raw, ",", true)) do
                                form = mw.text.trim(form)
                                if not seen_cls then
                                    seen_cls = true
                                    local cls_tr = fa_cls.tr(form)
                                    if cls_tr and cls_tr ~= "" then
                                        local final_cls_suffix = cls_suffix
                                        if applied_suffix == "یان" and (mw.ustring.match(cls_tr, "$")) then
                                            final_cls_suffix = "yān"
                                        end
                                        table.insert(cls_tr_list, cls_tr .. final_cls_suffix)
                                    end
                                end
                            end
                        end
                        
                        if ir_raw then
                            -- Handle comma-separated values
                            for _, form in ipairs(mw.text.split(ir_raw, ",", true)) do
                                form = mw.text.trim(form)
                                if not seen_ir then
                                    seen_ir = true
                                    local ir_tr = fa_ira.IRA_tr(form)
                                    if ir_tr and ir_tr ~= "" then
                                        local final_ir_suffix = ir_suffix
                                        if applied_suffix == "یان" and mw.ustring.match(ir_tr, "i$") then
                                            final_ir_suffix = "yân"
                                        end
                                        table.insert(ir_tr_list, ir_tr .. final_ir_suffix)
                                    end
                                end
                            end
                        elseif cls_raw and not ir_raw then
                            for _, form in ipairs(mw.text.split(cls_raw, ",", true)) do
                                form = mw.text.trim(form)
                                if not seen_ir then
                                    seen_ir = true
                                    local ir_tr = fa_ira.IRA_tr(form)
                                    if ir_tr and ir_tr ~= "" then
                                        local final_ir_suffix = ir_suffix
                                        if applied_suffix == "یان" and mw.ustring.match(ir_tr, "i$") then
                                            final_ir_suffix = "yân"
                                        end
                                        table.insert(ir_tr_list, ir_tr .. final_ir_suffix)
                                    end
                                end
                            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
                        main_tr = (cls_str == ir_str) and cls_str or (cls_str .. " / " .. ir_str)
                    elseif cls_str ~= "" then
                        main_tr = cls_str
                    elseif ir_str ~= "" then
                        main_tr = ir_str
                    end
                end
            end
            
            if main_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
            
            -- Create final transliteration string
            local final_tr = (#tr_variants > 0) and table.concat(tr_variants, " <i>or</i> ") or nil
            
            -- Add to inflections
            table.insert(data.inflections, {
                label = (i == 1 and "plural" or "<i>or</i>"),
                {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
            local prstem_translits = {}
            
            if #prstems == 1 then
                -- Single present stem: process multiple transliteration variants
                local cls_list = {}
                local ir_list = {}
                local tr_list = {}

                for i = 1, 3 do
                    local cls_raw = args
                    local ir_raw = args or cls_raw
                    local tr = clean_translit(args)

                    local cls_tr = ""
                    local ir_tr = ""

                    if cls_raw then
                        cls_tr = fa_cls.tr(cls_raw) or ""
                    end
                    if ir_raw then
                        ir_tr = fa_ira.IRA_tr(ir_raw) or ""
                    end

                    cls_list = cls_tr
                    ir_list = ir_tr
                    tr_list = tr
                end

                local tr_overrides = {}
                for i = 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 i = 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

                prstem_translits = final_tr
            else
                -- Multiple present stems: assign translit to stem
                for i = 1, #prstems do
                    local cls_list = {}
                    local ir_list = {}
                    local tr_list = {}

                    for j = 1, 3 do
                        local cls_raw, ir_raw, tr
                        
                        if i == 1 then
                            cls_raw = args
                            ir_raw = args or cls_raw
                            tr = clean_translit(args)
                        else
                            local stem_prefix = "prstem" .. tostring(i)
                            cls_raw = (j == 1) and args or args
                            ir_raw = (j == 1) and args or args
                            if not ir_raw then ir_raw = cls_raw end
                            tr = clean_translit((j == 1) and args or args)
                        end

                        local cls_tr = ""
                        local ir_tr = ""

                        if cls_raw then
                            cls_tr = fa_cls.tr(cls_raw) or ""
                        end
                        if ir_raw then
                            ir_tr = fa_ira.IRA_tr(ir_raw) or ""
                        end

                        cls_list = cls_tr
                        ir_list = ir_tr
                        tr_list = tr
                    end

                    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

                    prstem_translits = final_tr
                end
            end
            
            for i, stem in ipairs(prstems) do
                table.insert(data.inflections, {
                    label = (i == 1 and "present stem" or "<i>or</i>"),
                    {term = stem, translit = prstem_translits}
                })
            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