ویکی‌واژه fawiktionary https://fa.wiktionary.org/wiki/%D9%88%DB%8C%DA%A9%DB%8C%E2%80%8C%D9%88%D8%A7%DA%98%D9%87:%D8%B5%D9%81%D8%AD%D9%87%D9%94_%D8%A7%D8%B5%D9%84%DB%8C MediaWiki 1.39.0-wmf.21 case-sensitive مدیا ویژه بحث کاربر بحث کاربر ویکی‌واژه بحث ویکی‌واژه پرونده بحث پرونده مدیاویکی بحث مدیاویکی الگو بحث الگو راهنما بحث راهنما رده بحث رده پیوست بحث پیوست TimedText TimedText talk پودمان بحث پودمان ابزار بحث ابزار توضیحات ابزار بحث توضیحات ابزار baby 0 12242 847588 809912 2022-07-23T15:10:31Z Beginneruser 11037 wikitext text/x-wiki ==انگلیسی== ==ریشه‌شناسی== {{multiple images |direction = vertical |image1 = Baby.jpg |caption1 = بچه‌ی آدم |image2 = Baby ginger monkey.jpg |caption2 = بچه‌ی [[monkey#Noun|میمون]] |image3 = Smaller Babyelephant45 from wiki commons.jpg |caption3 = بچه‌ی [[فیل]] }} ===فعل=== {{en-verb|babies|babying|babied|babied}} #[[مانند]] [[کودک]] [[رفتارکردن]] ===اسم=== {{en-noun|bab|ies}} #[[بچه]] #[[کودک]] # <!--'''baby'''--> [[رده:فعل‌های انگلیسی]] hvj9s7n163uclupwxe2a9txogyz38i9 847589 847588 2022-07-23T15:11:09Z Beginneruser 11037 wikitext text/x-wiki ==انگلیسی== ===ریشه‌شناسی=== {{multiple images |direction = vertical |image1 = Baby.jpg |caption1 = بچه‌ی آدم |image2 = Baby ginger monkey.jpg |caption2 = بچه‌ی [[monkey#Noun|میمون]] |image3 = Smaller Babyelephant45 from wiki commons.jpg |caption3 = بچه‌ی [[فیل]] }} ===فعل=== {{en-verb|babies|babying|babied|babied}} #[[مانند]] [[کودک]] [[رفتارکردن]] ===اسم=== {{en-noun|bab|ies}} #[[بچه]] #[[کودک]] # <!--'''baby'''--> 53z90x9clrmfp8fbp1j6phvng5pz23q الگو:فعل-ان 10 14500 847569 759903 2022-07-23T14:15:04Z Beginneruser 11037 تغییرمسیر به [[الگو:en-verb]] wikitext text/x-wiki #تغییرمسیر [[الگو:en-verb]] 2h0roya8jatj0gluejqoei1povl5sfz رده:فعل‌های انگلیسی 14 18217 847582 759122 2022-07-23T14:51:34Z Beginneruser 11037 wikitext text/x-wiki [[رده:بن‌واژه‌های انگلیسی]] 248o5vdnndz6utkut09t4jt3hcn44kl الگو:en-noun 10 26305 847573 844697 2022-07-23T14:20:09Z Beginneruser 11037 wikitext text/x-wiki {{#invoke:en-headword|show|فعل‌های}}<noinclude>{{documentation}}</noinclude> qb9rumnzubhkyt7f2ecef6rl22f3wjz الگو:en-verb 10 26370 847570 150600 2022-07-23T14:15:09Z Beginneruser 11037 تغییرمسیر به [[الگو:فعل-ان]] حذف شد wikitext text/x-wiki {{#invoke:en-headword|show|verbs}} egiobnxcyqez9faudy6ah32gjxuaoae 847572 847570 2022-07-23T14:19:21Z Beginneruser 11037 wikitext text/x-wiki {{#invoke:en-headword|show|فعل‌های}} 6j4iqfja67nzvbl1qd91s1tkfeb7qsh 847574 847572 2022-07-23T14:20:25Z Beginneruser 11037 wikitext text/x-wiki {{#invoke:en-headword|show|فعل‌های}}<noinclude>{{documentation}}</noinclude> qb9rumnzubhkyt7f2ecef6rl22f3wjz یافرعی 0 75997 847562 514160 2022-07-23T13:16:06Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} ==فارسی== ====برگردان‌ها==== ;{{انگلیسی}}: [[by line]] s0noe9d5gi37onxrpmrbpzbxke25liz لاستيكماشين 0 94924 847597 336123 2022-07-23T17:41:21Z EmausBot 19188 ربات: اصلاح تغییرمسیر دوتایی به [[لاستیک‌ماشین]] wikitext text/x-wiki #تغییر_مسیر [[لاستیک‌ماشین]] j1eglr72rebbeph81gpe34m07dpz1q8 پودمان:en-headword 828 159180 847566 844743 2022-07-23T13:46:49Z Beginneruser 11037 Localization Scribunto text/plain local export = {} local pos_functions = {} local lang = require("Module:languages").getByCode("en") local PAGENAME = mw.title.getCurrentTitle().text local function glossary_link(entry, text) text = text or entry return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]" end local function track(page) require("Module:debug").track("en-headword/" .. page) return true end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") local params = { ["head"] = {list = true}, ["suff"] = {type = "boolean"}, ["sort"] = {}, } local pos_data = pos_functions[poscat] if pos_data then for key, val in pairs(pos_data.params) do params[key] = val end end local args, unknown_args = require("Module:parameters").process(frame:getParent().args, params, pos_data.return_unknown) if unknown_args and next(unknown_args) then track("unknown args") track("unknown args/POS/" .. tostring(poscat)) for parameter, value in pairs(unknown_args) do track("unknown args/param/" .. tostring(parameter)) mw.log("unknown parameter in [[Module:headword]]: |" .. tostring(parameter) .. "=" .. tostring(value)) end end local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], inflections = {}} if #data.heads == 0 and args.pagename then table.insert(data.heads, args.pagename) end if args["suff"] then data.pos_category = "suffixes" if poscat == "صفت‌ها" or poscat == "قید‌ها" or poscat == "اسم‌ها" or poscat == "فعل‌ها" then table.insert(data.categories, ("%s %s-forming suffixes") :format(lang:getCanonicalName(), poscat:gsub("s$", ""))) else error("No category exists for suffixes forming " .. poscat .. ".") end end if pos_data then pos_data.func(args, data) end local extra_categories = {} if PAGENAME:find("[Qq][^Uu]") or PAGENAME:find("[Qq]$") then table.insert(data.categories, lang:getCanonicalName() .. " words containing Q not followed by U") end if PAGENAME:find("([A-Za-z])%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing three consecutive instances of the same letter") end if PAGENAME:find("([A-Za-z])%1%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing four consecutive instances of the same letter") end -- mw.ustring.toNFD performs decomposition, so letters that decompose -- to an ASCII vowel and a diacritic, such as é, are counted as vowels and -- do not need to be included in the pattern. if not mw.ustring.find(mw.ustring.lower(mw.ustring.toNFD(PAGENAME)), "[aeiouyæœø]") then table.insert(data.categories, lang:getCanonicalName() .. " words without vowels") end if PAGENAME:find("yre$") then table.insert(data.categories, lang:getCanonicalName() .. ' words ending in "-yre"') end if not PAGENAME:find(" ") and PAGENAME:len() >= 25 then table.insert(extra_categories, "Long " .. lang:getCanonicalName() .. ' words') end if PAGENAME:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then table.insert(data.categories, lang:getCanonicalName() .. ' words that use all vowels in alphabetical order') end data.sort_key = args.sort return require("Module:headword").full_headword(data) .. (#extra_categories > 0 and require("Module:utilities").format_categories(extra_categories, lang, args.sort) or "") end -- This function does the common work between adjectives and adverbs function make_comparatives(params, data) local comp_parts = {label = glossary_link("comparative"), accel = {form = "comparative"}} local sup_parts = {label = glossary_link("superlative"), accel = {form = "superlative"}} if #params == 0 then table.insert(params, {"more"}) end -- To form the stem, replace -(e)y with -i and remove a final -e. local stem = PAGENAME:gsub("([^aeiou])e?y$", "%1i"):gsub("e$", "") -- Go over each parameter given and create a comparative and superlative form for i, val in ipairs(params) do local comp = val[1] local comp_qual = val[2] local sup = val[3] local sup_qual = val[4] local comp_part, sup_part if comp == "more" and PAGENAME ~= "many" and PAGENAME ~= "much" then comp_part = "[[more]] " .. PAGENAME sup_part = "[[most]] " .. PAGENAME elseif comp == "further" and PAGENAME ~= "far" then comp_part = "[[further]] " .. PAGENAME sup_part = "[[furthest]] " .. PAGENAME elseif comp == "er" then comp_part = stem .. "er" sup_part = stem .. "est" elseif comp == "-" or sup == "-" then -- Allowing '-' makes it more flexible to not have some forms if comp ~= "-" then comp_part = comp end if sup ~= "-" then sup_part = sup end else -- If the full comparative was given, but no superlative, then -- create it by replacing the ending -er with -est. if not sup then if comp:find("er$") then sup = comp:gsub("er$", "est") else error("The superlative of \"" .. comp .. "\" cannot be generated automatically. Please provide it with the \"sup" .. (i == 1 and "" or i) .. "=\" parameter.") end end comp_part = comp sup_part = sup end if comp_part then table.insert(comp_parts, {term = comp_part, qualifiers = {comp_qual}}) end if sup_part then table.insert(sup_parts, {term = sup_part, qualifiers = {sup_qual}}) end end table.insert(data.inflections, comp_parts) table.insert(data.inflections, sup_parts) end pos_functions["adjectives"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 local is_not_comparable = false local is_comparative_only = false -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 is_not_comparable = true -- If the only argument is +, then remember this and clear parameters elseif args[1][1] == "+" and args[1].maxindex == 1 then shift = 1 is_comparative_only = true end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. -- If there are parameters, then show "not generally comparable" -- before the forms. if #params == 0 then if is_not_comparable then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adjectives") return end if is_comparative_only then table.insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) table.insert(data.categories, lang:getCanonicalName() .. " comparative-only adjectives") return end else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["adverbs"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. If there are parameters, -- then show "not generally comparable" before the forms. if #params == 0 then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adverbs") return else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["conjunctions"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } pos_functions["interjections"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } local function default_plural(noun) local new_pl if noun:find("[sxz]$") or noun:find("[cs]h$") then new_pl = noun .. "es" elseif noun:find("[^aeiou]y$") then new_pl = noun:gsub("y$", "i") .. "es" else new_pl = noun .. "s" end return new_pl end local function canonicalize_plural(pl, stem) if pl == "s" then return stem .. "s" elseif pl == "es" then return stem .. "es" elseif pl == "+" then return default_plural(PAGENAME) else return nil end end pos_functions["اسم‌های"] = { params = { [1] = {list = true, allow_holes = true}, ["pl=qual"] = { list = true, allow_holes = true }, }, func = function(args, data) -- Gather all the plural parameters from the numbered parameters. local plurals = {} for i = 1, args[1].maxindex do local pl = args[1][i] if pl then local qual = args["plqual"][i] if qual then table.insert(plurals, {term = pl, qualifiers = {qual}}) else table.insert(plurals, pl) end end end -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) else table.insert(data.inflections, {label = glossary_link("شمارش‌ناپذیر")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("شمارش‌پذیر") .. " و " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end -- The default, always has a plural else table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local function check_ies(pl, stem) local newplural, nummatches = stem:gsub("([^aeiou])y$","%1ies") return nummatches > 0 and pl == newplural end local stem = PAGENAME local irregular = false for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl, stem) if canon_pl then table.insert(pl_parts, canon_pl) elseif type(pl) == "table" then canon_pl = canonicalize_plural(pl.term, stem) if canon_pl then table.insert(pl_parts, {term=canon_pl, qualifiers=pl.qualifiers}) end end if not canon_pl then table.insert(pl_parts, pl) if type(pl) == "table" then pl = pl.term end if not stem:find(" ") and not (pl == stem .. "s" or pl == stem .. "es" or check_ies(pl, stem)) then irregular = true if pl == stem then table.insert(data.categories, lang:getCanonicalName() .. " indeclinable nouns") end end end end if irregular then table.insert(data.categories, "اسم‌های دارای جمع‌های باقاعده " .. lang:getCanonicalName()) end table.insert(data.inflections, pl_parts) end } pos_functions["proper nouns"] = { params = { [1] = {list = true}, }, func = function(args, data) local plurals = args[1] -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") -- If no plural was given, add a default one now if #plurals == 0 then plurals = {"s"} end elseif #plurals > 0 then table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local stem = PAGENAME for i, pl in ipairs(plurals) do if pl == "s" then table.insert(pl_parts, stem .. "s") elseif pl == "es" then table.insert(pl_parts, stem .. "es") else table.insert(pl_parts, pl) end end table.insert(data.inflections, pl_parts) end } local function base_default_verb_forms(verb) local s_form = default_plural(verb) local ing_form, ed_form local vowel = "aeiouáéíóúàèìòùâêîôûäëïöüæœø" local ulvowel = vowel .. "AEIOUÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÆŒØ" -- (1) Check for C*VC verbs. -- -- flip -> flipping/flipped, strum -> strumming/strummed, nag -> nagging/nagged, etc. -- Do not include words with final -y, e.g. 'stay' (staying/stayed), 'toy' (toying/toyed), -- or with final -w, e.g. 'flow' (flowing/flowed), or with final -h, e.g. 'ah' (ahing/ahed), -- or with final -x, e.g. 'box' (boxing/boxed), or ending in an uppercase consonant, -- e.g. 'XOR' (XORing/XORed), 'OK' (OKing/OKed). Check specially for initial y- as a consonant, -- e.g. 'yip' (yipping/yipped), otherwise treat y as a vowel, so we don't trigger on 'hyphen' -- but do trigger on 'gyp'. local last_cons = mw.ustring.match(verb, "^[Yy][" .. vowel .. "y]([^A-Z" .. vowel .. "ywxh])$") if not last_cons then last_cons = mw.ustring.match(verb, "^[^" .. ulvowel .. "yY]*[" .. ulvowel .. "yY]([^A-Z" .. vowel .. "ywxh])$") end if last_cons then ing_form = verb .. last_cons .. "ing" ed_form = verb .. last_cons .. "ed" else -- (2) Generate -ing form. -- (2a) lie -> lying, untie -> untying, etc. local stem = verb:match("^(.*)ie$") if stem then ing_form = stem .. "ying" else -- (2b) argue -> arguing, sprue -> spruing, dialogue -> dialoguing, etc. stem = verb:match("^(.*)ue$") if stem then ing_form = stem .. "uing" else stem = mw.ustring.match(verb, "^(.*[" .. ulvowel .. "yY][^" .. vowel .. "y]+)e$") if stem then -- (2c) baptize -> baptizing, rake -> raking, type -> typing, parse -> parsing, etc. -- (ending in vowel + consonant(s) + -e); but not referee -> refereeing, -- backhoe -> backhoeing, redye -> redyeing (ending in some other vowel + -e or in -ye); -- and not be -> being (no vowel before the consonant preceding the -e) ing_form = stem .. "ing" else -- (2d) regular verbs ing_form = verb .. "ing" end end end -- (3) Generate -ed form. if verb:find("e$") then -- (3a) baptize -> baptized, rake -> raked, parse -> parsed, free -> freed, hoe -> hoed ed_form = verb .. "d" else stem = mw.ustring.match(verb, "^(.*[^" .. ulvowel .. "yY])y$") if stem then -- (3b) marry -> married, levy -> levied, try -> tried, etc.; but not toy -> toyed ed_form = stem .. "ied" else -- (3c) regular verbs ed_form = verb .. "ed" end end end return s_form, ing_form, ed_form end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil end end pos_functions["فعل‌های"] = { params = { [1] = {list = "pres_3sg", allow_holes = true}, ["pres_3sg_qual"] = {list = "pres_3sg=_qual", allow_holes = true}, [2] = {list = "pres_ptc", allow_holes = true}, ["pres_ptc_qual"] = {list = "pres_ptc=_qual", allow_holes = true}, [3] = {list = "past", allow_holes = true}, ["past_qual"] = {list = "past=_qual", allow_holes = true}, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc_qual"] = {list = "past_ptc=_qual", allow_holes = true}, ["pagename"] = {}, -- for testing }, func = function(args, data) -- Get parameters local par1 = args[1][1] local par2 = args[2][1] local par3 = args[3][1] local par4 = args[4][1] local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = args.pagename or PAGENAME ------------------------------------------- UTILITY FUNCTIONS #1 ------------------------------------------ -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(verb) local last_cons = verb:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. verb .. "' must end in a consonant to use ++") end return verb .. last_cons end local function compute_plusplus_s_form(verb, default_s_form) if verb:find("[sz]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(verb) .. "es" else return default_s_form end end ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local new_default_s, new_default_ing, new_default_ed, split_default_s, split_default_ing, split_default_ed = default_verb_forms(pagename) local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Verb '" .. verb .. "' must have a space in it to use ++*") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("First word '" .. first .. "' must end in a consonant to use ++*") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form) if form == nil then error("Verb '" .. pagename .. "' must have a space in it to use * or ++*") end return form end local function sub_tilde(form) if not form then return nil end local retval = form:gsub("~", pagename) -- discard second return value return retval end local function canonicalize_s_form(form) if form == "+" then return new_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s) elseif form == "++" then return compute_plusplus_s_form(pagename, new_default_s) elseif form == "++*" then if pagename:find("^[^ ]*[sz] ") then return compute_double_last_cons_stem_of_split_verb(pagename, "es") else return check_non_nil_star_form(split_default_s) end else return sub_tilde(form) end end local function canonicalize_ing_form(form) if form == "+" then return new_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ing" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ing") else return sub_tilde(form) end end local function canonicalize_ed_form(form) if form == "+" then return new_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ed" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ed") else return sub_tilde(form) end end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local past_ptcs_given if par1 and par1:find("<") then -------------------------- ANGLE-BRACKET FORMAT -------------------------- if par2 or par3 or par4 then error("Can't specify 2=, 3= or 4= when 1= contains angle brackets: " .. par1) end -- In the angle bracket format, we always copy the full past tense specs to the past participle -- specs if none of the latter are given, so act as if the past participle is always given. -- There is a separate check to see if the past tense and past participle are identical, in any case. past_ptcs_given = true local iut = require("Module:inflection utilities") -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = iut.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = iut.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec: " .. angle_bracket_spec) end local function fetch_qualifiers(separated_group) local qualifiers for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed qualifiers: '" .. table.concat(separated_group) .. "'") end if not qualifiers then qualifiers = {} end table.insert(qualifiers, separated_group[j]) end return qualifiers end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{}} end local specs = {} local colon_separated_groups = iut.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "++*" then error("* and ++* not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = nil end table.insert(specs, {form = form, qualifiers = fetch_qualifiers(colon_separated_group)}) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) for _, spec in ipairs(s_specs) do if spec.form == "++" and #ing_specs == 1 and not ing_specs[1].form and not ing_specs[1].qualifiers and #ed_specs == 1 and not ed_specs[1].form and not ed_specs[1].qualifiers then ing_specs[1].form = "++" ed_specs[1].form = "++" break end end return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(par1, parse_props) -- (2) Remove any links from the lemma, but remember the original form -- so we can use it below in the 'lemma_linked' form. iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = require("Module:links").remove_links(base.lemma) end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local def_s_form, def_ing_form, def_ed_form = base_default_verb_forms(base.lemma) local function process_specs(slot, specs, default_form, canonicalize_plusplus) for _, spec in ipairs(specs) do local form = spec.form if not form or form == "+" then form = default_form elseif form == "++" then form = canonicalize_plusplus() end -- If there's a ~ in the form, substitute it with the lemma, -- but make sure to first replace % in the lemma with %% so that -- it doesn't get interpreted as a capture replace expression. if form:find("~") then -- Assign to a var because gsub returns multiple values. local subbed_lemma = base.lemma:gsub("%%", "%%%%") form = form:gsub("~", subbed_lemma) end -- If the form is -, don't insert any forms, which will result -- in there being no overall forms (in fact it will be nil). -- We check for that down below and substitute a single "-" as -- the form, which in turn gets turned into special labels like -- "no present participle". if form ~= "-" then iut.insert_form(base.forms, slot, {form = form, footnotes = spec.qualifiers}) end end end process_specs("s_form", base.s_specs, def_s_form, function() return compute_plusplus_s_form(base.lemma, def_s_form) end) process_specs("ing_form", base.ing_specs, def_ing_form, function() return compute_double_last_cons_stem(base.lemma) .. "ing" end) process_specs("ed_form", base.ed_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) -- If the -en spec is completely missing, substitute the -ed spec in its entirely. -- Otherwise, if individual -en forms are missing or use +, we will substitute the -- default -ed form, as with the -ed spec. local en_specs = base.en_specs if #en_specs == 1 and not en_specs[1].form and not en_specs[1].qualifiers then en_specs = base.ed_specs end process_specs("en_form", en_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) iut.insert_form(base.forms, "lemma", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.orig_lemma:find("%[%[") then return base.orig_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_forms(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - -- for a spec. if not forms or #forms == 0 then forms = {{form = "-"}} end return forms end pres_3sgs = fetch_forms("s_form") pres_ptcs = fetch_forms("ing_form") pasts = fetch_forms("ed_form") past_ptcs = fetch_forms("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given. -- If no links in this form and it has multiple words, autolink the individual words. -- The user can override this using head=. if #data.heads == 0 then for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do local lemma = lemma_obj.form if not lemma:find("%[%[") then local m_headword = require("Module:headword") if m_headword.head_is_multiword(lemma) then lemma = m_headword.add_multiword_links(lemma) end end table.insert(data.heads, lemma) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- local pres_3sg, pres_ptc, past if par1 and not par2 and not par3 then -- Use of a single parameter other than "++", "*" or "++*" is now the "legacy" format, -- and no longer supported. if par1 == "es" or par1 == "ies" or par1 == "d" then error("Legacy parameter 1=es/ies/d no longer supported, just use 'en-verb' without params") elseif par1 == "++" or par1 == "*" or par1 == "++*" then pres_3sg = canonicalize_s_form(par1) pres_ptc = canonicalize_ing_form(par1) past = canonicalize_ed_form(par1) else error("Legacy parameter 1=STEM no longer supported, just use 'en-verb' without params") end else if par3 then track("xxx3") elseif par2 then track("xxx2") end end if not pres_3sg or not pres_ptc or not past then -- Either all three should be set above, or none of them. assert(not pres_3sg and not pres_ptc and not past) if par1 then pres_3sg = canonicalize_s_form(par1) else pres_3sg = new_default_s end if par2 then pres_ptc = canonicalize_ing_form(par2) else pres_ptc = new_default_ing end if par3 then past = canonicalize_ed_form(par3) else past = new_default_ed end end if par4 then past_ptcs_given = true past_ptc = canonicalize_ed_form(par4) else past_ptc = past end pres_3sgs = {{form = pres_3sg}} pres_ptcs = {{form = pres_ptc}} pasts = {{form = past}} past_ptcs = {{form = past_ptc}} end ------------------------------------------- HANDLE OVERRIDES ------------------------------------------ local pres_3sg_infls, pres_ptc_infls, past_infls, past_ptc_infls local function strip_brackets(qualifiers) if not qualifiers then return nil end local stripped_qualifiers = {} for _, qualifier in ipairs(qualifiers) do local stripped_qualifier = qualifier:match("^%[(.*)%]$") if not stripped_qualifier then error("Internal error: Qualifier should be surrounded by brackets at this stage: " .. qualifier) end table.insert(stripped_qualifiers, stripped_qualifier) end return stripped_qualifiers end local function collect_forms(label, accel_form, defaults, overrides, override_qualifiers, canonicalize) if defaults[1].form == "-" then return {label = "no " .. label} else local into_table = {label = label, accel = {form = accel_form}} local maxindex = math.max(#defaults, overrides.maxindex) local qualifiers = override_qualifiers[1] and {override_qualifiers[1]} or strip_brackets(defaults[1].footnotes) table.insert(into_table, {term = defaults[1].form, qualifiers = qualifiers}) -- Present 3rd singular for i = 2, maxindex do local override_form = canonicalize(overrides[i]) if override_form then -- If there is an override such as past_ptc2=..., only use the qualifier specified -- using an override (past_ptc2_qual=...), if any; it doesn't make sense to combine -- an override form with a qualifier specified inside of angle brackets. table.insert(into_table, {term = override_form, qualifiers = {override_qualifiers[i]}}) elseif defaults[i] then -- If the form comes from inside angle brackets, allow any override qualifier -- (past_ptc2_qual=...) to override any qualifier specified inside of angle brackets. -- FIXME: Maybe we should throw an error here if both exist. local qualifiers = override_qualifiers[i] and {override_qualifiers[i]} or strip_brackets(defaults[i].footnotes) table.insert(into_table, {term = defaults[i].form, qualifiers = qualifiers}) end end return into_table end end local pres_3sg_infls = collect_forms("third-person singular simple present", "3|s|pres", pres_3sgs, args[1], args.pres_3sg_qual, canonicalize_s_form) local pres_ptc_infls = collect_forms("present participle", "pres|ptcp", pres_ptcs, args[2], args.pres_ptc_qual, canonicalize_ing_form) local past_infls = collect_forms("simple past", "past", pasts, args[3], args.past_qual, canonicalize_ed_form) local past_ptc_infls = collect_forms("past participle", "past|ptcp", past_ptcs, args[4], args.past_ptc_qual, canonicalize_ed_form) -- Are the past forms identical to the past participle forms? If so, we use a single -- combined "simple past and past participle" label on the past tense forms. -- We check for two conditions: Either no past participle forms were given at all, or -- they were given but are identical in every way (all forms and qualifiers) to the past -- tense forms. The former "no explicit past participle forms" check is important in the -- "separate-parameter" format; if past tense overrides are given and no past participle -- forms given, the past tense overrides should apply to the past participle as well. -- In the angle-bracket format, it's expected that all forms and qualifiers are specified -- using that format, and we explicitly copy past tense forms and qualifiers to past -- participle ones if the latter are omitted, so we disable to "no explicit past participle -- forms" check. if args[4].maxindex > 0 or args.past_ptc_qual.maxindex > 0 then past_ptcs_given = true end local identical = true -- For the past and past participle to be identical, there must be -- the same number of inflections, and each inflection must match -- in term and qualifiers. if #past_infls ~= #past_ptc_infls then identical = false else for key, val in ipairs(past_infls) do if past_ptc_infls[key].term ~= val.term then identical = false break else local quals1 = past_ptc_infls[key].qualifiers local quals2 = val.qualifiers if (not not quals1) ~= (not not quals2) then -- one is nil, the other is not identical = false elseif quals1 and quals2 then -- qualifiers present in both; each qualifier must match if #quals1 ~= #quals2 then identical = false else for k, v in ipairs(quals1) do if v ~= quals2[k] then identical = false break end end end end if not identical then break end end end end -- Insert the forms table.insert(data.inflections, pres_3sg_infls) table.insert(data.inflections, pres_ptc_infls) if not past_ptcs_given or identical then if past_ptcs[1].form == "-" then past_infls.label = "no simple past or past participle" else past_infls.label = "simple past and past participle" past_infls.accel = {form = "past|and|past|ptcp"} end table.insert(data.inflections, past_infls) else table.insert(data.inflections, past_infls) table.insert(data.inflections, past_ptc_infls) end end } return export 7nqlxe5tnm3b4csey6nrbmqhqiwx13s 847567 847566 2022-07-23T13:49:24Z Beginneruser 11037 خنثی‌سازی نسخهٔ 847566 از [[Special:Contributions/Beginneruser|Beginneruser]] ([[User talk:Beginneruser|بحث]]) Scribunto text/plain local export = {} local pos_functions = {} local lang = require("Module:languages").getByCode("en") local PAGENAME = mw.title.getCurrentTitle().text local function glossary_link(entry, text) text = text or entry return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]" end local function track(page) require("Module:debug").track("en-headword/" .. page) return true end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") local params = { ["head"] = {list = true}, ["suff"] = {type = "boolean"}, ["sort"] = {}, } local pos_data = pos_functions[poscat] if pos_data then for key, val in pairs(pos_data.params) do params[key] = val end end local args, unknown_args = require("Module:parameters").process(frame:getParent().args, params, pos_data.return_unknown) if unknown_args and next(unknown_args) then track("unknown args") track("unknown args/POS/" .. tostring(poscat)) for parameter, value in pairs(unknown_args) do track("unknown args/param/" .. tostring(parameter)) mw.log("unknown parameter in [[Module:headword]]: |" .. tostring(parameter) .. "=" .. tostring(value)) end end local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], inflections = {}} if #data.heads == 0 and args.pagename then table.insert(data.heads, args.pagename) end if args["suff"] then data.pos_category = "suffixes" if poscat == "صفت‌ها" or poscat == "قید‌ها" or poscat == "اسم‌ها" or poscat == "فعل‌ها" then table.insert(data.categories, ("%s %s-forming suffixes") :format(lang:getCanonicalName(), poscat:gsub("s$", ""))) else error("No category exists for suffixes forming " .. poscat .. ".") end end if pos_data then pos_data.func(args, data) end local extra_categories = {} if PAGENAME:find("[Qq][^Uu]") or PAGENAME:find("[Qq]$") then table.insert(data.categories, lang:getCanonicalName() .. " words containing Q not followed by U") end if PAGENAME:find("([A-Za-z])%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing three consecutive instances of the same letter") end if PAGENAME:find("([A-Za-z])%1%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing four consecutive instances of the same letter") end -- mw.ustring.toNFD performs decomposition, so letters that decompose -- to an ASCII vowel and a diacritic, such as é, are counted as vowels and -- do not need to be included in the pattern. if not mw.ustring.find(mw.ustring.lower(mw.ustring.toNFD(PAGENAME)), "[aeiouyæœø]") then table.insert(data.categories, lang:getCanonicalName() .. " words without vowels") end if PAGENAME:find("yre$") then table.insert(data.categories, lang:getCanonicalName() .. ' words ending in "-yre"') end if not PAGENAME:find(" ") and PAGENAME:len() >= 25 then table.insert(extra_categories, "Long " .. lang:getCanonicalName() .. ' words') end if PAGENAME:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then table.insert(data.categories, lang:getCanonicalName() .. ' words that use all vowels in alphabetical order') end data.sort_key = args.sort return require("Module:headword").full_headword(data) .. (#extra_categories > 0 and require("Module:utilities").format_categories(extra_categories, lang, args.sort) or "") end -- This function does the common work between adjectives and adverbs function make_comparatives(params, data) local comp_parts = {label = glossary_link("comparative"), accel = {form = "comparative"}} local sup_parts = {label = glossary_link("superlative"), accel = {form = "superlative"}} if #params == 0 then table.insert(params, {"more"}) end -- To form the stem, replace -(e)y with -i and remove a final -e. local stem = PAGENAME:gsub("([^aeiou])e?y$", "%1i"):gsub("e$", "") -- Go over each parameter given and create a comparative and superlative form for i, val in ipairs(params) do local comp = val[1] local comp_qual = val[2] local sup = val[3] local sup_qual = val[4] local comp_part, sup_part if comp == "more" and PAGENAME ~= "many" and PAGENAME ~= "much" then comp_part = "[[more]] " .. PAGENAME sup_part = "[[most]] " .. PAGENAME elseif comp == "further" and PAGENAME ~= "far" then comp_part = "[[further]] " .. PAGENAME sup_part = "[[furthest]] " .. PAGENAME elseif comp == "er" then comp_part = stem .. "er" sup_part = stem .. "est" elseif comp == "-" or sup == "-" then -- Allowing '-' makes it more flexible to not have some forms if comp ~= "-" then comp_part = comp end if sup ~= "-" then sup_part = sup end else -- If the full comparative was given, but no superlative, then -- create it by replacing the ending -er with -est. if not sup then if comp:find("er$") then sup = comp:gsub("er$", "est") else error("The superlative of \"" .. comp .. "\" cannot be generated automatically. Please provide it with the \"sup" .. (i == 1 and "" or i) .. "=\" parameter.") end end comp_part = comp sup_part = sup end if comp_part then table.insert(comp_parts, {term = comp_part, qualifiers = {comp_qual}}) end if sup_part then table.insert(sup_parts, {term = sup_part, qualifiers = {sup_qual}}) end end table.insert(data.inflections, comp_parts) table.insert(data.inflections, sup_parts) end pos_functions["adjectives"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 local is_not_comparable = false local is_comparative_only = false -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 is_not_comparable = true -- If the only argument is +, then remember this and clear parameters elseif args[1][1] == "+" and args[1].maxindex == 1 then shift = 1 is_comparative_only = true end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. -- If there are parameters, then show "not generally comparable" -- before the forms. if #params == 0 then if is_not_comparable then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adjectives") return end if is_comparative_only then table.insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) table.insert(data.categories, lang:getCanonicalName() .. " comparative-only adjectives") return end else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["adverbs"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. If there are parameters, -- then show "not generally comparable" before the forms. if #params == 0 then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adverbs") return else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["conjunctions"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } pos_functions["interjections"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } local function default_plural(noun) local new_pl if noun:find("[sxz]$") or noun:find("[cs]h$") then new_pl = noun .. "es" elseif noun:find("[^aeiou]y$") then new_pl = noun:gsub("y$", "i") .. "es" else new_pl = noun .. "s" end return new_pl end local function canonicalize_plural(pl, stem) if pl == "s" then return stem .. "s" elseif pl == "es" then return stem .. "es" elseif pl == "+" then return default_plural(PAGENAME) else return nil end end pos_functions["nouns"] = { params = { [1] = {list = true, allow_holes = true}, ["pl=qual"] = { list = true, allow_holes = true }, }, func = function(args, data) -- Gather all the plural parameters from the numbered parameters. local plurals = {} for i = 1, args[1].maxindex do local pl = args[1][i] if pl then local qual = args["plqual"][i] if qual then table.insert(plurals, {term = pl, qualifiers = {qual}}) else table.insert(plurals, pl) end end end -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) else table.insert(data.inflections, {label = glossary_link("شمارش‌ناپذیر")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("شمارش‌پذیر") .. " و " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end -- The default, always has a plural else table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local function check_ies(pl, stem) local newplural, nummatches = stem:gsub("([^aeiou])y$","%1ies") return nummatches > 0 and pl == newplural end local stem = PAGENAME local irregular = false for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl, stem) if canon_pl then table.insert(pl_parts, canon_pl) elseif type(pl) == "table" then canon_pl = canonicalize_plural(pl.term, stem) if canon_pl then table.insert(pl_parts, {term=canon_pl, qualifiers=pl.qualifiers}) end end if not canon_pl then table.insert(pl_parts, pl) if type(pl) == "table" then pl = pl.term end if not stem:find(" ") and not (pl == stem .. "s" or pl == stem .. "es" or check_ies(pl, stem)) then irregular = true if pl == stem then table.insert(data.categories, lang:getCanonicalName() .. " indeclinable nouns") end end end end if irregular then table.insert(data.categories, "اسم‌های دارای جمع‌های باقاعده " .. lang:getCanonicalName()) end table.insert(data.inflections, pl_parts) end } pos_functions["proper nouns"] = { params = { [1] = {list = true}, }, func = function(args, data) local plurals = args[1] -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") -- If no plural was given, add a default one now if #plurals == 0 then plurals = {"s"} end elseif #plurals > 0 then table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local stem = PAGENAME for i, pl in ipairs(plurals) do if pl == "s" then table.insert(pl_parts, stem .. "s") elseif pl == "es" then table.insert(pl_parts, stem .. "es") else table.insert(pl_parts, pl) end end table.insert(data.inflections, pl_parts) end } local function base_default_verb_forms(verb) local s_form = default_plural(verb) local ing_form, ed_form local vowel = "aeiouáéíóúàèìòùâêîôûäëïöüæœø" local ulvowel = vowel .. "AEIOUÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÆŒØ" -- (1) Check for C*VC verbs. -- -- flip -> flipping/flipped, strum -> strumming/strummed, nag -> nagging/nagged, etc. -- Do not include words with final -y, e.g. 'stay' (staying/stayed), 'toy' (toying/toyed), -- or with final -w, e.g. 'flow' (flowing/flowed), or with final -h, e.g. 'ah' (ahing/ahed), -- or with final -x, e.g. 'box' (boxing/boxed), or ending in an uppercase consonant, -- e.g. 'XOR' (XORing/XORed), 'OK' (OKing/OKed). Check specially for initial y- as a consonant, -- e.g. 'yip' (yipping/yipped), otherwise treat y as a vowel, so we don't trigger on 'hyphen' -- but do trigger on 'gyp'. local last_cons = mw.ustring.match(verb, "^[Yy][" .. vowel .. "y]([^A-Z" .. vowel .. "ywxh])$") if not last_cons then last_cons = mw.ustring.match(verb, "^[^" .. ulvowel .. "yY]*[" .. ulvowel .. "yY]([^A-Z" .. vowel .. "ywxh])$") end if last_cons then ing_form = verb .. last_cons .. "ing" ed_form = verb .. last_cons .. "ed" else -- (2) Generate -ing form. -- (2a) lie -> lying, untie -> untying, etc. local stem = verb:match("^(.*)ie$") if stem then ing_form = stem .. "ying" else -- (2b) argue -> arguing, sprue -> spruing, dialogue -> dialoguing, etc. stem = verb:match("^(.*)ue$") if stem then ing_form = stem .. "uing" else stem = mw.ustring.match(verb, "^(.*[" .. ulvowel .. "yY][^" .. vowel .. "y]+)e$") if stem then -- (2c) baptize -> baptizing, rake -> raking, type -> typing, parse -> parsing, etc. -- (ending in vowel + consonant(s) + -e); but not referee -> refereeing, -- backhoe -> backhoeing, redye -> redyeing (ending in some other vowel + -e or in -ye); -- and not be -> being (no vowel before the consonant preceding the -e) ing_form = stem .. "ing" else -- (2d) regular verbs ing_form = verb .. "ing" end end end -- (3) Generate -ed form. if verb:find("e$") then -- (3a) baptize -> baptized, rake -> raked, parse -> parsed, free -> freed, hoe -> hoed ed_form = verb .. "d" else stem = mw.ustring.match(verb, "^(.*[^" .. ulvowel .. "yY])y$") if stem then -- (3b) marry -> married, levy -> levied, try -> tried, etc.; but not toy -> toyed ed_form = stem .. "ied" else -- (3c) regular verbs ed_form = verb .. "ed" end end end return s_form, ing_form, ed_form end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil end end pos_functions["verbs"] = { params = { [1] = {list = "pres_3sg", allow_holes = true}, ["pres_3sg_qual"] = {list = "pres_3sg=_qual", allow_holes = true}, [2] = {list = "pres_ptc", allow_holes = true}, ["pres_ptc_qual"] = {list = "pres_ptc=_qual", allow_holes = true}, [3] = {list = "past", allow_holes = true}, ["past_qual"] = {list = "past=_qual", allow_holes = true}, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc_qual"] = {list = "past_ptc=_qual", allow_holes = true}, ["pagename"] = {}, -- for testing }, func = function(args, data) -- Get parameters local par1 = args[1][1] local par2 = args[2][1] local par3 = args[3][1] local par4 = args[4][1] local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = args.pagename or PAGENAME ------------------------------------------- UTILITY FUNCTIONS #1 ------------------------------------------ -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(verb) local last_cons = verb:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. verb .. "' must end in a consonant to use ++") end return verb .. last_cons end local function compute_plusplus_s_form(verb, default_s_form) if verb:find("[sz]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(verb) .. "es" else return default_s_form end end ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local new_default_s, new_default_ing, new_default_ed, split_default_s, split_default_ing, split_default_ed = default_verb_forms(pagename) local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Verb '" .. verb .. "' must have a space in it to use ++*") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("First word '" .. first .. "' must end in a consonant to use ++*") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form) if form == nil then error("Verb '" .. pagename .. "' must have a space in it to use * or ++*") end return form end local function sub_tilde(form) if not form then return nil end local retval = form:gsub("~", pagename) -- discard second return value return retval end local function canonicalize_s_form(form) if form == "+" then return new_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s) elseif form == "++" then return compute_plusplus_s_form(pagename, new_default_s) elseif form == "++*" then if pagename:find("^[^ ]*[sz] ") then return compute_double_last_cons_stem_of_split_verb(pagename, "es") else return check_non_nil_star_form(split_default_s) end else return sub_tilde(form) end end local function canonicalize_ing_form(form) if form == "+" then return new_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ing" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ing") else return sub_tilde(form) end end local function canonicalize_ed_form(form) if form == "+" then return new_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ed" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ed") else return sub_tilde(form) end end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local past_ptcs_given if par1 and par1:find("<") then -------------------------- ANGLE-BRACKET FORMAT -------------------------- if par2 or par3 or par4 then error("Can't specify 2=, 3= or 4= when 1= contains angle brackets: " .. par1) end -- In the angle bracket format, we always copy the full past tense specs to the past participle -- specs if none of the latter are given, so act as if the past participle is always given. -- There is a separate check to see if the past tense and past participle are identical, in any case. past_ptcs_given = true local iut = require("Module:inflection utilities") -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = iut.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = iut.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec: " .. angle_bracket_spec) end local function fetch_qualifiers(separated_group) local qualifiers for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed qualifiers: '" .. table.concat(separated_group) .. "'") end if not qualifiers then qualifiers = {} end table.insert(qualifiers, separated_group[j]) end return qualifiers end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{}} end local specs = {} local colon_separated_groups = iut.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "++*" then error("* and ++* not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = nil end table.insert(specs, {form = form, qualifiers = fetch_qualifiers(colon_separated_group)}) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) for _, spec in ipairs(s_specs) do if spec.form == "++" and #ing_specs == 1 and not ing_specs[1].form and not ing_specs[1].qualifiers and #ed_specs == 1 and not ed_specs[1].form and not ed_specs[1].qualifiers then ing_specs[1].form = "++" ed_specs[1].form = "++" break end end return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(par1, parse_props) -- (2) Remove any links from the lemma, but remember the original form -- so we can use it below in the 'lemma_linked' form. iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = require("Module:links").remove_links(base.lemma) end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local def_s_form, def_ing_form, def_ed_form = base_default_verb_forms(base.lemma) local function process_specs(slot, specs, default_form, canonicalize_plusplus) for _, spec in ipairs(specs) do local form = spec.form if not form or form == "+" then form = default_form elseif form == "++" then form = canonicalize_plusplus() end -- If there's a ~ in the form, substitute it with the lemma, -- but make sure to first replace % in the lemma with %% so that -- it doesn't get interpreted as a capture replace expression. if form:find("~") then -- Assign to a var because gsub returns multiple values. local subbed_lemma = base.lemma:gsub("%%", "%%%%") form = form:gsub("~", subbed_lemma) end -- If the form is -, don't insert any forms, which will result -- in there being no overall forms (in fact it will be nil). -- We check for that down below and substitute a single "-" as -- the form, which in turn gets turned into special labels like -- "no present participle". if form ~= "-" then iut.insert_form(base.forms, slot, {form = form, footnotes = spec.qualifiers}) end end end process_specs("s_form", base.s_specs, def_s_form, function() return compute_plusplus_s_form(base.lemma, def_s_form) end) process_specs("ing_form", base.ing_specs, def_ing_form, function() return compute_double_last_cons_stem(base.lemma) .. "ing" end) process_specs("ed_form", base.ed_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) -- If the -en spec is completely missing, substitute the -ed spec in its entirely. -- Otherwise, if individual -en forms are missing or use +, we will substitute the -- default -ed form, as with the -ed spec. local en_specs = base.en_specs if #en_specs == 1 and not en_specs[1].form and not en_specs[1].qualifiers then en_specs = base.ed_specs end process_specs("en_form", en_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) iut.insert_form(base.forms, "lemma", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.orig_lemma:find("%[%[") then return base.orig_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_forms(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - -- for a spec. if not forms or #forms == 0 then forms = {{form = "-"}} end return forms end pres_3sgs = fetch_forms("s_form") pres_ptcs = fetch_forms("ing_form") pasts = fetch_forms("ed_form") past_ptcs = fetch_forms("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given. -- If no links in this form and it has multiple words, autolink the individual words. -- The user can override this using head=. if #data.heads == 0 then for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do local lemma = lemma_obj.form if not lemma:find("%[%[") then local m_headword = require("Module:headword") if m_headword.head_is_multiword(lemma) then lemma = m_headword.add_multiword_links(lemma) end end table.insert(data.heads, lemma) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- local pres_3sg, pres_ptc, past if par1 and not par2 and not par3 then -- Use of a single parameter other than "++", "*" or "++*" is now the "legacy" format, -- and no longer supported. if par1 == "es" or par1 == "ies" or par1 == "d" then error("Legacy parameter 1=es/ies/d no longer supported, just use 'en-verb' without params") elseif par1 == "++" or par1 == "*" or par1 == "++*" then pres_3sg = canonicalize_s_form(par1) pres_ptc = canonicalize_ing_form(par1) past = canonicalize_ed_form(par1) else error("Legacy parameter 1=STEM no longer supported, just use 'en-verb' without params") end else if par3 then track("xxx3") elseif par2 then track("xxx2") end end if not pres_3sg or not pres_ptc or not past then -- Either all three should be set above, or none of them. assert(not pres_3sg and not pres_ptc and not past) if par1 then pres_3sg = canonicalize_s_form(par1) else pres_3sg = new_default_s end if par2 then pres_ptc = canonicalize_ing_form(par2) else pres_ptc = new_default_ing end if par3 then past = canonicalize_ed_form(par3) else past = new_default_ed end end if par4 then past_ptcs_given = true past_ptc = canonicalize_ed_form(par4) else past_ptc = past end pres_3sgs = {{form = pres_3sg}} pres_ptcs = {{form = pres_ptc}} pasts = {{form = past}} past_ptcs = {{form = past_ptc}} end ------------------------------------------- HANDLE OVERRIDES ------------------------------------------ local pres_3sg_infls, pres_ptc_infls, past_infls, past_ptc_infls local function strip_brackets(qualifiers) if not qualifiers then return nil end local stripped_qualifiers = {} for _, qualifier in ipairs(qualifiers) do local stripped_qualifier = qualifier:match("^%[(.*)%]$") if not stripped_qualifier then error("Internal error: Qualifier should be surrounded by brackets at this stage: " .. qualifier) end table.insert(stripped_qualifiers, stripped_qualifier) end return stripped_qualifiers end local function collect_forms(label, accel_form, defaults, overrides, override_qualifiers, canonicalize) if defaults[1].form == "-" then return {label = "no " .. label} else local into_table = {label = label, accel = {form = accel_form}} local maxindex = math.max(#defaults, overrides.maxindex) local qualifiers = override_qualifiers[1] and {override_qualifiers[1]} or strip_brackets(defaults[1].footnotes) table.insert(into_table, {term = defaults[1].form, qualifiers = qualifiers}) -- Present 3rd singular for i = 2, maxindex do local override_form = canonicalize(overrides[i]) if override_form then -- If there is an override such as past_ptc2=..., only use the qualifier specified -- using an override (past_ptc2_qual=...), if any; it doesn't make sense to combine -- an override form with a qualifier specified inside of angle brackets. table.insert(into_table, {term = override_form, qualifiers = {override_qualifiers[i]}}) elseif defaults[i] then -- If the form comes from inside angle brackets, allow any override qualifier -- (past_ptc2_qual=...) to override any qualifier specified inside of angle brackets. -- FIXME: Maybe we should throw an error here if both exist. local qualifiers = override_qualifiers[i] and {override_qualifiers[i]} or strip_brackets(defaults[i].footnotes) table.insert(into_table, {term = defaults[i].form, qualifiers = qualifiers}) end end return into_table end end local pres_3sg_infls = collect_forms("third-person singular simple present", "3|s|pres", pres_3sgs, args[1], args.pres_3sg_qual, canonicalize_s_form) local pres_ptc_infls = collect_forms("present participle", "pres|ptcp", pres_ptcs, args[2], args.pres_ptc_qual, canonicalize_ing_form) local past_infls = collect_forms("simple past", "past", pasts, args[3], args.past_qual, canonicalize_ed_form) local past_ptc_infls = collect_forms("past participle", "past|ptcp", past_ptcs, args[4], args.past_ptc_qual, canonicalize_ed_form) -- Are the past forms identical to the past participle forms? If so, we use a single -- combined "simple past and past participle" label on the past tense forms. -- We check for two conditions: Either no past participle forms were given at all, or -- they were given but are identical in every way (all forms and qualifiers) to the past -- tense forms. The former "no explicit past participle forms" check is important in the -- "separate-parameter" format; if past tense overrides are given and no past participle -- forms given, the past tense overrides should apply to the past participle as well. -- In the angle-bracket format, it's expected that all forms and qualifiers are specified -- using that format, and we explicitly copy past tense forms and qualifiers to past -- participle ones if the latter are omitted, so we disable to "no explicit past participle -- forms" check. if args[4].maxindex > 0 or args.past_ptc_qual.maxindex > 0 then past_ptcs_given = true end local identical = true -- For the past and past participle to be identical, there must be -- the same number of inflections, and each inflection must match -- in term and qualifiers. if #past_infls ~= #past_ptc_infls then identical = false else for key, val in ipairs(past_infls) do if past_ptc_infls[key].term ~= val.term then identical = false break else local quals1 = past_ptc_infls[key].qualifiers local quals2 = val.qualifiers if (not not quals1) ~= (not not quals2) then -- one is nil, the other is not identical = false elseif quals1 and quals2 then -- qualifiers present in both; each qualifier must match if #quals1 ~= #quals2 then identical = false else for k, v in ipairs(quals1) do if v ~= quals2[k] then identical = false break end end end end if not identical then break end end end end -- Insert the forms table.insert(data.inflections, pres_3sg_infls) table.insert(data.inflections, pres_ptc_infls) if not past_ptcs_given or identical then if past_ptcs[1].form == "-" then past_infls.label = "no simple past or past participle" else past_infls.label = "simple past and past participle" past_infls.accel = {form = "past|and|past|ptcp"} end table.insert(data.inflections, past_infls) else table.insert(data.inflections, past_infls) table.insert(data.inflections, past_ptc_infls) end end } return export ck411ovf41f5ff6w4jmx3y8ngyziruq 847571 847567 2022-07-23T14:19:15Z Beginneruser 11037 خنثی‌سازی نسخهٔ 847567 از [[Special:Contributions/Beginneruser|Beginneruser]] ([[User talk:Beginneruser|بحث]]) Scribunto text/plain local export = {} local pos_functions = {} local lang = require("Module:languages").getByCode("en") local PAGENAME = mw.title.getCurrentTitle().text local function glossary_link(entry, text) text = text or entry return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]" end local function track(page) require("Module:debug").track("en-headword/" .. page) return true end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") local params = { ["head"] = {list = true}, ["suff"] = {type = "boolean"}, ["sort"] = {}, } local pos_data = pos_functions[poscat] if pos_data then for key, val in pairs(pos_data.params) do params[key] = val end end local args, unknown_args = require("Module:parameters").process(frame:getParent().args, params, pos_data.return_unknown) if unknown_args and next(unknown_args) then track("unknown args") track("unknown args/POS/" .. tostring(poscat)) for parameter, value in pairs(unknown_args) do track("unknown args/param/" .. tostring(parameter)) mw.log("unknown parameter in [[Module:headword]]: |" .. tostring(parameter) .. "=" .. tostring(value)) end end local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], inflections = {}} if #data.heads == 0 and args.pagename then table.insert(data.heads, args.pagename) end if args["suff"] then data.pos_category = "suffixes" if poscat == "صفت‌ها" or poscat == "قید‌ها" or poscat == "اسم‌ها" or poscat == "فعل‌ها" then table.insert(data.categories, ("%s %s-forming suffixes") :format(lang:getCanonicalName(), poscat:gsub("s$", ""))) else error("No category exists for suffixes forming " .. poscat .. ".") end end if pos_data then pos_data.func(args, data) end local extra_categories = {} if PAGENAME:find("[Qq][^Uu]") or PAGENAME:find("[Qq]$") then table.insert(data.categories, lang:getCanonicalName() .. " words containing Q not followed by U") end if PAGENAME:find("([A-Za-z])%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing three consecutive instances of the same letter") end if PAGENAME:find("([A-Za-z])%1%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing four consecutive instances of the same letter") end -- mw.ustring.toNFD performs decomposition, so letters that decompose -- to an ASCII vowel and a diacritic, such as é, are counted as vowels and -- do not need to be included in the pattern. if not mw.ustring.find(mw.ustring.lower(mw.ustring.toNFD(PAGENAME)), "[aeiouyæœø]") then table.insert(data.categories, lang:getCanonicalName() .. " words without vowels") end if PAGENAME:find("yre$") then table.insert(data.categories, lang:getCanonicalName() .. ' words ending in "-yre"') end if not PAGENAME:find(" ") and PAGENAME:len() >= 25 then table.insert(extra_categories, "Long " .. lang:getCanonicalName() .. ' words') end if PAGENAME:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then table.insert(data.categories, lang:getCanonicalName() .. ' words that use all vowels in alphabetical order') end data.sort_key = args.sort return require("Module:headword").full_headword(data) .. (#extra_categories > 0 and require("Module:utilities").format_categories(extra_categories, lang, args.sort) or "") end -- This function does the common work between adjectives and adverbs function make_comparatives(params, data) local comp_parts = {label = glossary_link("comparative"), accel = {form = "comparative"}} local sup_parts = {label = glossary_link("superlative"), accel = {form = "superlative"}} if #params == 0 then table.insert(params, {"more"}) end -- To form the stem, replace -(e)y with -i and remove a final -e. local stem = PAGENAME:gsub("([^aeiou])e?y$", "%1i"):gsub("e$", "") -- Go over each parameter given and create a comparative and superlative form for i, val in ipairs(params) do local comp = val[1] local comp_qual = val[2] local sup = val[3] local sup_qual = val[4] local comp_part, sup_part if comp == "more" and PAGENAME ~= "many" and PAGENAME ~= "much" then comp_part = "[[more]] " .. PAGENAME sup_part = "[[most]] " .. PAGENAME elseif comp == "further" and PAGENAME ~= "far" then comp_part = "[[further]] " .. PAGENAME sup_part = "[[furthest]] " .. PAGENAME elseif comp == "er" then comp_part = stem .. "er" sup_part = stem .. "est" elseif comp == "-" or sup == "-" then -- Allowing '-' makes it more flexible to not have some forms if comp ~= "-" then comp_part = comp end if sup ~= "-" then sup_part = sup end else -- If the full comparative was given, but no superlative, then -- create it by replacing the ending -er with -est. if not sup then if comp:find("er$") then sup = comp:gsub("er$", "est") else error("The superlative of \"" .. comp .. "\" cannot be generated automatically. Please provide it with the \"sup" .. (i == 1 and "" or i) .. "=\" parameter.") end end comp_part = comp sup_part = sup end if comp_part then table.insert(comp_parts, {term = comp_part, qualifiers = {comp_qual}}) end if sup_part then table.insert(sup_parts, {term = sup_part, qualifiers = {sup_qual}}) end end table.insert(data.inflections, comp_parts) table.insert(data.inflections, sup_parts) end pos_functions["adjectives"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 local is_not_comparable = false local is_comparative_only = false -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 is_not_comparable = true -- If the only argument is +, then remember this and clear parameters elseif args[1][1] == "+" and args[1].maxindex == 1 then shift = 1 is_comparative_only = true end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. -- If there are parameters, then show "not generally comparable" -- before the forms. if #params == 0 then if is_not_comparable then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adjectives") return end if is_comparative_only then table.insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) table.insert(data.categories, lang:getCanonicalName() .. " comparative-only adjectives") return end else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["adverbs"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. If there are parameters, -- then show "not generally comparable" before the forms. if #params == 0 then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adverbs") return else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["conjunctions"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } pos_functions["interjections"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } local function default_plural(noun) local new_pl if noun:find("[sxz]$") or noun:find("[cs]h$") then new_pl = noun .. "es" elseif noun:find("[^aeiou]y$") then new_pl = noun:gsub("y$", "i") .. "es" else new_pl = noun .. "s" end return new_pl end local function canonicalize_plural(pl, stem) if pl == "s" then return stem .. "s" elseif pl == "es" then return stem .. "es" elseif pl == "+" then return default_plural(PAGENAME) else return nil end end pos_functions["اسم‌های"] = { params = { [1] = {list = true, allow_holes = true}, ["pl=qual"] = { list = true, allow_holes = true }, }, func = function(args, data) -- Gather all the plural parameters from the numbered parameters. local plurals = {} for i = 1, args[1].maxindex do local pl = args[1][i] if pl then local qual = args["plqual"][i] if qual then table.insert(plurals, {term = pl, qualifiers = {qual}}) else table.insert(plurals, pl) end end end -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) else table.insert(data.inflections, {label = glossary_link("شمارش‌ناپذیر")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("شمارش‌پذیر") .. " و " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end -- The default, always has a plural else table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local function check_ies(pl, stem) local newplural, nummatches = stem:gsub("([^aeiou])y$","%1ies") return nummatches > 0 and pl == newplural end local stem = PAGENAME local irregular = false for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl, stem) if canon_pl then table.insert(pl_parts, canon_pl) elseif type(pl) == "table" then canon_pl = canonicalize_plural(pl.term, stem) if canon_pl then table.insert(pl_parts, {term=canon_pl, qualifiers=pl.qualifiers}) end end if not canon_pl then table.insert(pl_parts, pl) if type(pl) == "table" then pl = pl.term end if not stem:find(" ") and not (pl == stem .. "s" or pl == stem .. "es" or check_ies(pl, stem)) then irregular = true if pl == stem then table.insert(data.categories, lang:getCanonicalName() .. " indeclinable nouns") end end end end if irregular then table.insert(data.categories, "اسم‌های دارای جمع‌های باقاعده " .. lang:getCanonicalName()) end table.insert(data.inflections, pl_parts) end } pos_functions["proper nouns"] = { params = { [1] = {list = true}, }, func = function(args, data) local plurals = args[1] -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") -- If no plural was given, add a default one now if #plurals == 0 then plurals = {"s"} end elseif #plurals > 0 then table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local stem = PAGENAME for i, pl in ipairs(plurals) do if pl == "s" then table.insert(pl_parts, stem .. "s") elseif pl == "es" then table.insert(pl_parts, stem .. "es") else table.insert(pl_parts, pl) end end table.insert(data.inflections, pl_parts) end } local function base_default_verb_forms(verb) local s_form = default_plural(verb) local ing_form, ed_form local vowel = "aeiouáéíóúàèìòùâêîôûäëïöüæœø" local ulvowel = vowel .. "AEIOUÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÆŒØ" -- (1) Check for C*VC verbs. -- -- flip -> flipping/flipped, strum -> strumming/strummed, nag -> nagging/nagged, etc. -- Do not include words with final -y, e.g. 'stay' (staying/stayed), 'toy' (toying/toyed), -- or with final -w, e.g. 'flow' (flowing/flowed), or with final -h, e.g. 'ah' (ahing/ahed), -- or with final -x, e.g. 'box' (boxing/boxed), or ending in an uppercase consonant, -- e.g. 'XOR' (XORing/XORed), 'OK' (OKing/OKed). Check specially for initial y- as a consonant, -- e.g. 'yip' (yipping/yipped), otherwise treat y as a vowel, so we don't trigger on 'hyphen' -- but do trigger on 'gyp'. local last_cons = mw.ustring.match(verb, "^[Yy][" .. vowel .. "y]([^A-Z" .. vowel .. "ywxh])$") if not last_cons then last_cons = mw.ustring.match(verb, "^[^" .. ulvowel .. "yY]*[" .. ulvowel .. "yY]([^A-Z" .. vowel .. "ywxh])$") end if last_cons then ing_form = verb .. last_cons .. "ing" ed_form = verb .. last_cons .. "ed" else -- (2) Generate -ing form. -- (2a) lie -> lying, untie -> untying, etc. local stem = verb:match("^(.*)ie$") if stem then ing_form = stem .. "ying" else -- (2b) argue -> arguing, sprue -> spruing, dialogue -> dialoguing, etc. stem = verb:match("^(.*)ue$") if stem then ing_form = stem .. "uing" else stem = mw.ustring.match(verb, "^(.*[" .. ulvowel .. "yY][^" .. vowel .. "y]+)e$") if stem then -- (2c) baptize -> baptizing, rake -> raking, type -> typing, parse -> parsing, etc. -- (ending in vowel + consonant(s) + -e); but not referee -> refereeing, -- backhoe -> backhoeing, redye -> redyeing (ending in some other vowel + -e or in -ye); -- and not be -> being (no vowel before the consonant preceding the -e) ing_form = stem .. "ing" else -- (2d) regular verbs ing_form = verb .. "ing" end end end -- (3) Generate -ed form. if verb:find("e$") then -- (3a) baptize -> baptized, rake -> raked, parse -> parsed, free -> freed, hoe -> hoed ed_form = verb .. "d" else stem = mw.ustring.match(verb, "^(.*[^" .. ulvowel .. "yY])y$") if stem then -- (3b) marry -> married, levy -> levied, try -> tried, etc.; but not toy -> toyed ed_form = stem .. "ied" else -- (3c) regular verbs ed_form = verb .. "ed" end end end return s_form, ing_form, ed_form end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil end end pos_functions["فعل‌های"] = { params = { [1] = {list = "pres_3sg", allow_holes = true}, ["pres_3sg_qual"] = {list = "pres_3sg=_qual", allow_holes = true}, [2] = {list = "pres_ptc", allow_holes = true}, ["pres_ptc_qual"] = {list = "pres_ptc=_qual", allow_holes = true}, [3] = {list = "past", allow_holes = true}, ["past_qual"] = {list = "past=_qual", allow_holes = true}, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc_qual"] = {list = "past_ptc=_qual", allow_holes = true}, ["pagename"] = {}, -- for testing }, func = function(args, data) -- Get parameters local par1 = args[1][1] local par2 = args[2][1] local par3 = args[3][1] local par4 = args[4][1] local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = args.pagename or PAGENAME ------------------------------------------- UTILITY FUNCTIONS #1 ------------------------------------------ -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(verb) local last_cons = verb:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. verb .. "' must end in a consonant to use ++") end return verb .. last_cons end local function compute_plusplus_s_form(verb, default_s_form) if verb:find("[sz]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(verb) .. "es" else return default_s_form end end ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local new_default_s, new_default_ing, new_default_ed, split_default_s, split_default_ing, split_default_ed = default_verb_forms(pagename) local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Verb '" .. verb .. "' must have a space in it to use ++*") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("First word '" .. first .. "' must end in a consonant to use ++*") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form) if form == nil then error("Verb '" .. pagename .. "' must have a space in it to use * or ++*") end return form end local function sub_tilde(form) if not form then return nil end local retval = form:gsub("~", pagename) -- discard second return value return retval end local function canonicalize_s_form(form) if form == "+" then return new_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s) elseif form == "++" then return compute_plusplus_s_form(pagename, new_default_s) elseif form == "++*" then if pagename:find("^[^ ]*[sz] ") then return compute_double_last_cons_stem_of_split_verb(pagename, "es") else return check_non_nil_star_form(split_default_s) end else return sub_tilde(form) end end local function canonicalize_ing_form(form) if form == "+" then return new_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ing" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ing") else return sub_tilde(form) end end local function canonicalize_ed_form(form) if form == "+" then return new_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ed" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ed") else return sub_tilde(form) end end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local past_ptcs_given if par1 and par1:find("<") then -------------------------- ANGLE-BRACKET FORMAT -------------------------- if par2 or par3 or par4 then error("Can't specify 2=, 3= or 4= when 1= contains angle brackets: " .. par1) end -- In the angle bracket format, we always copy the full past tense specs to the past participle -- specs if none of the latter are given, so act as if the past participle is always given. -- There is a separate check to see if the past tense and past participle are identical, in any case. past_ptcs_given = true local iut = require("Module:inflection utilities") -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = iut.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = iut.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec: " .. angle_bracket_spec) end local function fetch_qualifiers(separated_group) local qualifiers for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed qualifiers: '" .. table.concat(separated_group) .. "'") end if not qualifiers then qualifiers = {} end table.insert(qualifiers, separated_group[j]) end return qualifiers end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{}} end local specs = {} local colon_separated_groups = iut.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "++*" then error("* and ++* not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = nil end table.insert(specs, {form = form, qualifiers = fetch_qualifiers(colon_separated_group)}) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) for _, spec in ipairs(s_specs) do if spec.form == "++" and #ing_specs == 1 and not ing_specs[1].form and not ing_specs[1].qualifiers and #ed_specs == 1 and not ed_specs[1].form and not ed_specs[1].qualifiers then ing_specs[1].form = "++" ed_specs[1].form = "++" break end end return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(par1, parse_props) -- (2) Remove any links from the lemma, but remember the original form -- so we can use it below in the 'lemma_linked' form. iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = require("Module:links").remove_links(base.lemma) end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local def_s_form, def_ing_form, def_ed_form = base_default_verb_forms(base.lemma) local function process_specs(slot, specs, default_form, canonicalize_plusplus) for _, spec in ipairs(specs) do local form = spec.form if not form or form == "+" then form = default_form elseif form == "++" then form = canonicalize_plusplus() end -- If there's a ~ in the form, substitute it with the lemma, -- but make sure to first replace % in the lemma with %% so that -- it doesn't get interpreted as a capture replace expression. if form:find("~") then -- Assign to a var because gsub returns multiple values. local subbed_lemma = base.lemma:gsub("%%", "%%%%") form = form:gsub("~", subbed_lemma) end -- If the form is -, don't insert any forms, which will result -- in there being no overall forms (in fact it will be nil). -- We check for that down below and substitute a single "-" as -- the form, which in turn gets turned into special labels like -- "no present participle". if form ~= "-" then iut.insert_form(base.forms, slot, {form = form, footnotes = spec.qualifiers}) end end end process_specs("s_form", base.s_specs, def_s_form, function() return compute_plusplus_s_form(base.lemma, def_s_form) end) process_specs("ing_form", base.ing_specs, def_ing_form, function() return compute_double_last_cons_stem(base.lemma) .. "ing" end) process_specs("ed_form", base.ed_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) -- If the -en spec is completely missing, substitute the -ed spec in its entirely. -- Otherwise, if individual -en forms are missing or use +, we will substitute the -- default -ed form, as with the -ed spec. local en_specs = base.en_specs if #en_specs == 1 and not en_specs[1].form and not en_specs[1].qualifiers then en_specs = base.ed_specs end process_specs("en_form", en_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) iut.insert_form(base.forms, "lemma", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.orig_lemma:find("%[%[") then return base.orig_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_forms(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - -- for a spec. if not forms or #forms == 0 then forms = {{form = "-"}} end return forms end pres_3sgs = fetch_forms("s_form") pres_ptcs = fetch_forms("ing_form") pasts = fetch_forms("ed_form") past_ptcs = fetch_forms("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given. -- If no links in this form and it has multiple words, autolink the individual words. -- The user can override this using head=. if #data.heads == 0 then for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do local lemma = lemma_obj.form if not lemma:find("%[%[") then local m_headword = require("Module:headword") if m_headword.head_is_multiword(lemma) then lemma = m_headword.add_multiword_links(lemma) end end table.insert(data.heads, lemma) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- local pres_3sg, pres_ptc, past if par1 and not par2 and not par3 then -- Use of a single parameter other than "++", "*" or "++*" is now the "legacy" format, -- and no longer supported. if par1 == "es" or par1 == "ies" or par1 == "d" then error("Legacy parameter 1=es/ies/d no longer supported, just use 'en-verb' without params") elseif par1 == "++" or par1 == "*" or par1 == "++*" then pres_3sg = canonicalize_s_form(par1) pres_ptc = canonicalize_ing_form(par1) past = canonicalize_ed_form(par1) else error("Legacy parameter 1=STEM no longer supported, just use 'en-verb' without params") end else if par3 then track("xxx3") elseif par2 then track("xxx2") end end if not pres_3sg or not pres_ptc or not past then -- Either all three should be set above, or none of them. assert(not pres_3sg and not pres_ptc and not past) if par1 then pres_3sg = canonicalize_s_form(par1) else pres_3sg = new_default_s end if par2 then pres_ptc = canonicalize_ing_form(par2) else pres_ptc = new_default_ing end if par3 then past = canonicalize_ed_form(par3) else past = new_default_ed end end if par4 then past_ptcs_given = true past_ptc = canonicalize_ed_form(par4) else past_ptc = past end pres_3sgs = {{form = pres_3sg}} pres_ptcs = {{form = pres_ptc}} pasts = {{form = past}} past_ptcs = {{form = past_ptc}} end ------------------------------------------- HANDLE OVERRIDES ------------------------------------------ local pres_3sg_infls, pres_ptc_infls, past_infls, past_ptc_infls local function strip_brackets(qualifiers) if not qualifiers then return nil end local stripped_qualifiers = {} for _, qualifier in ipairs(qualifiers) do local stripped_qualifier = qualifier:match("^%[(.*)%]$") if not stripped_qualifier then error("Internal error: Qualifier should be surrounded by brackets at this stage: " .. qualifier) end table.insert(stripped_qualifiers, stripped_qualifier) end return stripped_qualifiers end local function collect_forms(label, accel_form, defaults, overrides, override_qualifiers, canonicalize) if defaults[1].form == "-" then return {label = "no " .. label} else local into_table = {label = label, accel = {form = accel_form}} local maxindex = math.max(#defaults, overrides.maxindex) local qualifiers = override_qualifiers[1] and {override_qualifiers[1]} or strip_brackets(defaults[1].footnotes) table.insert(into_table, {term = defaults[1].form, qualifiers = qualifiers}) -- Present 3rd singular for i = 2, maxindex do local override_form = canonicalize(overrides[i]) if override_form then -- If there is an override such as past_ptc2=..., only use the qualifier specified -- using an override (past_ptc2_qual=...), if any; it doesn't make sense to combine -- an override form with a qualifier specified inside of angle brackets. table.insert(into_table, {term = override_form, qualifiers = {override_qualifiers[i]}}) elseif defaults[i] then -- If the form comes from inside angle brackets, allow any override qualifier -- (past_ptc2_qual=...) to override any qualifier specified inside of angle brackets. -- FIXME: Maybe we should throw an error here if both exist. local qualifiers = override_qualifiers[i] and {override_qualifiers[i]} or strip_brackets(defaults[i].footnotes) table.insert(into_table, {term = defaults[i].form, qualifiers = qualifiers}) end end return into_table end end local pres_3sg_infls = collect_forms("third-person singular simple present", "3|s|pres", pres_3sgs, args[1], args.pres_3sg_qual, canonicalize_s_form) local pres_ptc_infls = collect_forms("present participle", "pres|ptcp", pres_ptcs, args[2], args.pres_ptc_qual, canonicalize_ing_form) local past_infls = collect_forms("simple past", "past", pasts, args[3], args.past_qual, canonicalize_ed_form) local past_ptc_infls = collect_forms("past participle", "past|ptcp", past_ptcs, args[4], args.past_ptc_qual, canonicalize_ed_form) -- Are the past forms identical to the past participle forms? If so, we use a single -- combined "simple past and past participle" label on the past tense forms. -- We check for two conditions: Either no past participle forms were given at all, or -- they were given but are identical in every way (all forms and qualifiers) to the past -- tense forms. The former "no explicit past participle forms" check is important in the -- "separate-parameter" format; if past tense overrides are given and no past participle -- forms given, the past tense overrides should apply to the past participle as well. -- In the angle-bracket format, it's expected that all forms and qualifiers are specified -- using that format, and we explicitly copy past tense forms and qualifiers to past -- participle ones if the latter are omitted, so we disable to "no explicit past participle -- forms" check. if args[4].maxindex > 0 or args.past_ptc_qual.maxindex > 0 then past_ptcs_given = true end local identical = true -- For the past and past participle to be identical, there must be -- the same number of inflections, and each inflection must match -- in term and qualifiers. if #past_infls ~= #past_ptc_infls then identical = false else for key, val in ipairs(past_infls) do if past_ptc_infls[key].term ~= val.term then identical = false break else local quals1 = past_ptc_infls[key].qualifiers local quals2 = val.qualifiers if (not not quals1) ~= (not not quals2) then -- one is nil, the other is not identical = false elseif quals1 and quals2 then -- qualifiers present in both; each qualifier must match if #quals1 ~= #quals2 then identical = false else for k, v in ipairs(quals1) do if v ~= quals2[k] then identical = false break end end end end if not identical then break end end end end -- Insert the forms table.insert(data.inflections, pres_3sg_infls) table.insert(data.inflections, pres_ptc_infls) if not past_ptcs_given or identical then if past_ptcs[1].form == "-" then past_infls.label = "no simple past or past participle" else past_infls.label = "simple past and past participle" past_infls.accel = {form = "past|and|past|ptcp"} end table.insert(data.inflections, past_infls) else table.insert(data.inflections, past_infls) table.insert(data.inflections, past_ptc_infls) end end } return export 7nqlxe5tnm3b4csey6nrbmqhqiwx13s 847577 847571 2022-07-23T14:42:25Z Beginneruser 11037 Scribunto text/plain local export = {} local pos_functions = {} local lang = require("Module:languages").getByCode("en") local PAGENAME = mw.title.getCurrentTitle().text local function glossary_link(entry, text) text = text or entry return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]" end local function track(page) require("Module:debug").track("en-headword/" .. page) return true end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") local params = { ["head"] = {list = true}, ["suff"] = {type = "boolean"}, ["sort"] = {}, } local pos_data = pos_functions[poscat] if pos_data then for key, val in pairs(pos_data.params) do params[key] = val end end local args, unknown_args = require("Module:parameters").process(frame:getParent().args, params, pos_data.return_unknown) if unknown_args and next(unknown_args) then track("unknown args") track("unknown args/POS/" .. tostring(poscat)) for parameter, value in pairs(unknown_args) do track("unknown args/param/" .. tostring(parameter)) mw.log("unknown parameter in [[Module:headword]]: |" .. tostring(parameter) .. "=" .. tostring(value)) end end local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], inflections = {}} if #data.heads == 0 and args.pagename then table.insert(data.heads, args.pagename) end if args["suff"] then data.pos_category = "suffixes" if poscat == "صفت‌ها" or poscat == "قید‌ها" or poscat == "اسم‌ها" or poscat == "فعل‌ها" then table.insert(data.categories, ("%s %s-forming suffixes") :format(lang:getCanonicalName(), poscat:gsub("s$", ""))) else error("No category exists for suffixes forming " .. poscat .. ".") end end if pos_data then pos_data.func(args, data) end local extra_categories = {} if PAGENAME:find("[Qq][^Uu]") or PAGENAME:find("[Qq]$") then table.insert(data.categories, lang:getCanonicalName() .. " words containing Q not followed by U") end if PAGENAME:find("([A-Za-z])%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing three consecutive instances of the same letter") end if PAGENAME:find("([A-Za-z])%1%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing four consecutive instances of the same letter") end -- mw.ustring.toNFD performs decomposition, so letters that decompose -- to an ASCII vowel and a diacritic, such as é, are counted as vowels and -- do not need to be included in the pattern. if not mw.ustring.find(mw.ustring.lower(mw.ustring.toNFD(PAGENAME)), "[aeiouyæœø]") then table.insert(data.categories, lang:getCanonicalName() .. " words without vowels") end if PAGENAME:find("yre$") then table.insert(data.categories, lang:getCanonicalName() .. ' words ending in "-yre"') end if not PAGENAME:find(" ") and PAGENAME:len() >= 25 then table.insert(extra_categories, "Long " .. lang:getCanonicalName() .. ' words') end if PAGENAME:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then table.insert(data.categories, lang:getCanonicalName() .. ' words that use all vowels in alphabetical order') end data.sort_key = args.sort return require("Module:headword").full_headword(data) .. (#extra_categories > 0 and require("Module:utilities").format_categories(extra_categories, lang, args.sort) or "") end -- This function does the common work between adjectives and adverbs function make_comparatives(params, data) local comp_parts = {label = glossary_link("comparative"), accel = {form = "comparative"}} local sup_parts = {label = glossary_link("superlative"), accel = {form = "superlative"}} if #params == 0 then table.insert(params, {"more"}) end -- To form the stem, replace -(e)y with -i and remove a final -e. local stem = PAGENAME:gsub("([^aeiou])e?y$", "%1i"):gsub("e$", "") -- Go over each parameter given and create a comparative and superlative form for i, val in ipairs(params) do local comp = val[1] local comp_qual = val[2] local sup = val[3] local sup_qual = val[4] local comp_part, sup_part if comp == "more" and PAGENAME ~= "many" and PAGENAME ~= "much" then comp_part = "[[more]] " .. PAGENAME sup_part = "[[most]] " .. PAGENAME elseif comp == "further" and PAGENAME ~= "far" then comp_part = "[[further]] " .. PAGENAME sup_part = "[[furthest]] " .. PAGENAME elseif comp == "er" then comp_part = stem .. "er" sup_part = stem .. "est" elseif comp == "-" or sup == "-" then -- Allowing '-' makes it more flexible to not have some forms if comp ~= "-" then comp_part = comp end if sup ~= "-" then sup_part = sup end else -- If the full comparative was given, but no superlative, then -- create it by replacing the ending -er with -est. if not sup then if comp:find("er$") then sup = comp:gsub("er$", "est") else error("The superlative of \"" .. comp .. "\" cannot be generated automatically. Please provide it with the \"sup" .. (i == 1 and "" or i) .. "=\" parameter.") end end comp_part = comp sup_part = sup end if comp_part then table.insert(comp_parts, {term = comp_part, qualifiers = {comp_qual}}) end if sup_part then table.insert(sup_parts, {term = sup_part, qualifiers = {sup_qual}}) end end table.insert(data.inflections, comp_parts) table.insert(data.inflections, sup_parts) end pos_functions["adjectives"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 local is_not_comparable = false local is_comparative_only = false -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 is_not_comparable = true -- If the only argument is +, then remember this and clear parameters elseif args[1][1] == "+" and args[1].maxindex == 1 then shift = 1 is_comparative_only = true end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. -- If there are parameters, then show "not generally comparable" -- before the forms. if #params == 0 then if is_not_comparable then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adjectives") return end if is_comparative_only then table.insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) table.insert(data.categories, lang:getCanonicalName() .. " comparative-only adjectives") return end else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["adverbs"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. If there are parameters, -- then show "not generally comparable" before the forms. if #params == 0 then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adverbs") return else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["conjunctions"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } pos_functions["interjections"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } local function default_plural(noun) local new_pl if noun:find("[sxz]$") or noun:find("[cs]h$") then new_pl = noun .. "es" elseif noun:find("[^aeiou]y$") then new_pl = noun:gsub("y$", "i") .. "es" else new_pl = noun .. "s" end return new_pl end local function canonicalize_plural(pl, stem) if pl == "s" then return stem .. "s" elseif pl == "es" then return stem .. "es" elseif pl == "+" then return default_plural(PAGENAME) else return nil end end pos_functions["اسم‌های"] = { params = { [1] = {list = true, allow_holes = true}, ["pl=qual"] = { list = true, allow_holes = true }, }, func = function(args, data) -- Gather all the plural parameters from the numbered parameters. local plurals = {} for i = 1, args[1].maxindex do local pl = args[1][i] if pl then local qual = args["plqual"][i] if qual then table.insert(plurals, {term = pl, qualifiers = {qual}}) else table.insert(plurals, pl) end end end -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) else table.insert(data.inflections, {label = glossary_link("شمارش‌ناپذیر")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("شمارش‌پذیر") .. " و " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end -- The default, always has a plural else table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local function check_ies(pl, stem) local newplural, nummatches = stem:gsub("([^aeiou])y$","%1ies") return nummatches > 0 and pl == newplural end local stem = PAGENAME local irregular = false for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl, stem) if canon_pl then table.insert(pl_parts, canon_pl) elseif type(pl) == "table" then canon_pl = canonicalize_plural(pl.term, stem) if canon_pl then table.insert(pl_parts, {term=canon_pl, qualifiers=pl.qualifiers}) end end if not canon_pl then table.insert(pl_parts, pl) if type(pl) == "table" then pl = pl.term end if not stem:find(" ") and not (pl == stem .. "s" or pl == stem .. "es" or check_ies(pl, stem)) then irregular = true if pl == stem then table.insert(data.categories, lang:getCanonicalName() .. " indeclinable nouns") end end end end if irregular then table.insert(data.categories, "اسم‌های دارای جمع‌های باقاعده " .. lang:getCanonicalName()) end table.insert(data.inflections, pl_parts) end } pos_functions["proper nouns"] = { params = { [1] = {list = true}, }, func = function(args, data) local plurals = args[1] -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") -- If no plural was given, add a default one now if #plurals == 0 then plurals = {"s"} end elseif #plurals > 0 then table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local stem = PAGENAME for i, pl in ipairs(plurals) do if pl == "s" then table.insert(pl_parts, stem .. "s") elseif pl == "es" then table.insert(pl_parts, stem .. "es") else table.insert(pl_parts, pl) end end table.insert(data.inflections, pl_parts) end } local function base_default_verb_forms(verb) local s_form = default_plural(verb) local ing_form, ed_form local vowel = "aeiouáéíóúàèìòùâêîôûäëïöüæœø" local ulvowel = vowel .. "AEIOUÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÆŒØ" -- (1) Check for C*VC verbs. -- -- flip -> flipping/flipped, strum -> strumming/strummed, nag -> nagging/nagged, etc. -- Do not include words with final -y, e.g. 'stay' (staying/stayed), 'toy' (toying/toyed), -- or with final -w, e.g. 'flow' (flowing/flowed), or with final -h, e.g. 'ah' (ahing/ahed), -- or with final -x, e.g. 'box' (boxing/boxed), or ending in an uppercase consonant, -- e.g. 'XOR' (XORing/XORed), 'OK' (OKing/OKed). Check specially for initial y- as a consonant, -- e.g. 'yip' (yipping/yipped), otherwise treat y as a vowel, so we don't trigger on 'hyphen' -- but do trigger on 'gyp'. local last_cons = mw.ustring.match(verb, "^[Yy][" .. vowel .. "y]([^A-Z" .. vowel .. "ywxh])$") if not last_cons then last_cons = mw.ustring.match(verb, "^[^" .. ulvowel .. "yY]*[" .. ulvowel .. "yY]([^A-Z" .. vowel .. "ywxh])$") end if last_cons then ing_form = verb .. last_cons .. "ing" ed_form = verb .. last_cons .. "ed" else -- (2) Generate -ing form. -- (2a) lie -> lying, untie -> untying, etc. local stem = verb:match("^(.*)ie$") if stem then ing_form = stem .. "ying" else -- (2b) argue -> arguing, sprue -> spruing, dialogue -> dialoguing, etc. stem = verb:match("^(.*)ue$") if stem then ing_form = stem .. "uing" else stem = mw.ustring.match(verb, "^(.*[" .. ulvowel .. "yY][^" .. vowel .. "y]+)e$") if stem then -- (2c) baptize -> baptizing, rake -> raking, type -> typing, parse -> parsing, etc. -- (ending in vowel + consonant(s) + -e); but not referee -> refereeing, -- backhoe -> backhoeing, redye -> redyeing (ending in some other vowel + -e or in -ye); -- and not be -> being (no vowel before the consonant preceding the -e) ing_form = stem .. "ing" else -- (2d) regular verbs ing_form = verb .. "ing" end end end -- (3) Generate -ed form. if verb:find("e$") then -- (3a) baptize -> baptized, rake -> raked, parse -> parsed, free -> freed, hoe -> hoed ed_form = verb .. "d" else stem = mw.ustring.match(verb, "^(.*[^" .. ulvowel .. "yY])y$") if stem then -- (3b) marry -> married, levy -> levied, try -> tried, etc.; but not toy -> toyed ed_form = stem .. "ied" else -- (3c) regular verbs ed_form = verb .. "ed" end end end return s_form, ing_form, ed_form end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil end end pos_functions["فعل‌های"] = { params = { [1] = {list = "pres_3sg", allow_holes = true}, ["pres_3sg_qual"] = {list = "pres_3sg=_qual", allow_holes = true}, [2] = {list = "pres_ptc", allow_holes = true}, ["pres_ptc_qual"] = {list = "pres_ptc=_qual", allow_holes = true}, [3] = {list = "past", allow_holes = true}, ["past_qual"] = {list = "past=_qual", allow_holes = true}, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc_qual"] = {list = "past_ptc=_qual", allow_holes = true}, ["pagename"] = {}, -- for testing }, func = function(args, data) -- Get parameters local par1 = args[1][1] local par2 = args[2][1] local par3 = args[3][1] local par4 = args[4][1] local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = args.pagename or PAGENAME ------------------------------------------- UTILITY FUNCTIONS #1 ------------------------------------------ -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(verb) local last_cons = verb:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. verb .. "' must end in a consonant to use ++") end return verb .. last_cons end local function compute_plusplus_s_form(verb, default_s_form) if verb:find("[sz]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(verb) .. "es" else return default_s_form end end ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local new_default_s, new_default_ing, new_default_ed, split_default_s, split_default_ing, split_default_ed = default_verb_forms(pagename) local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Verb '" .. verb .. "' must have a space in it to use ++*") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("First word '" .. first .. "' must end in a consonant to use ++*") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form) if form == nil then error("Verb '" .. pagename .. "' must have a space in it to use * or ++*") end return form end local function sub_tilde(form) if not form then return nil end local retval = form:gsub("~", pagename) -- discard second return value return retval end local function canonicalize_s_form(form) if form == "+" then return new_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s) elseif form == "++" then return compute_plusplus_s_form(pagename, new_default_s) elseif form == "++*" then if pagename:find("^[^ ]*[sz] ") then return compute_double_last_cons_stem_of_split_verb(pagename, "es") else return check_non_nil_star_form(split_default_s) end else return sub_tilde(form) end end local function canonicalize_ing_form(form) if form == "+" then return new_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ing" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ing") else return sub_tilde(form) end end local function canonicalize_ed_form(form) if form == "+" then return new_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ed" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ed") else return sub_tilde(form) end end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local past_ptcs_given if par1 and par1:find("<") then -------------------------- ANGLE-BRACKET FORMAT -------------------------- if par2 or par3 or par4 then error("Can't specify 2=, 3= or 4= when 1= contains angle brackets: " .. par1) end -- In the angle bracket format, we always copy the full past tense specs to the past participle -- specs if none of the latter are given, so act as if the past participle is always given. -- There is a separate check to see if the past tense and past participle are identical, in any case. past_ptcs_given = true local iut = require("Module:inflection utilities") -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = iut.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = iut.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec: " .. angle_bracket_spec) end local function fetch_qualifiers(separated_group) local qualifiers for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed qualifiers: '" .. table.concat(separated_group) .. "'") end if not qualifiers then qualifiers = {} end table.insert(qualifiers, separated_group[j]) end return qualifiers end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{}} end local specs = {} local colon_separated_groups = iut.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "++*" then error("* and ++* not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = nil end table.insert(specs, {form = form, qualifiers = fetch_qualifiers(colon_separated_group)}) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) for _, spec in ipairs(s_specs) do if spec.form == "++" and #ing_specs == 1 and not ing_specs[1].form and not ing_specs[1].qualifiers and #ed_specs == 1 and not ed_specs[1].form and not ed_specs[1].qualifiers then ing_specs[1].form = "++" ed_specs[1].form = "++" break end end return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(par1, parse_props) -- (2) Remove any links from the lemma, but remember the original form -- so we can use it below in the 'lemma_linked' form. iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = require("Module:links").remove_links(base.lemma) end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local def_s_form, def_ing_form, def_ed_form = base_default_verb_forms(base.lemma) local function process_specs(slot, specs, default_form, canonicalize_plusplus) for _, spec in ipairs(specs) do local form = spec.form if not form or form == "+" then form = default_form elseif form == "++" then form = canonicalize_plusplus() end -- If there's a ~ in the form, substitute it with the lemma, -- but make sure to first replace % in the lemma with %% so that -- it doesn't get interpreted as a capture replace expression. if form:find("~") then -- Assign to a var because gsub returns multiple values. local subbed_lemma = base.lemma:gsub("%%", "%%%%") form = form:gsub("~", subbed_lemma) end -- If the form is -, don't insert any forms, which will result -- in there being no overall forms (in fact it will be nil). -- We check for that down below and substitute a single "-" as -- the form, which in turn gets turned into special labels like -- "no present participle". if form ~= "-" then iut.insert_form(base.forms, slot, {form = form, footnotes = spec.qualifiers}) end end end process_specs("s_form", base.s_specs, def_s_form, function() return compute_plusplus_s_form(base.lemma, def_s_form) end) process_specs("ing_form", base.ing_specs, def_ing_form, function() return compute_double_last_cons_stem(base.lemma) .. "ing" end) process_specs("ed_form", base.ed_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) -- If the -en spec is completely missing, substitute the -ed spec in its entirely. -- Otherwise, if individual -en forms are missing or use +, we will substitute the -- default -ed form, as with the -ed spec. local en_specs = base.en_specs if #en_specs == 1 and not en_specs[1].form and not en_specs[1].qualifiers then en_specs = base.ed_specs end process_specs("en_form", en_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) iut.insert_form(base.forms, "بن‌واژه", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.orig_lemma:find("%[%[") then return base.orig_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_forms(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - -- for a spec. if not forms or #forms == 0 then forms = {{form = "-"}} end return forms end pres_3sgs = fetch_forms("s_form") pres_ptcs = fetch_forms("ing_form") pasts = fetch_forms("ed_form") past_ptcs = fetch_forms("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given. -- If no links in this form and it has multiple words, autolink the individual words. -- The user can override this using head=. if #data.heads == 0 then for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do local lemma = lemma_obj.form if not lemma:find("%[%[") then local m_headword = require("Module:headword") if m_headword.head_is_multiword(lemma) then lemma = m_headword.add_multiword_links(lemma) end end table.insert(data.heads, lemma) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- local pres_3sg, pres_ptc, past if par1 and not par2 and not par3 then -- Use of a single parameter other than "++", "*" or "++*" is now the "legacy" format, -- and no longer supported. if par1 == "es" or par1 == "ies" or par1 == "d" then error("Legacy parameter 1=es/ies/d no longer supported, just use 'en-verb' without params") elseif par1 == "++" or par1 == "*" or par1 == "++*" then pres_3sg = canonicalize_s_form(par1) pres_ptc = canonicalize_ing_form(par1) past = canonicalize_ed_form(par1) else error("Legacy parameter 1=STEM no longer supported, just use 'en-verb' without params") end else if par3 then track("xxx3") elseif par2 then track("xxx2") end end if not pres_3sg or not pres_ptc or not past then -- Either all three should be set above, or none of them. assert(not pres_3sg and not pres_ptc and not past) if par1 then pres_3sg = canonicalize_s_form(par1) else pres_3sg = new_default_s end if par2 then pres_ptc = canonicalize_ing_form(par2) else pres_ptc = new_default_ing end if par3 then past = canonicalize_ed_form(par3) else past = new_default_ed end end if par4 then past_ptcs_given = true past_ptc = canonicalize_ed_form(par4) else past_ptc = past end pres_3sgs = {{form = pres_3sg}} pres_ptcs = {{form = pres_ptc}} pasts = {{form = past}} past_ptcs = {{form = past_ptc}} end ------------------------------------------- HANDLE OVERRIDES ------------------------------------------ local pres_3sg_infls, pres_ptc_infls, past_infls, past_ptc_infls local function strip_brackets(qualifiers) if not qualifiers then return nil end local stripped_qualifiers = {} for _, qualifier in ipairs(qualifiers) do local stripped_qualifier = qualifier:match("^%[(.*)%]$") if not stripped_qualifier then error("Internal error: Qualifier should be surrounded by brackets at this stage: " .. qualifier) end table.insert(stripped_qualifiers, stripped_qualifier) end return stripped_qualifiers end local function collect_forms(label, accel_form, defaults, overrides, override_qualifiers, canonicalize) if defaults[1].form == "-" then return {label = "no " .. label} else local into_table = {label = label, accel = {form = accel_form}} local maxindex = math.max(#defaults, overrides.maxindex) local qualifiers = override_qualifiers[1] and {override_qualifiers[1]} or strip_brackets(defaults[1].footnotes) table.insert(into_table, {term = defaults[1].form, qualifiers = qualifiers}) -- Present 3rd singular for i = 2, maxindex do local override_form = canonicalize(overrides[i]) if override_form then -- If there is an override such as past_ptc2=..., only use the qualifier specified -- using an override (past_ptc2_qual=...), if any; it doesn't make sense to combine -- an override form with a qualifier specified inside of angle brackets. table.insert(into_table, {term = override_form, qualifiers = {override_qualifiers[i]}}) elseif defaults[i] then -- If the form comes from inside angle brackets, allow any override qualifier -- (past_ptc2_qual=...) to override any qualifier specified inside of angle brackets. -- FIXME: Maybe we should throw an error here if both exist. local qualifiers = override_qualifiers[i] and {override_qualifiers[i]} or strip_brackets(defaults[i].footnotes) table.insert(into_table, {term = defaults[i].form, qualifiers = qualifiers}) end end return into_table end end local pres_3sg_infls = collect_forms("third-person singular simple present", "3|s|pres", pres_3sgs, args[1], args.pres_3sg_qual, canonicalize_s_form) local pres_ptc_infls = collect_forms("present participle", "pres|ptcp", pres_ptcs, args[2], args.pres_ptc_qual, canonicalize_ing_form) local past_infls = collect_forms("simple past", "past", pasts, args[3], args.past_qual, canonicalize_ed_form) local past_ptc_infls = collect_forms("past participle", "past|ptcp", past_ptcs, args[4], args.past_ptc_qual, canonicalize_ed_form) -- Are the past forms identical to the past participle forms? If so, we use a single -- combined "simple past and past participle" label on the past tense forms. -- We check for two conditions: Either no past participle forms were given at all, or -- they were given but are identical in every way (all forms and qualifiers) to the past -- tense forms. The former "no explicit past participle forms" check is important in the -- "separate-parameter" format; if past tense overrides are given and no past participle -- forms given, the past tense overrides should apply to the past participle as well. -- In the angle-bracket format, it's expected that all forms and qualifiers are specified -- using that format, and we explicitly copy past tense forms and qualifiers to past -- participle ones if the latter are omitted, so we disable to "no explicit past participle -- forms" check. if args[4].maxindex > 0 or args.past_ptc_qual.maxindex > 0 then past_ptcs_given = true end local identical = true -- For the past and past participle to be identical, there must be -- the same number of inflections, and each inflection must match -- in term and qualifiers. if #past_infls ~= #past_ptc_infls then identical = false else for key, val in ipairs(past_infls) do if past_ptc_infls[key].term ~= val.term then identical = false break else local quals1 = past_ptc_infls[key].qualifiers local quals2 = val.qualifiers if (not not quals1) ~= (not not quals2) then -- one is nil, the other is not identical = false elseif quals1 and quals2 then -- qualifiers present in both; each qualifier must match if #quals1 ~= #quals2 then identical = false else for k, v in ipairs(quals1) do if v ~= quals2[k] then identical = false break end end end end if not identical then break end end end end -- Insert the forms table.insert(data.inflections, pres_3sg_infls) table.insert(data.inflections, pres_ptc_infls) if not past_ptcs_given or identical then if past_ptcs[1].form == "-" then past_infls.label = "no simple past or past participle" else past_infls.label = "simple past and past participle" past_infls.accel = {form = "past|and|past|ptcp"} end table.insert(data.inflections, past_infls) else table.insert(data.inflections, past_infls) table.insert(data.inflections, past_ptc_infls) end end } return export mwibt3jgcr9a0w6nok9dmceqsc49aew 847580 847577 2022-07-23T14:47:52Z Beginneruser 11037 Scribunto text/plain local export = {} local pos_functions = {} local lang = require("Module:languages").getByCode("en") local PAGENAME = mw.title.getCurrentTitle().text local function glossary_link(entry, text) text = text or entry return "[[Appendix:Glossary#" .. entry .. "|" .. text .. "]]" end local function track(page) require("Module:debug").track("en-headword/" .. page) return true end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.") local params = { ["head"] = {list = true}, ["suff"] = {type = "boolean"}, ["sort"] = {}, } local pos_data = pos_functions[poscat] if pos_data then for key, val in pairs(pos_data.params) do params[key] = val end end local args, unknown_args = require("Module:parameters").process(frame:getParent().args, params, pos_data.return_unknown) if unknown_args and next(unknown_args) then track("unknown args") track("unknown args/POS/" .. tostring(poscat)) for parameter, value in pairs(unknown_args) do track("unknown args/param/" .. tostring(parameter)) mw.log("unknown parameter in [[Module:headword]]: |" .. tostring(parameter) .. "=" .. tostring(value)) end end local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], inflections = {}} if #data.heads == 0 and args.pagename then table.insert(data.heads, args.pagename) end if args["suff"] then data.pos_category = "suffixes" if poscat == "صفت‌های" or poscat == "قید‌های" or poscat == "اسم‌های" or poscat == "فعل‌های" then table.insert(data.categories, ("%s %s-forming suffixes") :format(lang:getCanonicalName(), poscat:gsub("s$", ""))) else error("No category exists for suffixes forming " .. poscat .. ".") end end if pos_data then pos_data.func(args, data) end local extra_categories = {} if PAGENAME:find("[Qq][^Uu]") or PAGENAME:find("[Qq]$") then table.insert(data.categories, lang:getCanonicalName() .. " words containing Q not followed by U") end if PAGENAME:find("([A-Za-z])%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing three consecutive instances of the same letter") end if PAGENAME:find("([A-Za-z])%1%1%1") then table.insert(data.categories, lang:getCanonicalName() .. " words containing four consecutive instances of the same letter") end -- mw.ustring.toNFD performs decomposition, so letters that decompose -- to an ASCII vowel and a diacritic, such as é, are counted as vowels and -- do not need to be included in the pattern. if not mw.ustring.find(mw.ustring.lower(mw.ustring.toNFD(PAGENAME)), "[aeiouyæœø]") then table.insert(data.categories, lang:getCanonicalName() .. " words without vowels") end if PAGENAME:find("yre$") then table.insert(data.categories, lang:getCanonicalName() .. ' words ending in "-yre"') end if not PAGENAME:find(" ") and PAGENAME:len() >= 25 then table.insert(extra_categories, "Long " .. lang:getCanonicalName() .. ' words') end if PAGENAME:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then table.insert(data.categories, lang:getCanonicalName() .. ' words that use all vowels in alphabetical order') end data.sort_key = args.sort return require("Module:headword").full_headword(data) .. (#extra_categories > 0 and require("Module:utilities").format_categories(extra_categories, lang, args.sort) or "") end -- This function does the common work between adjectives and adverbs function make_comparatives(params, data) local comp_parts = {label = glossary_link("comparative"), accel = {form = "comparative"}} local sup_parts = {label = glossary_link("superlative"), accel = {form = "superlative"}} if #params == 0 then table.insert(params, {"more"}) end -- To form the stem, replace -(e)y with -i and remove a final -e. local stem = PAGENAME:gsub("([^aeiou])e?y$", "%1i"):gsub("e$", "") -- Go over each parameter given and create a comparative and superlative form for i, val in ipairs(params) do local comp = val[1] local comp_qual = val[2] local sup = val[3] local sup_qual = val[4] local comp_part, sup_part if comp == "more" and PAGENAME ~= "many" and PAGENAME ~= "much" then comp_part = "[[more]] " .. PAGENAME sup_part = "[[most]] " .. PAGENAME elseif comp == "further" and PAGENAME ~= "far" then comp_part = "[[further]] " .. PAGENAME sup_part = "[[furthest]] " .. PAGENAME elseif comp == "er" then comp_part = stem .. "er" sup_part = stem .. "est" elseif comp == "-" or sup == "-" then -- Allowing '-' makes it more flexible to not have some forms if comp ~= "-" then comp_part = comp end if sup ~= "-" then sup_part = sup end else -- If the full comparative was given, but no superlative, then -- create it by replacing the ending -er with -est. if not sup then if comp:find("er$") then sup = comp:gsub("er$", "est") else error("The superlative of \"" .. comp .. "\" cannot be generated automatically. Please provide it with the \"sup" .. (i == 1 and "" or i) .. "=\" parameter.") end end comp_part = comp sup_part = sup end if comp_part then table.insert(comp_parts, {term = comp_part, qualifiers = {comp_qual}}) end if sup_part then table.insert(sup_parts, {term = sup_part, qualifiers = {sup_qual}}) end end table.insert(data.inflections, comp_parts) table.insert(data.inflections, sup_parts) end pos_functions["adjectives"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 local is_not_comparable = false local is_comparative_only = false -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 is_not_comparable = true -- If the only argument is +, then remember this and clear parameters elseif args[1][1] == "+" and args[1].maxindex == 1 then shift = 1 is_comparative_only = true end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. -- If there are parameters, then show "not generally comparable" -- before the forms. if #params == 0 then if is_not_comparable then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adjectives") return end if is_comparative_only then table.insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) table.insert(data.categories, lang:getCanonicalName() .. " comparative-only adjectives") return end else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["adverbs"] = { params = { [1] = {list = true, allow_holes = true}, ["comp_qual"] = {list = "comp=_qual", allow_holes = true}, ["sup"] = {list = true, allow_holes = true}, ["sup_qual"] = {list = "sup=_qual", allow_holes = true}, }, func = function(args, data) local shift = 0 -- If the first parameter is ?, then don't show anything, just return. if args[1][1] == "?" then return -- If the first parameter is -, then move all parameters up one position. elseif args[1][1] == "-" then shift = 1 end -- Gather all the comparative and superlative parameters. local params = {} for i = 1, args[1].maxindex - shift do local comp = args[1][i + shift] local comp_qual = args["comp_qual"][i + shift] local sup = args["sup"][i] local sup_qual = args["sup_qual"][i + shift] if comp or sup then table.insert(params, {comp, comp_qual, sup, sup_qual}) end end if shift == 1 then -- If the first parameter is "-" but there are no parameters, -- then show "not comparable" only and return. If there are parameters, -- then show "not generally comparable" before the forms. if #params == 0 then table.insert(data.inflections, {label = "not " .. glossary_link("comparable")}) table.insert(data.categories, lang:getCanonicalName() .. " uncomparable adverbs") return else table.insert(data.inflections, {label = "not generally " .. glossary_link("comparable")}) end end -- Process the parameters make_comparatives(params, data) end } pos_functions["conjunctions"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } pos_functions["interjections"] = { params = { [1] = { alias_of = "head" }, }, return_unknown = true, func = function (args, data) end, } local function default_plural(noun) local new_pl if noun:find("[sxz]$") or noun:find("[cs]h$") then new_pl = noun .. "es" elseif noun:find("[^aeiou]y$") then new_pl = noun:gsub("y$", "i") .. "es" else new_pl = noun .. "s" end return new_pl end local function canonicalize_plural(pl, stem) if pl == "s" then return stem .. "s" elseif pl == "es" then return stem .. "es" elseif pl == "+" then return default_plural(PAGENAME) else return nil end end pos_functions["اسم‌های"] = { params = { [1] = {list = true, allow_holes = true}, ["pl=qual"] = { list = true, allow_holes = true }, }, func = function(args, data) -- Gather all the plural parameters from the numbered parameters. local plurals = {} for i = 1, args[1].maxindex do local pl = args[1][i] if pl then local qual = args["plqual"][i] if qual then table.insert(plurals, {term = pl, qualifiers = {qual}}) else table.insert(plurals, pl) end end end -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) else table.insert(data.inflections, {label = glossary_link("شمارش‌ناپذیر")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("شمارش‌پذیر") .. " و " .. glossary_link("شمارش‌ناپذیر")}) table.insert(data.categories, "اسم‌های شمارش‌ناپذیر " .. lang:getCanonicalName()) table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end -- The default, always has a plural else table.insert(data.categories, "اسم‌های شمارش‌پذیر " .. lang:getCanonicalName()) -- If no plural was given, add a default one now if #plurals == 0 then plurals = {default_plural(PAGENAME)} end end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local function check_ies(pl, stem) local newplural, nummatches = stem:gsub("([^aeiou])y$","%1ies") return nummatches > 0 and pl == newplural end local stem = PAGENAME local irregular = false for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl, stem) if canon_pl then table.insert(pl_parts, canon_pl) elseif type(pl) == "table" then canon_pl = canonicalize_plural(pl.term, stem) if canon_pl then table.insert(pl_parts, {term=canon_pl, qualifiers=pl.qualifiers}) end end if not canon_pl then table.insert(pl_parts, pl) if type(pl) == "table" then pl = pl.term end if not stem:find(" ") and not (pl == stem .. "s" or pl == stem .. "es" or check_ies(pl, stem)) then irregular = true if pl == stem then table.insert(data.categories, lang:getCanonicalName() .. " indeclinable nouns") end end end end if irregular then table.insert(data.categories, "اسم‌های دارای جمع‌های باقاعده " .. lang:getCanonicalName()) end table.insert(data.inflections, pl_parts) end } pos_functions["proper nouns"] = { params = { [1] = {list = true}, }, func = function(args, data) local plurals = args[1] -- Decide what to do next... local mode = nil if plurals[1] == "?" or plurals[1] == "!" or plurals[1] == "-" or plurals[1] == "~" then mode = plurals[1] table.remove(plurals, 1) -- Remove the mode parameter end -- Plural is unknown if mode == "?" then table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unknown or uncertain plurals") return -- Plural is not attested elseif mode == "!" then table.insert(data.inflections, {label = "plural not attested"}) table.insert(data.categories, lang:getCanonicalName() .. " proper nouns with unattested plurals") return -- Uncountable noun; may occasionally have a plural elseif mode == "-" then -- If plural forms were given explicitly, then show "usually" if #plurals > 0 then table.insert(data.inflections, {label = "usually " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") else table.insert(data.inflections, {label = glossary_link("uncountable")}) end -- Mixed countable/uncountable noun, always has a plural elseif mode == "~" then table.insert(data.inflections, {label = glossary_link("countable") .. " and " .. glossary_link("uncountable")}) table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") -- If no plural was given, add a default one now if #plurals == 0 then plurals = {"s"} end elseif #plurals > 0 then table.insert(data.categories, lang:getCanonicalName() .. " countable proper nouns") end -- If there are no plurals to show, return now if #plurals == 0 then return end -- There are plural forms to show, so show them local pl_parts = {label = "plural", accel = {form = "p"}} local stem = PAGENAME for i, pl in ipairs(plurals) do if pl == "s" then table.insert(pl_parts, stem .. "s") elseif pl == "es" then table.insert(pl_parts, stem .. "es") else table.insert(pl_parts, pl) end end table.insert(data.inflections, pl_parts) end } local function base_default_verb_forms(verb) local s_form = default_plural(verb) local ing_form, ed_form local vowel = "aeiouáéíóúàèìòùâêîôûäëïöüæœø" local ulvowel = vowel .. "AEIOUÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÆŒØ" -- (1) Check for C*VC verbs. -- -- flip -> flipping/flipped, strum -> strumming/strummed, nag -> nagging/nagged, etc. -- Do not include words with final -y, e.g. 'stay' (staying/stayed), 'toy' (toying/toyed), -- or with final -w, e.g. 'flow' (flowing/flowed), or with final -h, e.g. 'ah' (ahing/ahed), -- or with final -x, e.g. 'box' (boxing/boxed), or ending in an uppercase consonant, -- e.g. 'XOR' (XORing/XORed), 'OK' (OKing/OKed). Check specially for initial y- as a consonant, -- e.g. 'yip' (yipping/yipped), otherwise treat y as a vowel, so we don't trigger on 'hyphen' -- but do trigger on 'gyp'. local last_cons = mw.ustring.match(verb, "^[Yy][" .. vowel .. "y]([^A-Z" .. vowel .. "ywxh])$") if not last_cons then last_cons = mw.ustring.match(verb, "^[^" .. ulvowel .. "yY]*[" .. ulvowel .. "yY]([^A-Z" .. vowel .. "ywxh])$") end if last_cons then ing_form = verb .. last_cons .. "ing" ed_form = verb .. last_cons .. "ed" else -- (2) Generate -ing form. -- (2a) lie -> lying, untie -> untying, etc. local stem = verb:match("^(.*)ie$") if stem then ing_form = stem .. "ying" else -- (2b) argue -> arguing, sprue -> spruing, dialogue -> dialoguing, etc. stem = verb:match("^(.*)ue$") if stem then ing_form = stem .. "uing" else stem = mw.ustring.match(verb, "^(.*[" .. ulvowel .. "yY][^" .. vowel .. "y]+)e$") if stem then -- (2c) baptize -> baptizing, rake -> raking, type -> typing, parse -> parsing, etc. -- (ending in vowel + consonant(s) + -e); but not referee -> refereeing, -- backhoe -> backhoeing, redye -> redyeing (ending in some other vowel + -e or in -ye); -- and not be -> being (no vowel before the consonant preceding the -e) ing_form = stem .. "ing" else -- (2d) regular verbs ing_form = verb .. "ing" end end end -- (3) Generate -ed form. if verb:find("e$") then -- (3a) baptize -> baptized, rake -> raked, parse -> parsed, free -> freed, hoe -> hoed ed_form = verb .. "d" else stem = mw.ustring.match(verb, "^(.*[^" .. ulvowel .. "yY])y$") if stem then -- (3b) marry -> married, levy -> levied, try -> tried, etc.; but not toy -> toyed ed_form = stem .. "ied" else -- (3c) regular verbs ed_form = verb .. "ed" end end end return s_form, ing_form, ed_form end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil end end pos_functions["فعل‌های"] = { params = { [1] = {list = "pres_3sg", allow_holes = true}, ["pres_3sg_qual"] = {list = "pres_3sg=_qual", allow_holes = true}, [2] = {list = "pres_ptc", allow_holes = true}, ["pres_ptc_qual"] = {list = "pres_ptc=_qual", allow_holes = true}, [3] = {list = "past", allow_holes = true}, ["past_qual"] = {list = "past=_qual", allow_holes = true}, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc_qual"] = {list = "past_ptc=_qual", allow_holes = true}, ["pagename"] = {}, -- for testing }, func = function(args, data) -- Get parameters local par1 = args[1][1] local par2 = args[2][1] local par3 = args[3][1] local par4 = args[4][1] local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = args.pagename or PAGENAME ------------------------------------------- UTILITY FUNCTIONS #1 ------------------------------------------ -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(verb) local last_cons = verb:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. verb .. "' must end in a consonant to use ++") end return verb .. last_cons end local function compute_plusplus_s_form(verb, default_s_form) if verb:find("[sz]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(verb) .. "es" else return default_s_form end end ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local new_default_s, new_default_ing, new_default_ed, split_default_s, split_default_ing, split_default_ed = default_verb_forms(pagename) local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Verb '" .. verb .. "' must have a space in it to use ++*") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("First word '" .. first .. "' must end in a consonant to use ++*") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form) if form == nil then error("Verb '" .. pagename .. "' must have a space in it to use * or ++*") end return form end local function sub_tilde(form) if not form then return nil end local retval = form:gsub("~", pagename) -- discard second return value return retval end local function canonicalize_s_form(form) if form == "+" then return new_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s) elseif form == "++" then return compute_plusplus_s_form(pagename, new_default_s) elseif form == "++*" then if pagename:find("^[^ ]*[sz] ") then return compute_double_last_cons_stem_of_split_verb(pagename, "es") else return check_non_nil_star_form(split_default_s) end else return sub_tilde(form) end end local function canonicalize_ing_form(form) if form == "+" then return new_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ing" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ing") else return sub_tilde(form) end end local function canonicalize_ed_form(form) if form == "+" then return new_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed) elseif form == "++" then return compute_double_last_cons_stem(pagename) .. "ed" elseif form == "++*" then return compute_double_last_cons_stem_of_split_verb(pagename, "ed") else return sub_tilde(form) end end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local past_ptcs_given if par1 and par1:find("<") then -------------------------- ANGLE-BRACKET FORMAT -------------------------- if par2 or par3 or par4 then error("Can't specify 2=, 3= or 4= when 1= contains angle brackets: " .. par1) end -- In the angle bracket format, we always copy the full past tense specs to the past participle -- specs if none of the latter are given, so act as if the past participle is always given. -- There is a separate check to see if the past tense and past participle are identical, in any case. past_ptcs_given = true local iut = require("Module:inflection utilities") -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = iut.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = iut.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec: " .. angle_bracket_spec) end local function fetch_qualifiers(separated_group) local qualifiers for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed qualifiers: '" .. table.concat(separated_group) .. "'") end if not qualifiers then qualifiers = {} end table.insert(qualifiers, separated_group[j]) end return qualifiers end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{}} end local specs = {} local colon_separated_groups = iut.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "++*" then error("* and ++* not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = nil end table.insert(specs, {form = form, qualifiers = fetch_qualifiers(colon_separated_group)}) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) for _, spec in ipairs(s_specs) do if spec.form == "++" and #ing_specs == 1 and not ing_specs[1].form and not ing_specs[1].qualifiers and #ed_specs == 1 and not ed_specs[1].form and not ed_specs[1].qualifiers then ing_specs[1].form = "++" ed_specs[1].form = "++" break end end return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(par1, parse_props) -- (2) Remove any links from the lemma, but remember the original form -- so we can use it below in the 'lemma_linked' form. iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = require("Module:links").remove_links(base.lemma) end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local def_s_form, def_ing_form, def_ed_form = base_default_verb_forms(base.lemma) local function process_specs(slot, specs, default_form, canonicalize_plusplus) for _, spec in ipairs(specs) do local form = spec.form if not form or form == "+" then form = default_form elseif form == "++" then form = canonicalize_plusplus() end -- If there's a ~ in the form, substitute it with the lemma, -- but make sure to first replace % in the lemma with %% so that -- it doesn't get interpreted as a capture replace expression. if form:find("~") then -- Assign to a var because gsub returns multiple values. local subbed_lemma = base.lemma:gsub("%%", "%%%%") form = form:gsub("~", subbed_lemma) end -- If the form is -, don't insert any forms, which will result -- in there being no overall forms (in fact it will be nil). -- We check for that down below and substitute a single "-" as -- the form, which in turn gets turned into special labels like -- "no present participle". if form ~= "-" then iut.insert_form(base.forms, slot, {form = form, footnotes = spec.qualifiers}) end end end process_specs("s_form", base.s_specs, def_s_form, function() return compute_plusplus_s_form(base.lemma, def_s_form) end) process_specs("ing_form", base.ing_specs, def_ing_form, function() return compute_double_last_cons_stem(base.lemma) .. "ing" end) process_specs("ed_form", base.ed_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) -- If the -en spec is completely missing, substitute the -ed spec in its entirely. -- Otherwise, if individual -en forms are missing or use +, we will substitute the -- default -ed form, as with the -ed spec. local en_specs = base.en_specs if #en_specs == 1 and not en_specs[1].form and not en_specs[1].qualifiers then en_specs = base.ed_specs end process_specs("en_form", en_specs, def_ed_form, function() return compute_double_last_cons_stem(base.lemma) .. "ed" end) iut.insert_form(base.forms, "بن‌واژه", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.orig_lemma:find("%[%[") then return base.orig_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_forms(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - -- for a spec. if not forms or #forms == 0 then forms = {{form = "-"}} end return forms end pres_3sgs = fetch_forms("s_form") pres_ptcs = fetch_forms("ing_form") pasts = fetch_forms("ed_form") past_ptcs = fetch_forms("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given. -- If no links in this form and it has multiple words, autolink the individual words. -- The user can override this using head=. if #data.heads == 0 then for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do local lemma = lemma_obj.form if not lemma:find("%[%[") then local m_headword = require("Module:headword") if m_headword.head_is_multiword(lemma) then lemma = m_headword.add_multiword_links(lemma) end end table.insert(data.heads, lemma) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- local pres_3sg, pres_ptc, past if par1 and not par2 and not par3 then -- Use of a single parameter other than "++", "*" or "++*" is now the "legacy" format, -- and no longer supported. if par1 == "es" or par1 == "ies" or par1 == "d" then error("Legacy parameter 1=es/ies/d no longer supported, just use 'en-verb' without params") elseif par1 == "++" or par1 == "*" or par1 == "++*" then pres_3sg = canonicalize_s_form(par1) pres_ptc = canonicalize_ing_form(par1) past = canonicalize_ed_form(par1) else error("Legacy parameter 1=STEM no longer supported, just use 'en-verb' without params") end else if par3 then track("xxx3") elseif par2 then track("xxx2") end end if not pres_3sg or not pres_ptc or not past then -- Either all three should be set above, or none of them. assert(not pres_3sg and not pres_ptc and not past) if par1 then pres_3sg = canonicalize_s_form(par1) else pres_3sg = new_default_s end if par2 then pres_ptc = canonicalize_ing_form(par2) else pres_ptc = new_default_ing end if par3 then past = canonicalize_ed_form(par3) else past = new_default_ed end end if par4 then past_ptcs_given = true past_ptc = canonicalize_ed_form(par4) else past_ptc = past end pres_3sgs = {{form = pres_3sg}} pres_ptcs = {{form = pres_ptc}} pasts = {{form = past}} past_ptcs = {{form = past_ptc}} end ------------------------------------------- HANDLE OVERRIDES ------------------------------------------ local pres_3sg_infls, pres_ptc_infls, past_infls, past_ptc_infls local function strip_brackets(qualifiers) if not qualifiers then return nil end local stripped_qualifiers = {} for _, qualifier in ipairs(qualifiers) do local stripped_qualifier = qualifier:match("^%[(.*)%]$") if not stripped_qualifier then error("Internal error: Qualifier should be surrounded by brackets at this stage: " .. qualifier) end table.insert(stripped_qualifiers, stripped_qualifier) end return stripped_qualifiers end local function collect_forms(label, accel_form, defaults, overrides, override_qualifiers, canonicalize) if defaults[1].form == "-" then return {label = "no " .. label} else local into_table = {label = label, accel = {form = accel_form}} local maxindex = math.max(#defaults, overrides.maxindex) local qualifiers = override_qualifiers[1] and {override_qualifiers[1]} or strip_brackets(defaults[1].footnotes) table.insert(into_table, {term = defaults[1].form, qualifiers = qualifiers}) -- Present 3rd singular for i = 2, maxindex do local override_form = canonicalize(overrides[i]) if override_form then -- If there is an override such as past_ptc2=..., only use the qualifier specified -- using an override (past_ptc2_qual=...), if any; it doesn't make sense to combine -- an override form with a qualifier specified inside of angle brackets. table.insert(into_table, {term = override_form, qualifiers = {override_qualifiers[i]}}) elseif defaults[i] then -- If the form comes from inside angle brackets, allow any override qualifier -- (past_ptc2_qual=...) to override any qualifier specified inside of angle brackets. -- FIXME: Maybe we should throw an error here if both exist. local qualifiers = override_qualifiers[i] and {override_qualifiers[i]} or strip_brackets(defaults[i].footnotes) table.insert(into_table, {term = defaults[i].form, qualifiers = qualifiers}) end end return into_table end end local pres_3sg_infls = collect_forms("third-person singular simple present", "3|s|pres", pres_3sgs, args[1], args.pres_3sg_qual, canonicalize_s_form) local pres_ptc_infls = collect_forms("present participle", "pres|ptcp", pres_ptcs, args[2], args.pres_ptc_qual, canonicalize_ing_form) local past_infls = collect_forms("simple past", "past", pasts, args[3], args.past_qual, canonicalize_ed_form) local past_ptc_infls = collect_forms("past participle", "past|ptcp", past_ptcs, args[4], args.past_ptc_qual, canonicalize_ed_form) -- Are the past forms identical to the past participle forms? If so, we use a single -- combined "simple past and past participle" label on the past tense forms. -- We check for two conditions: Either no past participle forms were given at all, or -- they were given but are identical in every way (all forms and qualifiers) to the past -- tense forms. The former "no explicit past participle forms" check is important in the -- "separate-parameter" format; if past tense overrides are given and no past participle -- forms given, the past tense overrides should apply to the past participle as well. -- In the angle-bracket format, it's expected that all forms and qualifiers are specified -- using that format, and we explicitly copy past tense forms and qualifiers to past -- participle ones if the latter are omitted, so we disable to "no explicit past participle -- forms" check. if args[4].maxindex > 0 or args.past_ptc_qual.maxindex > 0 then past_ptcs_given = true end local identical = true -- For the past and past participle to be identical, there must be -- the same number of inflections, and each inflection must match -- in term and qualifiers. if #past_infls ~= #past_ptc_infls then identical = false else for key, val in ipairs(past_infls) do if past_ptc_infls[key].term ~= val.term then identical = false break else local quals1 = past_ptc_infls[key].qualifiers local quals2 = val.qualifiers if (not not quals1) ~= (not not quals2) then -- one is nil, the other is not identical = false elseif quals1 and quals2 then -- qualifiers present in both; each qualifier must match if #quals1 ~= #quals2 then identical = false else for k, v in ipairs(quals1) do if v ~= quals2[k] then identical = false break end end end end if not identical then break end end end end -- Insert the forms table.insert(data.inflections, pres_3sg_infls) table.insert(data.inflections, pres_ptc_infls) if not past_ptcs_given or identical then if past_ptcs[1].form == "-" then past_infls.label = "no simple past or past participle" else past_infls.label = "simple past and past participle" past_infls.accel = {form = "past|and|past|ptcp"} end table.insert(data.inflections, past_infls) else table.insert(data.inflections, past_infls) table.insert(data.inflections, past_ptc_infls) end end } return export l8jm7cklpqmfd7d8aqtxitl1io52neh پودمان:headword 828 159181 847575 844712 2022-07-23T14:31:09Z Beginneruser 11037 Scribunto text/plain local export = {} local m_data = mw.loadData("Module:headword/data") local title = mw.title.getCurrentTitle() local isLemma = m_data.lemmas local isNonLemma = m_data.nonlemmas local notranslit = m_data.notranslit local toBeTagged = m_data.toBeTagged -- If set to true, categories always appear, even in non-mainspace pages local test_force_categories = false local function test_script(text, script_code) if type(text) == "string" and type(script_code) == "string" then local sc = require("Module:scripts").getByCode(script_code) local characters if sc then characters = sc:getCharacters() end local out if characters then text = mw.ustring.gsub(text, "%W", "") out = mw.ustring.find(text, "[" .. characters .. "]") end if out then return true else return false end else mw.log("Parameters to test_script were incorrect.") return nil end end local spacingPunctuation = "[%s%p]+" --[[ List of punctuation or spacing characters that are found inside of words. Used to exclude characters from the regex above. ]] local wordPunc = "-־׳״'.·*’་•" local notWordPunc = "[^" .. wordPunc .. "]+" -- Return true if the given head is multiword according to the algorithm used -- in full_headword(). function export.head_is_multiword(head) for possibleWordBreak in mw.ustring.gmatch(head, spacingPunctuation) do if mw.ustring.find(possibleWordBreak, notWordPunc) then return true end end return false end -- Add links to a multiword head. function export.add_multiword_links(head) local function workaround_to_exclude_chars(s) return mw.ustring.gsub(s, notWordPunc, "]]%1[[") end head = "[[" .. mw.ustring.gsub( head, spacingPunctuation, workaround_to_exclude_chars ) .. "]]" --[=[ use this when workaround is no longer needed: head = "[[" .. mw.ustring.gsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]" Remove any empty links, which could have been created above at the beginning or end of the string. ]=] head = mw.ustring.gsub(head, "%[%[%]%]", "") return head end local function non_categorizable() return (title:inNamespace("") and title.text:find("^Unsupported titles/")) or (title:inNamespace("پیوست") and title.text:find("^Gestures/")) end local function preprocess(data, postype) --[=[ [[Special:WhatLinksHere/Template:tracking/headword/heads-not-table]] [[Special:WhatLinksHere/Template:tracking/headword/translits-not-table]] ]=] if type(data.heads) ~= "table" then if data.heads then require("Module:debug/track")("headword/heads-not-table") end data.heads = { data.heads } end if type(data.translits) ~= "table" then if data.translits then require("Module:debug/track")("headword/translits-not-table") end data.translits = { data.translits } end if type(data.transcriptions) ~= "table" then if data.transcriptions then require("Module:debug/track")("headword/transcriptions-not-table") end data.transcriptions = { data.transcriptions } end if not data.heads or #data.heads == 0 then data.heads = {""} end -- Determine if term is reconstructed local is_reconstructed = data.lang:getType() == "reconstructed" or title.nsText == "Reconstruction" -- Create a default headword. local subpagename = title.subpageText local pagename = title.text local default_head if is_reconstructed then default_head = require("Module:utilities").plain_gsub(pagename, data.lang:getCanonicalName() .. "/", "") else default_head = subpagename end local unmodified_default_head = default_head -- Add links to multi-word page names when appropriate if data.lang:getCode() ~= "zh" and (not is_reconstructed) and export.head_is_multiword(default_head) then default_head = export.add_multiword_links(default_head) end if is_reconstructed then default_head = "*" .. default_head end -- If a head is the empty string "", then replace it with the default for i, head in ipairs(data.heads) do if head == "" then head = default_head else if head == default_head and data.lang:getCanonicalName() == "English" then table.insert(data.categories, data.lang:getCanonicalName() .. " terms with redundant head parameter") end end data.heads[i] = head end -- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms" if not data.nomultiwordcat and postype == "lemma" and not m_data.no_multiword_cat[data.lang:getCode()] then -- Check for spaces or hyphens, but exclude prefixes and suffixes. -- Use the pagename, not the head= value, because the latter may have extra -- junk in it, e.g. superscripted text that throws off the algorithm. local checkpattern = ".[%s%-፡]." if m_data.hyphen_not_multiword_sep[data.lang:getCode()] then -- Exclude hyphens if the data module states that they should for this language checkpattern = ".[%s፡]." end if mw.ustring.find(unmodified_default_head, checkpattern) and not non_categorizable() then table.insert(data.categories, data.lang:getCanonicalName() .. " multiword terms") end end --[[ Try to detect the script if it was not provided We use the first headword for this, and assume that all of them have the same script This *should* always be true, right? ]] if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads[1], data.lang) end for i, val in pairs(data.translits) do data.translits[i] = {display = val, is_manual = true} end -- Make transliterations for i, head in ipairs(data.heads) do local translit = data.translits[i] -- Try to generate a transliteration if necessary -- Generate it if the script is not Latn or similar, and if no transliteration was provided if translit and translit.display == "-" then translit = nil elseif not translit and not (data.sc:getCode():find("Latn", nil, true) or data.sc:getCode() == "Latinx" or data.sc:getCode() == "None") and (not data.sc or data.sc:getCode() ~= "Imag") then translit = data.lang:transliterate(require("Module:links").remove_links(head), data.sc) -- There is still no transliteration? -- Add the entry to a cleanup category. if not translit and not notranslit[data.lang:getCode()] then translit = "<small>transliteration needed</small>" table.insert(data.categories, "Requests for transliteration of " .. data.lang:getCanonicalName() .. " terms") end if translit then translit = {display = translit, is_manual = false} end end -- Link to the transliteration entry for languages that require this if translit and data.lang:link_tr() then translit.display = require("Module:links").full_link{ term = translit.display, lang = data.lang, sc = require("Module:scripts").getByCode("Latn"), tr = "-" } end data.translits[i] = translit end if data.id and type(data.id) ~= "string" then error("The id in the data table should be a string.") end end -- Format a headword with transliterations local function format_headword(data) local m_scriptutils = require("Module:script utilities") -- Are there non-empty transliterations? -- Need to do it this way because translit[1] might be nil while translit[2] is not local has_translits = false local has_manual_translits = false -- Format the headwords for i, head in ipairs(data.heads) do if data.translits[i] or data.transcriptions[i] then has_translits = true end if data.translits[i] and data.translits[i].is_manual or data.transcriptions[i] then has_manual_translits = true end -- Apply processing to the headword, for formatting links and such if head:find("[[", nil, true) and (not data.sc or data.sc:getCode() ~= "Imag") then head = require("Module:links").language_link({term = head, lang = data.lang}, false) end -- Add language and script wrapper if i == 1 then head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil, data.id) else head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil) end data.heads[i] = head end local translits_formatted = "" if has_manual_translits then -- [[Special:WhatLinksHere/Template:tracking/headword/has-manual-translit/LANG]] require("Module:debug/track")("headword/has-manual-translit/" .. data.lang:getCode()) end if has_translits then -- Format the transliterations local translits = data.translits local transcriptions = data.transcriptions if translits then -- using pairs() instead of ipairs() in case there is a gap for i, _ in pairs(translits) do if type(i) == "number" then translits[i] = m_scriptutils.tag_translit(translits[i].display, data.lang:getCode(), "head", nil, translits[i].is_manual) end end end if transcriptions then for i, _ in pairs(transcriptions) do if type(i) == "number" then transcriptions[i] = m_scriptutils.tag_transcription(transcriptions[i], data.lang:getCode(), "head") end end end for i = 1, math.max(#translits, #transcriptions) do local translits_formatted = {} table.insert(translits_formatted, translits[i] and translits[i] or "") table.insert(translits_formatted, (translits[i] and transcriptions[i]) and " " or "") table.insert(translits_formatted, transcriptions[i] and "/" .. transcriptions[i] .. "/" or "") data.translits[i] = table.concat(translits_formatted) end translits_formatted = " (" .. table.concat(data.translits, " <i>or</i> ") .. ")" local transliteration_page = mw.title.new(data.lang:getCanonicalName() .. " transliteration", "Wiktionary") if transliteration_page then local success, exists = pcall(function () return transliteration_page.exists end) if success and exists then translits_formatted = " [[Wiktionary:" .. data.lang:getCanonicalName() .. " transliteration|•]]" .. translits_formatted end end end return table.concat(data.heads, " <i>or</i> ") .. translits_formatted end local function format_genders(data) if data.genders and #data.genders > 0 then local pos_for_cat if not data.nogendercat and not m_data.no_gender_cat[data.lang:getCode()] then local pos_category = data.pos_category:gsub("^reconstructed ", "") pos_for_cat = m_data.pos_for_gender_number_cat[pos_category] end local text, cats = require("Module:gender and number").format_genders(data.genders, data.lang, pos_for_cat) for _, cat in ipairs(cats) do table.insert(data.categories, cat) end return "&nbsp;" .. text else return "" end end local function format_inflection_parts(data, parts) for key, part in ipairs(parts) do if type(part) ~= "table" then part = {term = part} end local qualifiers local reftext if part.qualifiers and #part.qualifiers > 0 then qualifiers = require("Module:qualifier").format_qualifier(part.qualifiers) .. " " -- [[Special:WhatLinksHere/Template:tracking/headword/qualifier]] require("Module:debug/track")("headword/qualifier") end if part.refs and #part.refs > 0 then local refs = {} for _, ref in ipairs(part.refs) do if type(ref) ~= "table" then ref = {text = ref} end local refargs if ref.name or ref.group then refargs = {name = ref.name, group = ref.group} end table.insert(refs, mw.getCurrentFrame():extensionTag("ref", ref.text, refargs)) end reftext = table.concat(refs) end local partaccel = part.accel local face = part.hypothetical and "hypothetical" or "bold" local nolink = part.hypothetical or part.nolink if part.label then -- There should be a better way of italicizing a label. As is, this isn't customizable. part = "<i>" .. part.label .. "</i>" else -- Convert the term into a full link -- Don't show a transliteration here, the consensus seems to be not to -- show them in headword lines to avoid clutter. part = require("Module:links").full_link( { term = not nolink and part.term or nil, alt = part.alt or (nolink and part.term or nil), lang = part.lang or data.lang, sc = part.sc or parts.sc or (not part.lang and data.sc), id = part.id, genders = part.genders, tr = part.translit or (not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil), ts = part.transcription, accel = parts.accel or partaccel, }, face, false ) end if qualifiers then part = qualifiers .. part end if reftext then part = part .. reftext end parts[key] = part end local parts_output = "" if #parts > 0 then parts_output = " " .. table.concat(parts, " <i>or</i> ") elseif parts.request then parts_output = " <small>[please provide]</small>" .. require("Module:utilities/format_categories")( {"Requests for inflections in " .. data.lang:getCanonicalName() .. " entries"}, lang, nil, nil, data.force_cat_output or test_force_categories, data.sc ) end return "<i>" .. parts.label .. "</i>" .. parts_output end -- Format the inflections following the headword local function format_inflections(data) if data.inflections and #data.inflections > 0 then -- Format each inflection individually for key, infl in ipairs(data.inflections) do data.inflections[key] = format_inflection_parts(data, infl) end return " (" .. table.concat(data.inflections, ", ") .. ")" else return "" end end -- Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil -- if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.). -- If you have a POS in its singular form, call pluralize() in [[Module:string utilities]] to -- pluralize it in a smart fashion that knows when to add '-s' and when to add '-es'. -- -- If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess -- based on whether it ends in " forms"; otherwise, return nil. function export.pos_lemma_or_nonlemma(plpos, best_guess) -- Is it a lemma category? if isLemma[plpos] or isLemma[plpos:gsub("^reconstructed ", "")] then return "lemma" -- Is it a nonlemma category? elseif isNonLemma[plpos] or isNonLemma[plpos:gsub("^reconstructed ", "")] or isLemma[plpos:gsub("^mutated ", "")] or isNonLemma[plpos:gsub("^mutated ", "")] then return "non-lemma form" elseif best_guess then return plpos:find(" forms$") and "non-lemma form" or "lemma" else return nil end end local function show_headword_line(data) local namespace = title.nsText -- Check the namespace against the language type if namespace == "" then if data.lang:getType() == "reconstructed" then error("Entries for this language must be placed in the Reconstruction: namespace.") elseif data.lang:getType() == "appendix-constructed" then error("Entries for this language must be placed in the Appendix: namespace.") end end local tracking_categories = {} if not data.noposcat then local pos_category = data.pos_category .. " " .. data.lang:getCanonicalName() if pos_category ~= "Translingual Han characters" then table.insert(data.categories, 1, pos_category) end end if data.sccat and data.sc then table.insert(data.categories, data.pos_category .. " " .. data.lang:getCanonicalName() .. " در " .. data.sc:getDisplayForm()) end -- Is it a lemma category? local postype = export.pos_lemma_or_nonlemma(data.pos_category) if not postype then -- We don't know what this category is, so tag it with a tracking category. --[=[ [[Special:WhatLinksHere/Template:tracking/headword/unrecognized pos]] ]=] table.insert(tracking_categories, "head tracking/unrecognized pos") require("Module:debug/track"){ "headword/unrecognized pos", "headword/unrecognized pos/lang/" .. data.lang:getCode(), "headword/unrecognized pos/pos/" .. data.pos_category } elseif not data.noposcat then table.insert(data.categories, 1, postype .. "های " .. data.lang:getCanonicalName()) end -- Preprocess preprocess(data, postype) if namespace == "" and data.lang:getType() ~= "reconstructed" then local m_links = require("Module:links") for _, head in ipairs(data.heads) do if title.prefixedText ~= m_links.getLinkPage(m_links.remove_links(head), data.lang) then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/pagename spelling mismatch]] ]=] require("Module:debug/track"){ "headword/pagename spelling mismatch", "headword/pagename spelling mismatch/" .. data.lang:getCode() } break end end end -- Format and return all the gathered information return format_headword(data) .. format_genders(data) .. format_inflections(data) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end function export.full_headword(data) local tracking_categories = {} -- Script-tags the topmost header. local pagename = title.text local fullPagename = title.fullText local namespace = title.nsText if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then error("In data, the first argument to full_headword, data.lang should be a language object.") end if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads and data.heads[1] ~= "" and data.heads[1] or pagename, data.lang) else -- Track uses of sc parameter local best = require("Module:scripts").findBestScript(pagename, data.lang) require("Module:debug/track")("headword/sc") if data.sc:getCode() == best:getCode() then require("Module:debug/track")("headword/sc/redundant") require("Module:debug/track")("headword/sc/redundant/" .. data.sc:getCode()) else require("Module:debug/track")("headword/sc/needed") require("Module:debug/track")("headword/sc/needed/" .. data.sc:getCode()) end end local displayTitle -- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace. -- Avoid tagging ASCII as Hani even when it is tagged as Hani in the -- headword, as in [[check]]. The check for ASCII might need to be expanded -- to a check for any Latin characters and whitespace or punctuation. if (namespace == "" and data.sc and toBeTagged[data.sc:getCode()] and not pagename:find "^[%z\1-\127]+$") or (data.sc:getCode() == "Jpan" and (test_script(pagename, "Hira") or test_script(pagename, "Kana"))) then displayTitle = '<span class="' .. data.sc:getCode() .. '">' .. pagename .. '</span>' elseif namespace == "Reconstruction" then displayTitle, matched = mw.ustring.gsub( fullPagename, "^(Reconstruction:[^/]+/)(.+)$", function(before, term) return before .. require("Module:script utilities").tag_text( term, data.lang, data.sc ) end ) if matched == 0 then displayTitle = nil end end if displayTitle then local frame = mw.getCurrentFrame() frame:callParserFunction( "DISPLAYTITLE", displayTitle ) end if data.force_cat_output then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/force cat output]] ]=] require("Module:debug/track")("headword/force cat output") end if data.getCanonicalName then error('The "data" variable supplied to "full_headword" should not be a language object.') end -- Were any categories specified? if data.categories and #data.categories > 0 then local lang_name = require("Module:string/pattern_escape")(data.lang:getCanonicalName()) for _, cat in ipairs(data.categories) do -- Does the category begin with the language name? If not, tag it with a tracking category. if not mw.ustring.find(cat, "^" .. lang_name) then mw.log(cat, data.lang:getCanonicalName()) table.insert(tracking_categories, "head tracking/no lang category") --[=[ [[Special:WhatLinksHere/Template:tracking/head tracking/no lang category]] ]=] require("Module:debug/track"){ "headword/no lang category", "headword/no lang category/lang/" .. data.lang:getCode() } end end if not data.pos_category and mw.ustring.find(data.categories[1], "^" .. data.lang:getCanonicalName()) then data.pos_category = mw.ustring.gsub(data.categories[1], "^" .. data.lang:getCanonicalName() .. " ", "") table.remove(data.categories, 1) end end if not data.pos_category then error( 'No valid part-of-speech categories were found in the list ' .. 'of categories passed to the function "full_headword". ' .. 'The part-of-speech category should consist of a language\'s ' .. 'canonical name plus a part of speech.' ) end -- Categorise for unusual characters local standard = data.lang:getStandardCharacters() if standard then if mw.ustring.len(title.subpageText) ~= 1 and not non_categorizable() then for character in mw.ustring.gmatch(title.subpageText, "([^" .. standard .. "])") do local upper = mw.ustring.upper(character) if not mw.ustring.find(upper, "[" .. standard .. "]") then character = upper end table.insert( data.categories, data.lang:getCanonicalName() .. " terms spelled with " .. character ) end end end -- Categorise for palindromes if title.nsText ~= "Reconstruction" and mw.ustring.len(title.subpageText)>2 and require('Module:palindromes').is_palindrome( title.subpageText, data.lang, data.sc ) then table.insert(data.categories, data.lang:getCanonicalName() .. " palindromes") end -- This may add more categories (e.g. gender categories), so make sure it gets -- evaluated first. local text = show_headword_line(data) return text .. require("Module:utilities/format_categories")( data.categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end return export c05npqblkosav0dnby1ys08f5oemvn7 847576 847575 2022-07-23T14:41:34Z Beginneruser 11037 Scribunto text/plain local export = {} local m_data = mw.loadData("Module:headword/data") local title = mw.title.getCurrentTitle() local isLemma = m_data.lemmas local isNonLemma = m_data.nonlemmas local notranslit = m_data.notranslit local toBeTagged = m_data.toBeTagged -- If set to true, categories always appear, even in non-mainspace pages local test_force_categories = false local function test_script(text, script_code) if type(text) == "string" and type(script_code) == "string" then local sc = require("Module:scripts").getByCode(script_code) local characters if sc then characters = sc:getCharacters() end local out if characters then text = mw.ustring.gsub(text, "%W", "") out = mw.ustring.find(text, "[" .. characters .. "]") end if out then return true else return false end else mw.log("Parameters to test_script were incorrect.") return nil end end local spacingPunctuation = "[%s%p]+" --[[ List of punctuation or spacing characters that are found inside of words. Used to exclude characters from the regex above. ]] local wordPunc = "-־׳״'.·*’་•" local notWordPunc = "[^" .. wordPunc .. "]+" -- Return true if the given head is multiword according to the algorithm used -- in full_headword(). function export.head_is_multiword(head) for possibleWordBreak in mw.ustring.gmatch(head, spacingPunctuation) do if mw.ustring.find(possibleWordBreak, notWordPunc) then return true end end return false end -- Add links to a multiword head. function export.add_multiword_links(head) local function workaround_to_exclude_chars(s) return mw.ustring.gsub(s, notWordPunc, "]]%1[[") end head = "[[" .. mw.ustring.gsub( head, spacingPunctuation, workaround_to_exclude_chars ) .. "]]" --[=[ use this when workaround is no longer needed: head = "[[" .. mw.ustring.gsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]" Remove any empty links, which could have been created above at the beginning or end of the string. ]=] head = mw.ustring.gsub(head, "%[%[%]%]", "") return head end local function non_categorizable() return (title:inNamespace("") and title.text:find("^Unsupported titles/")) or (title:inNamespace("پیوست") and title.text:find("^Gestures/")) end local function preprocess(data, postype) --[=[ [[Special:WhatLinksHere/Template:tracking/headword/heads-not-table]] [[Special:WhatLinksHere/Template:tracking/headword/translits-not-table]] ]=] if type(data.heads) ~= "table" then if data.heads then require("Module:debug/track")("headword/heads-not-table") end data.heads = { data.heads } end if type(data.translits) ~= "table" then if data.translits then require("Module:debug/track")("headword/translits-not-table") end data.translits = { data.translits } end if type(data.transcriptions) ~= "table" then if data.transcriptions then require("Module:debug/track")("headword/transcriptions-not-table") end data.transcriptions = { data.transcriptions } end if not data.heads or #data.heads == 0 then data.heads = {""} end -- Determine if term is reconstructed local is_reconstructed = data.lang:getType() == "reconstructed" or title.nsText == "Reconstruction" -- Create a default headword. local subpagename = title.subpageText local pagename = title.text local default_head if is_reconstructed then default_head = require("Module:utilities").plain_gsub(pagename, data.lang:getCanonicalName() .. "/", "") else default_head = subpagename end local unmodified_default_head = default_head -- Add links to multi-word page names when appropriate if data.lang:getCode() ~= "zh" and (not is_reconstructed) and export.head_is_multiword(default_head) then default_head = export.add_multiword_links(default_head) end if is_reconstructed then default_head = "*" .. default_head end -- If a head is the empty string "", then replace it with the default for i, head in ipairs(data.heads) do if head == "" then head = default_head else if head == default_head and data.lang:getCanonicalName() == "English" then table.insert(data.categories, data.lang:getCanonicalName() .. " terms with redundant head parameter") end end data.heads[i] = head end -- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms" if not data.nomultiwordcat and postype == "بن‌واژه" and not m_data.no_multiword_cat[data.lang:getCode()] then -- Check for spaces or hyphens, but exclude prefixes and suffixes. -- Use the pagename, not the head= value, because the latter may have extra -- junk in it, e.g. superscripted text that throws off the algorithm. local checkpattern = ".[%s%-፡]." if m_data.hyphen_not_multiword_sep[data.lang:getCode()] then -- Exclude hyphens if the data module states that they should for this language checkpattern = ".[%s፡]." end if mw.ustring.find(unmodified_default_head, checkpattern) and not non_categorizable() then table.insert(data.categories, data.lang:getCanonicalName() .. " multiword terms") end end --[[ Try to detect the script if it was not provided We use the first headword for this, and assume that all of them have the same script This *should* always be true, right? ]] if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads[1], data.lang) end for i, val in pairs(data.translits) do data.translits[i] = {display = val, is_manual = true} end -- Make transliterations for i, head in ipairs(data.heads) do local translit = data.translits[i] -- Try to generate a transliteration if necessary -- Generate it if the script is not Latn or similar, and if no transliteration was provided if translit and translit.display == "-" then translit = nil elseif not translit and not (data.sc:getCode():find("Latn", nil, true) or data.sc:getCode() == "Latinx" or data.sc:getCode() == "None") and (not data.sc or data.sc:getCode() ~= "Imag") then translit = data.lang:transliterate(require("Module:links").remove_links(head), data.sc) -- There is still no transliteration? -- Add the entry to a cleanup category. if not translit and not notranslit[data.lang:getCode()] then translit = "<small>transliteration needed</small>" table.insert(data.categories, "Requests for transliteration of " .. data.lang:getCanonicalName() .. " terms") end if translit then translit = {display = translit, is_manual = false} end end -- Link to the transliteration entry for languages that require this if translit and data.lang:link_tr() then translit.display = require("Module:links").full_link{ term = translit.display, lang = data.lang, sc = require("Module:scripts").getByCode("Latn"), tr = "-" } end data.translits[i] = translit end if data.id and type(data.id) ~= "string" then error("The id in the data table should be a string.") end end -- Format a headword with transliterations local function format_headword(data) local m_scriptutils = require("Module:script utilities") -- Are there non-empty transliterations? -- Need to do it this way because translit[1] might be nil while translit[2] is not local has_translits = false local has_manual_translits = false -- Format the headwords for i, head in ipairs(data.heads) do if data.translits[i] or data.transcriptions[i] then has_translits = true end if data.translits[i] and data.translits[i].is_manual or data.transcriptions[i] then has_manual_translits = true end -- Apply processing to the headword, for formatting links and such if head:find("[[", nil, true) and (not data.sc or data.sc:getCode() ~= "Imag") then head = require("Module:links").language_link({term = head, lang = data.lang}, false) end -- Add language and script wrapper if i == 1 then head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil, data.id) else head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil) end data.heads[i] = head end local translits_formatted = "" if has_manual_translits then -- [[Special:WhatLinksHere/Template:tracking/headword/has-manual-translit/LANG]] require("Module:debug/track")("headword/has-manual-translit/" .. data.lang:getCode()) end if has_translits then -- Format the transliterations local translits = data.translits local transcriptions = data.transcriptions if translits then -- using pairs() instead of ipairs() in case there is a gap for i, _ in pairs(translits) do if type(i) == "number" then translits[i] = m_scriptutils.tag_translit(translits[i].display, data.lang:getCode(), "head", nil, translits[i].is_manual) end end end if transcriptions then for i, _ in pairs(transcriptions) do if type(i) == "number" then transcriptions[i] = m_scriptutils.tag_transcription(transcriptions[i], data.lang:getCode(), "head") end end end for i = 1, math.max(#translits, #transcriptions) do local translits_formatted = {} table.insert(translits_formatted, translits[i] and translits[i] or "") table.insert(translits_formatted, (translits[i] and transcriptions[i]) and " " or "") table.insert(translits_formatted, transcriptions[i] and "/" .. transcriptions[i] .. "/" or "") data.translits[i] = table.concat(translits_formatted) end translits_formatted = " (" .. table.concat(data.translits, " <i>or</i> ") .. ")" local transliteration_page = mw.title.new(data.lang:getCanonicalName() .. " transliteration", "Wiktionary") if transliteration_page then local success, exists = pcall(function () return transliteration_page.exists end) if success and exists then translits_formatted = " [[Wiktionary:" .. data.lang:getCanonicalName() .. " transliteration|•]]" .. translits_formatted end end end return table.concat(data.heads, " <i>or</i> ") .. translits_formatted end local function format_genders(data) if data.genders and #data.genders > 0 then local pos_for_cat if not data.nogendercat and not m_data.no_gender_cat[data.lang:getCode()] then local pos_category = data.pos_category:gsub("^reconstructed ", "") pos_for_cat = m_data.pos_for_gender_number_cat[pos_category] end local text, cats = require("Module:gender and number").format_genders(data.genders, data.lang, pos_for_cat) for _, cat in ipairs(cats) do table.insert(data.categories, cat) end return "&nbsp;" .. text else return "" end end local function format_inflection_parts(data, parts) for key, part in ipairs(parts) do if type(part) ~= "table" then part = {term = part} end local qualifiers local reftext if part.qualifiers and #part.qualifiers > 0 then qualifiers = require("Module:qualifier").format_qualifier(part.qualifiers) .. " " -- [[Special:WhatLinksHere/Template:tracking/headword/qualifier]] require("Module:debug/track")("headword/qualifier") end if part.refs and #part.refs > 0 then local refs = {} for _, ref in ipairs(part.refs) do if type(ref) ~= "table" then ref = {text = ref} end local refargs if ref.name or ref.group then refargs = {name = ref.name, group = ref.group} end table.insert(refs, mw.getCurrentFrame():extensionTag("ref", ref.text, refargs)) end reftext = table.concat(refs) end local partaccel = part.accel local face = part.hypothetical and "hypothetical" or "bold" local nolink = part.hypothetical or part.nolink if part.label then -- There should be a better way of italicizing a label. As is, this isn't customizable. part = "<i>" .. part.label .. "</i>" else -- Convert the term into a full link -- Don't show a transliteration here, the consensus seems to be not to -- show them in headword lines to avoid clutter. part = require("Module:links").full_link( { term = not nolink and part.term or nil, alt = part.alt or (nolink and part.term or nil), lang = part.lang or data.lang, sc = part.sc or parts.sc or (not part.lang and data.sc), id = part.id, genders = part.genders, tr = part.translit or (not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil), ts = part.transcription, accel = parts.accel or partaccel, }, face, false ) end if qualifiers then part = qualifiers .. part end if reftext then part = part .. reftext end parts[key] = part end local parts_output = "" if #parts > 0 then parts_output = " " .. table.concat(parts, " <i>or</i> ") elseif parts.request then parts_output = " <small>[please provide]</small>" .. require("Module:utilities/format_categories")( {"Requests for inflections in " .. data.lang:getCanonicalName() .. " entries"}, lang, nil, nil, data.force_cat_output or test_force_categories, data.sc ) end return "<i>" .. parts.label .. "</i>" .. parts_output end -- Format the inflections following the headword local function format_inflections(data) if data.inflections and #data.inflections > 0 then -- Format each inflection individually for key, infl in ipairs(data.inflections) do data.inflections[key] = format_inflection_parts(data, infl) end return " (" .. table.concat(data.inflections, ", ") .. ")" else return "" end end -- Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil -- if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.). -- If you have a POS in its singular form, call pluralize() in [[Module:string utilities]] to -- pluralize it in a smart fashion that knows when to add '-s' and when to add '-es'. -- -- If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess -- based on whether it ends in " forms"; otherwise, return nil. function export.pos_lemma_or_nonlemma(plpos, best_guess) -- Is it a lemma category? if isLemma[plpos] or isLemma[plpos:gsub("^reconstructed ", "")] then return "lemma" -- Is it a nonlemma category? elseif isNonLemma[plpos] or isNonLemma[plpos:gsub("^reconstructed ", "")] or isLemma[plpos:gsub("^mutated ", "")] or isNonLemma[plpos:gsub("^mutated ", "")] then return "شکل غیر بن‌واژه" elseif best_guess then return plpos:find(" forms$") and "شکل غیر بن‌واژه" or "بن‌واژه" else return nil end end local function show_headword_line(data) local namespace = title.nsText -- Check the namespace against the language type if namespace == "" then if data.lang:getType() == "reconstructed" then error("Entries for this language must be placed in the Reconstruction: namespace.") elseif data.lang:getType() == "appendix-constructed" then error("Entries for this language must be placed in the Appendix: namespace.") end end local tracking_categories = {} if not data.noposcat then local pos_category = data.pos_category .. " " .. data.lang:getCanonicalName() if pos_category ~= "Translingual Han characters" then table.insert(data.categories, 1, pos_category) end end if data.sccat and data.sc then table.insert(data.categories, data.pos_category .. " " .. data.lang:getCanonicalName() .. " در " .. data.sc:getDisplayForm()) end -- Is it a lemma category? local postype = export.pos_lemma_or_nonlemma(data.pos_category) if not postype then -- We don't know what this category is, so tag it with a tracking category. --[=[ [[Special:WhatLinksHere/Template:tracking/headword/unrecognized pos]] ]=] table.insert(tracking_categories, "head tracking/unrecognized pos") require("Module:debug/track"){ "headword/unrecognized pos", "headword/unrecognized pos/lang/" .. data.lang:getCode(), "headword/unrecognized pos/pos/" .. data.pos_category } elseif not data.noposcat then table.insert(data.categories, 1, postype .. "های " .. data.lang:getCanonicalName()) end -- Preprocess preprocess(data, postype) if namespace == "" and data.lang:getType() ~= "reconstructed" then local m_links = require("Module:links") for _, head in ipairs(data.heads) do if title.prefixedText ~= m_links.getLinkPage(m_links.remove_links(head), data.lang) then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/pagename spelling mismatch]] ]=] require("Module:debug/track"){ "headword/pagename spelling mismatch", "headword/pagename spelling mismatch/" .. data.lang:getCode() } break end end end -- Format and return all the gathered information return format_headword(data) .. format_genders(data) .. format_inflections(data) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end function export.full_headword(data) local tracking_categories = {} -- Script-tags the topmost header. local pagename = title.text local fullPagename = title.fullText local namespace = title.nsText if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then error("In data, the first argument to full_headword, data.lang should be a language object.") end if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads and data.heads[1] ~= "" and data.heads[1] or pagename, data.lang) else -- Track uses of sc parameter local best = require("Module:scripts").findBestScript(pagename, data.lang) require("Module:debug/track")("headword/sc") if data.sc:getCode() == best:getCode() then require("Module:debug/track")("headword/sc/redundant") require("Module:debug/track")("headword/sc/redundant/" .. data.sc:getCode()) else require("Module:debug/track")("headword/sc/needed") require("Module:debug/track")("headword/sc/needed/" .. data.sc:getCode()) end end local displayTitle -- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace. -- Avoid tagging ASCII as Hani even when it is tagged as Hani in the -- headword, as in [[check]]. The check for ASCII might need to be expanded -- to a check for any Latin characters and whitespace or punctuation. if (namespace == "" and data.sc and toBeTagged[data.sc:getCode()] and not pagename:find "^[%z\1-\127]+$") or (data.sc:getCode() == "Jpan" and (test_script(pagename, "Hira") or test_script(pagename, "Kana"))) then displayTitle = '<span class="' .. data.sc:getCode() .. '">' .. pagename .. '</span>' elseif namespace == "Reconstruction" then displayTitle, matched = mw.ustring.gsub( fullPagename, "^(Reconstruction:[^/]+/)(.+)$", function(before, term) return before .. require("Module:script utilities").tag_text( term, data.lang, data.sc ) end ) if matched == 0 then displayTitle = nil end end if displayTitle then local frame = mw.getCurrentFrame() frame:callParserFunction( "DISPLAYTITLE", displayTitle ) end if data.force_cat_output then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/force cat output]] ]=] require("Module:debug/track")("headword/force cat output") end if data.getCanonicalName then error('The "data" variable supplied to "full_headword" should not be a language object.') end -- Were any categories specified? if data.categories and #data.categories > 0 then local lang_name = require("Module:string/pattern_escape")(data.lang:getCanonicalName()) for _, cat in ipairs(data.categories) do -- Does the category begin with the language name? If not, tag it with a tracking category. if not mw.ustring.find(cat, "^" .. lang_name) then mw.log(cat, data.lang:getCanonicalName()) table.insert(tracking_categories, "head tracking/no lang category") --[=[ [[Special:WhatLinksHere/Template:tracking/head tracking/no lang category]] ]=] require("Module:debug/track"){ "headword/no lang category", "headword/no lang category/lang/" .. data.lang:getCode() } end end if not data.pos_category and mw.ustring.find(data.categories[1], "^" .. data.lang:getCanonicalName()) then data.pos_category = mw.ustring.gsub(data.categories[1], "^" .. data.lang:getCanonicalName() .. " ", "") table.remove(data.categories, 1) end end if not data.pos_category then error( 'No valid part-of-speech categories were found in the list ' .. 'of categories passed to the function "full_headword". ' .. 'The part-of-speech category should consist of a language\'s ' .. 'canonical name plus a part of speech.' ) end -- Categorise for unusual characters local standard = data.lang:getStandardCharacters() if standard then if mw.ustring.len(title.subpageText) ~= 1 and not non_categorizable() then for character in mw.ustring.gmatch(title.subpageText, "([^" .. standard .. "])") do local upper = mw.ustring.upper(character) if not mw.ustring.find(upper, "[" .. standard .. "]") then character = upper end table.insert( data.categories, data.lang:getCanonicalName() .. " terms spelled with " .. character ) end end end -- Categorise for palindromes if title.nsText ~= "Reconstruction" and mw.ustring.len(title.subpageText)>2 and require('Module:palindromes').is_palindrome( title.subpageText, data.lang, data.sc ) then table.insert(data.categories, data.lang:getCanonicalName() .. " palindromes") end -- This may add more categories (e.g. gender categories), so make sure it gets -- evaluated first. local text = show_headword_line(data) return text .. require("Module:utilities/format_categories")( data.categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end return export 5p53q6dstd3ya25000y85xkbrj41hsr 847578 847576 2022-07-23T14:45:07Z Beginneruser 11037 Scribunto text/plain local export = {} local m_data = mw.loadData("Module:headword/data") local title = mw.title.getCurrentTitle() local isLemma = m_data.lemmas local isNonLemma = m_data.nonlemmas local notranslit = m_data.notranslit local toBeTagged = m_data.toBeTagged -- If set to true, categories always appear, even in non-mainspace pages local test_force_categories = false local function test_script(text, script_code) if type(text) == "string" and type(script_code) == "string" then local sc = require("Module:scripts").getByCode(script_code) local characters if sc then characters = sc:getCharacters() end local out if characters then text = mw.ustring.gsub(text, "%W", "") out = mw.ustring.find(text, "[" .. characters .. "]") end if out then return true else return false end else mw.log("Parameters to test_script were incorrect.") return nil end end local spacingPunctuation = "[%s%p]+" --[[ List of punctuation or spacing characters that are found inside of words. Used to exclude characters from the regex above. ]] local wordPunc = "-־׳״'.·*’་•" local notWordPunc = "[^" .. wordPunc .. "]+" -- Return true if the given head is multiword according to the algorithm used -- in full_headword(). function export.head_is_multiword(head) for possibleWordBreak in mw.ustring.gmatch(head, spacingPunctuation) do if mw.ustring.find(possibleWordBreak, notWordPunc) then return true end end return false end -- Add links to a multiword head. function export.add_multiword_links(head) local function workaround_to_exclude_chars(s) return mw.ustring.gsub(s, notWordPunc, "]]%1[[") end head = "[[" .. mw.ustring.gsub( head, spacingPunctuation, workaround_to_exclude_chars ) .. "]]" --[=[ use this when workaround is no longer needed: head = "[[" .. mw.ustring.gsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]" Remove any empty links, which could have been created above at the beginning or end of the string. ]=] head = mw.ustring.gsub(head, "%[%[%]%]", "") return head end local function non_categorizable() return (title:inNamespace("") and title.text:find("^Unsupported titles/")) or (title:inNamespace("پیوست") and title.text:find("^Gestures/")) end local function preprocess(data, postype) --[=[ [[Special:WhatLinksHere/Template:tracking/headword/heads-not-table]] [[Special:WhatLinksHere/Template:tracking/headword/translits-not-table]] ]=] if type(data.heads) ~= "table" then if data.heads then require("Module:debug/track")("headword/heads-not-table") end data.heads = { data.heads } end if type(data.translits) ~= "table" then if data.translits then require("Module:debug/track")("headword/translits-not-table") end data.translits = { data.translits } end if type(data.transcriptions) ~= "table" then if data.transcriptions then require("Module:debug/track")("headword/transcriptions-not-table") end data.transcriptions = { data.transcriptions } end if not data.heads or #data.heads == 0 then data.heads = {""} end -- Determine if term is reconstructed local is_reconstructed = data.lang:getType() == "reconstructed" or title.nsText == "Reconstruction" -- Create a default headword. local subpagename = title.subpageText local pagename = title.text local default_head if is_reconstructed then default_head = require("Module:utilities").plain_gsub(pagename, data.lang:getCanonicalName() .. "/", "") else default_head = subpagename end local unmodified_default_head = default_head -- Add links to multi-word page names when appropriate if data.lang:getCode() ~= "zh" and (not is_reconstructed) and export.head_is_multiword(default_head) then default_head = export.add_multiword_links(default_head) end if is_reconstructed then default_head = "*" .. default_head end -- If a head is the empty string "", then replace it with the default for i, head in ipairs(data.heads) do if head == "" then head = default_head else if head == default_head and data.lang:getCanonicalName() == "English" then table.insert(data.categories, data.lang:getCanonicalName() .. " terms with redundant head parameter") end end data.heads[i] = head end -- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms" if not data.nomultiwordcat and postype == "بن‌واژه" and not m_data.no_multiword_cat[data.lang:getCode()] then -- Check for spaces or hyphens, but exclude prefixes and suffixes. -- Use the pagename, not the head= value, because the latter may have extra -- junk in it, e.g. superscripted text that throws off the algorithm. local checkpattern = ".[%s%-፡]." if m_data.hyphen_not_multiword_sep[data.lang:getCode()] then -- Exclude hyphens if the data module states that they should for this language checkpattern = ".[%s፡]." end if mw.ustring.find(unmodified_default_head, checkpattern) and not non_categorizable() then table.insert(data.categories, data.lang:getCanonicalName() .. " multiword terms") end end --[[ Try to detect the script if it was not provided We use the first headword for this, and assume that all of them have the same script This *should* always be true, right? ]] if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads[1], data.lang) end for i, val in pairs(data.translits) do data.translits[i] = {display = val, is_manual = true} end -- Make transliterations for i, head in ipairs(data.heads) do local translit = data.translits[i] -- Try to generate a transliteration if necessary -- Generate it if the script is not Latn or similar, and if no transliteration was provided if translit and translit.display == "-" then translit = nil elseif not translit and not (data.sc:getCode():find("Latn", nil, true) or data.sc:getCode() == "Latinx" or data.sc:getCode() == "None") and (not data.sc or data.sc:getCode() ~= "Imag") then translit = data.lang:transliterate(require("Module:links").remove_links(head), data.sc) -- There is still no transliteration? -- Add the entry to a cleanup category. if not translit and not notranslit[data.lang:getCode()] then translit = "<small>transliteration needed</small>" table.insert(data.categories, "Requests for transliteration of " .. data.lang:getCanonicalName() .. " terms") end if translit then translit = {display = translit, is_manual = false} end end -- Link to the transliteration entry for languages that require this if translit and data.lang:link_tr() then translit.display = require("Module:links").full_link{ term = translit.display, lang = data.lang, sc = require("Module:scripts").getByCode("Latn"), tr = "-" } end data.translits[i] = translit end if data.id and type(data.id) ~= "string" then error("The id in the data table should be a string.") end end -- Format a headword with transliterations local function format_headword(data) local m_scriptutils = require("Module:script utilities") -- Are there non-empty transliterations? -- Need to do it this way because translit[1] might be nil while translit[2] is not local has_translits = false local has_manual_translits = false -- Format the headwords for i, head in ipairs(data.heads) do if data.translits[i] or data.transcriptions[i] then has_translits = true end if data.translits[i] and data.translits[i].is_manual or data.transcriptions[i] then has_manual_translits = true end -- Apply processing to the headword, for formatting links and such if head:find("[[", nil, true) and (not data.sc or data.sc:getCode() ~= "Imag") then head = require("Module:links").language_link({term = head, lang = data.lang}, false) end -- Add language and script wrapper if i == 1 then head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil, data.id) else head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil) end data.heads[i] = head end local translits_formatted = "" if has_manual_translits then -- [[Special:WhatLinksHere/Template:tracking/headword/has-manual-translit/LANG]] require("Module:debug/track")("headword/has-manual-translit/" .. data.lang:getCode()) end if has_translits then -- Format the transliterations local translits = data.translits local transcriptions = data.transcriptions if translits then -- using pairs() instead of ipairs() in case there is a gap for i, _ in pairs(translits) do if type(i) == "number" then translits[i] = m_scriptutils.tag_translit(translits[i].display, data.lang:getCode(), "head", nil, translits[i].is_manual) end end end if transcriptions then for i, _ in pairs(transcriptions) do if type(i) == "number" then transcriptions[i] = m_scriptutils.tag_transcription(transcriptions[i], data.lang:getCode(), "head") end end end for i = 1, math.max(#translits, #transcriptions) do local translits_formatted = {} table.insert(translits_formatted, translits[i] and translits[i] or "") table.insert(translits_formatted, (translits[i] and transcriptions[i]) and " " or "") table.insert(translits_formatted, transcriptions[i] and "/" .. transcriptions[i] .. "/" or "") data.translits[i] = table.concat(translits_formatted) end translits_formatted = " (" .. table.concat(data.translits, " <i>or</i> ") .. ")" local transliteration_page = mw.title.new(data.lang:getCanonicalName() .. " transliteration", "Wiktionary") if transliteration_page then local success, exists = pcall(function () return transliteration_page.exists end) if success and exists then translits_formatted = " [[Wiktionary:" .. data.lang:getCanonicalName() .. " transliteration|•]]" .. translits_formatted end end end return table.concat(data.heads, " <i>or</i> ") .. translits_formatted end local function format_genders(data) if data.genders and #data.genders > 0 then local pos_for_cat if not data.nogendercat and not m_data.no_gender_cat[data.lang:getCode()] then local pos_category = data.pos_category:gsub("^reconstructed ", "") pos_for_cat = m_data.pos_for_gender_number_cat[pos_category] end local text, cats = require("Module:gender and number").format_genders(data.genders, data.lang, pos_for_cat) for _, cat in ipairs(cats) do table.insert(data.categories, cat) end return "&nbsp;" .. text else return "" end end local function format_inflection_parts(data, parts) for key, part in ipairs(parts) do if type(part) ~= "table" then part = {term = part} end local qualifiers local reftext if part.qualifiers and #part.qualifiers > 0 then qualifiers = require("Module:qualifier").format_qualifier(part.qualifiers) .. " " -- [[Special:WhatLinksHere/Template:tracking/headword/qualifier]] require("Module:debug/track")("headword/qualifier") end if part.refs and #part.refs > 0 then local refs = {} for _, ref in ipairs(part.refs) do if type(ref) ~= "table" then ref = {text = ref} end local refargs if ref.name or ref.group then refargs = {name = ref.name, group = ref.group} end table.insert(refs, mw.getCurrentFrame():extensionTag("ref", ref.text, refargs)) end reftext = table.concat(refs) end local partaccel = part.accel local face = part.hypothetical and "hypothetical" or "bold" local nolink = part.hypothetical or part.nolink if part.label then -- There should be a better way of italicizing a label. As is, this isn't customizable. part = "<i>" .. part.label .. "</i>" else -- Convert the term into a full link -- Don't show a transliteration here, the consensus seems to be not to -- show them in headword lines to avoid clutter. part = require("Module:links").full_link( { term = not nolink and part.term or nil, alt = part.alt or (nolink and part.term or nil), lang = part.lang or data.lang, sc = part.sc or parts.sc or (not part.lang and data.sc), id = part.id, genders = part.genders, tr = part.translit or (not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil), ts = part.transcription, accel = parts.accel or partaccel, }, face, false ) end if qualifiers then part = qualifiers .. part end if reftext then part = part .. reftext end parts[key] = part end local parts_output = "" if #parts > 0 then parts_output = " " .. table.concat(parts, " <i>or</i> ") elseif parts.request then parts_output = " <small>[please provide]</small>" .. require("Module:utilities/format_categories")( {"Requests for inflections in " .. data.lang:getCanonicalName() .. " entries"}, lang, nil, nil, data.force_cat_output or test_force_categories, data.sc ) end return "<i>" .. parts.label .. "</i>" .. parts_output end -- Format the inflections following the headword local function format_inflections(data) if data.inflections and #data.inflections > 0 then -- Format each inflection individually for key, infl in ipairs(data.inflections) do data.inflections[key] = format_inflection_parts(data, infl) end return " (" .. table.concat(data.inflections, ", ") .. ")" else return "" end end -- Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil -- if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.). -- If you have a POS in its singular form, call pluralize() in [[Module:string utilities]] to -- pluralize it in a smart fashion that knows when to add '-s' and when to add '-es'. -- -- If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess -- based on whether it ends in " forms"; otherwise, return nil. function export.pos_lemma_or_nonlemma(plpos, best_guess) -- Is it a lemma category? if isLemma[plpos] or isLemma[plpos:gsub("^reconstructed ", "")] then return "بن‌واژه" -- Is it a nonlemma category? elseif isNonLemma[plpos] or isNonLemma[plpos:gsub("^reconstructed ", "")] or isLemma[plpos:gsub("^mutated ", "")] or isNonLemma[plpos:gsub("^mutated ", "")] then return "شکل غیر بن‌واژه" elseif best_guess then return plpos:find(" forms$") and "شکل غیر بن‌واژه" or "بن‌واژه" else return nil end end local function show_headword_line(data) local namespace = title.nsText -- Check the namespace against the language type if namespace == "" then if data.lang:getType() == "reconstructed" then error("Entries for this language must be placed in the Reconstruction: namespace.") elseif data.lang:getType() == "appendix-constructed" then error("Entries for this language must be placed in the Appendix: namespace.") end end local tracking_categories = {} if not data.noposcat then local pos_category = data.pos_category .. " " .. data.lang:getCanonicalName() if pos_category ~= "Translingual Han characters" then table.insert(data.categories, 1, pos_category) end end if data.sccat and data.sc then table.insert(data.categories, data.pos_category .. " " .. data.lang:getCanonicalName() .. " در " .. data.sc:getDisplayForm()) end -- Is it a lemma category? local postype = export.pos_lemma_or_nonlemma(data.pos_category) if not postype then -- We don't know what this category is, so tag it with a tracking category. --[=[ [[Special:WhatLinksHere/Template:tracking/headword/unrecognized pos]] ]=] table.insert(tracking_categories, "head tracking/unrecognized pos") require("Module:debug/track"){ "headword/unrecognized pos", "headword/unrecognized pos/lang/" .. data.lang:getCode(), "headword/unrecognized pos/pos/" .. data.pos_category } elseif not data.noposcat then table.insert(data.categories, 1, postype .. "های " .. data.lang:getCanonicalName()) end -- Preprocess preprocess(data, postype) if namespace == "" and data.lang:getType() ~= "reconstructed" then local m_links = require("Module:links") for _, head in ipairs(data.heads) do if title.prefixedText ~= m_links.getLinkPage(m_links.remove_links(head), data.lang) then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/pagename spelling mismatch]] ]=] require("Module:debug/track"){ "headword/pagename spelling mismatch", "headword/pagename spelling mismatch/" .. data.lang:getCode() } break end end end -- Format and return all the gathered information return format_headword(data) .. format_genders(data) .. format_inflections(data) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end function export.full_headword(data) local tracking_categories = {} -- Script-tags the topmost header. local pagename = title.text local fullPagename = title.fullText local namespace = title.nsText if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then error("In data, the first argument to full_headword, data.lang should be a language object.") end if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads and data.heads[1] ~= "" and data.heads[1] or pagename, data.lang) else -- Track uses of sc parameter local best = require("Module:scripts").findBestScript(pagename, data.lang) require("Module:debug/track")("headword/sc") if data.sc:getCode() == best:getCode() then require("Module:debug/track")("headword/sc/redundant") require("Module:debug/track")("headword/sc/redundant/" .. data.sc:getCode()) else require("Module:debug/track")("headword/sc/needed") require("Module:debug/track")("headword/sc/needed/" .. data.sc:getCode()) end end local displayTitle -- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace. -- Avoid tagging ASCII as Hani even when it is tagged as Hani in the -- headword, as in [[check]]. The check for ASCII might need to be expanded -- to a check for any Latin characters and whitespace or punctuation. if (namespace == "" and data.sc and toBeTagged[data.sc:getCode()] and not pagename:find "^[%z\1-\127]+$") or (data.sc:getCode() == "Jpan" and (test_script(pagename, "Hira") or test_script(pagename, "Kana"))) then displayTitle = '<span class="' .. data.sc:getCode() .. '">' .. pagename .. '</span>' elseif namespace == "Reconstruction" then displayTitle, matched = mw.ustring.gsub( fullPagename, "^(Reconstruction:[^/]+/)(.+)$", function(before, term) return before .. require("Module:script utilities").tag_text( term, data.lang, data.sc ) end ) if matched == 0 then displayTitle = nil end end if displayTitle then local frame = mw.getCurrentFrame() frame:callParserFunction( "DISPLAYTITLE", displayTitle ) end if data.force_cat_output then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/force cat output]] ]=] require("Module:debug/track")("headword/force cat output") end if data.getCanonicalName then error('The "data" variable supplied to "full_headword" should not be a language object.') end -- Were any categories specified? if data.categories and #data.categories > 0 then local lang_name = require("Module:string/pattern_escape")(data.lang:getCanonicalName()) for _, cat in ipairs(data.categories) do -- Does the category begin with the language name? If not, tag it with a tracking category. if not mw.ustring.find(cat, "^" .. lang_name) then mw.log(cat, data.lang:getCanonicalName()) table.insert(tracking_categories, "head tracking/no lang category") --[=[ [[Special:WhatLinksHere/Template:tracking/head tracking/no lang category]] ]=] require("Module:debug/track"){ "headword/no lang category", "headword/no lang category/lang/" .. data.lang:getCode() } end end if not data.pos_category and mw.ustring.find(data.categories[1], "^" .. data.lang:getCanonicalName()) then data.pos_category = mw.ustring.gsub(data.categories[1], "^" .. data.lang:getCanonicalName() .. " ", "") table.remove(data.categories, 1) end end if not data.pos_category then error( 'No valid part-of-speech categories were found in the list ' .. 'of categories passed to the function "full_headword". ' .. 'The part-of-speech category should consist of a language\'s ' .. 'canonical name plus a part of speech.' ) end -- Categorise for unusual characters local standard = data.lang:getStandardCharacters() if standard then if mw.ustring.len(title.subpageText) ~= 1 and not non_categorizable() then for character in mw.ustring.gmatch(title.subpageText, "([^" .. standard .. "])") do local upper = mw.ustring.upper(character) if not mw.ustring.find(upper, "[" .. standard .. "]") then character = upper end table.insert( data.categories, data.lang:getCanonicalName() .. " terms spelled with " .. character ) end end end -- Categorise for palindromes if title.nsText ~= "Reconstruction" and mw.ustring.len(title.subpageText)>2 and require('Module:palindromes').is_palindrome( title.subpageText, data.lang, data.sc ) then table.insert(data.categories, data.lang:getCanonicalName() .. " palindromes") end -- This may add more categories (e.g. gender categories), so make sure it gets -- evaluated first. local text = show_headword_line(data) return text .. require("Module:utilities/format_categories")( data.categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end return export 0t6dk99tdx0qe05qpajl7ehktz99u3z 847579 847578 2022-07-23T14:46:35Z Beginneruser 11037 Scribunto text/plain local export = {} local m_data = mw.loadData("Module:headword/data") local title = mw.title.getCurrentTitle() local isLemma = m_data.lemmas local isNonLemma = m_data.nonlemmas local notranslit = m_data.notranslit local toBeTagged = m_data.toBeTagged -- If set to true, categories always appear, even in non-mainspace pages local test_force_categories = false local function test_script(text, script_code) if type(text) == "string" and type(script_code) == "string" then local sc = require("Module:scripts").getByCode(script_code) local characters if sc then characters = sc:getCharacters() end local out if characters then text = mw.ustring.gsub(text, "%W", "") out = mw.ustring.find(text, "[" .. characters .. "]") end if out then return true else return false end else mw.log("Parameters to test_script were incorrect.") return nil end end local spacingPunctuation = "[%s%p]+" --[[ List of punctuation or spacing characters that are found inside of words. Used to exclude characters from the regex above. ]] local wordPunc = "-־׳״'.·*’་•" local notWordPunc = "[^" .. wordPunc .. "]+" -- Return true if the given head is multiword according to the algorithm used -- in full_headword(). function export.head_is_multiword(head) for possibleWordBreak in mw.ustring.gmatch(head, spacingPunctuation) do if mw.ustring.find(possibleWordBreak, notWordPunc) then return true end end return false end -- Add links to a multiword head. function export.add_multiword_links(head) local function workaround_to_exclude_chars(s) return mw.ustring.gsub(s, notWordPunc, "]]%1[[") end head = "[[" .. mw.ustring.gsub( head, spacingPunctuation, workaround_to_exclude_chars ) .. "]]" --[=[ use this when workaround is no longer needed: head = "[[" .. mw.ustring.gsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]" Remove any empty links, which could have been created above at the beginning or end of the string. ]=] head = mw.ustring.gsub(head, "%[%[%]%]", "") return head end local function non_categorizable() return (title:inNamespace("") and title.text:find("^Unsupported titles/")) or (title:inNamespace("پیوست") and title.text:find("^Gestures/")) end local function preprocess(data, postype) --[=[ [[Special:WhatLinksHere/Template:tracking/headword/heads-not-table]] [[Special:WhatLinksHere/Template:tracking/headword/translits-not-table]] ]=] if type(data.heads) ~= "table" then if data.heads then require("Module:debug/track")("headword/heads-not-table") end data.heads = { data.heads } end if type(data.translits) ~= "table" then if data.translits then require("Module:debug/track")("headword/translits-not-table") end data.translits = { data.translits } end if type(data.transcriptions) ~= "table" then if data.transcriptions then require("Module:debug/track")("headword/transcriptions-not-table") end data.transcriptions = { data.transcriptions } end if not data.heads or #data.heads == 0 then data.heads = {""} end -- Determine if term is reconstructed local is_reconstructed = data.lang:getType() == "reconstructed" or title.nsText == "Reconstruction" -- Create a default headword. local subpagename = title.subpageText local pagename = title.text local default_head if is_reconstructed then default_head = require("Module:utilities").plain_gsub(pagename, data.lang:getCanonicalName() .. "/", "") else default_head = subpagename end local unmodified_default_head = default_head -- Add links to multi-word page names when appropriate if data.lang:getCode() ~= "zh" and (not is_reconstructed) and export.head_is_multiword(default_head) then default_head = export.add_multiword_links(default_head) end if is_reconstructed then default_head = "*" .. default_head end -- If a head is the empty string "", then replace it with the default for i, head in ipairs(data.heads) do if head == "" then head = default_head else if head == default_head and data.lang:getCanonicalName() == "English" then table.insert(data.categories, data.lang:getCanonicalName() .. " terms with redundant head parameter") end end data.heads[i] = head end -- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms" if not data.nomultiwordcat and postype == "بن‌واژه" and not m_data.no_multiword_cat[data.lang:getCode()] then -- Check for spaces or hyphens, but exclude prefixes and suffixes. -- Use the pagename, not the head= value, because the latter may have extra -- junk in it, e.g. superscripted text that throws off the algorithm. local checkpattern = ".[%s%-፡]." if m_data.hyphen_not_multiword_sep[data.lang:getCode()] then -- Exclude hyphens if the data module states that they should for this language checkpattern = ".[%s፡]." end if mw.ustring.find(unmodified_default_head, checkpattern) and not non_categorizable() then table.insert(data.categories, data.lang:getCanonicalName() .. " multiword terms") end end --[[ Try to detect the script if it was not provided We use the first headword for this, and assume that all of them have the same script This *should* always be true, right? ]] if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads[1], data.lang) end for i, val in pairs(data.translits) do data.translits[i] = {display = val, is_manual = true} end -- Make transliterations for i, head in ipairs(data.heads) do local translit = data.translits[i] -- Try to generate a transliteration if necessary -- Generate it if the script is not Latn or similar, and if no transliteration was provided if translit and translit.display == "-" then translit = nil elseif not translit and not (data.sc:getCode():find("Latn", nil, true) or data.sc:getCode() == "Latinx" or data.sc:getCode() == "None") and (not data.sc or data.sc:getCode() ~= "Imag") then translit = data.lang:transliterate(require("Module:links").remove_links(head), data.sc) -- There is still no transliteration? -- Add the entry to a cleanup category. if not translit and not notranslit[data.lang:getCode()] then translit = "<small>transliteration needed</small>" table.insert(data.categories, "Requests for transliteration of " .. data.lang:getCanonicalName() .. " terms") end if translit then translit = {display = translit, is_manual = false} end end -- Link to the transliteration entry for languages that require this if translit and data.lang:link_tr() then translit.display = require("Module:links").full_link{ term = translit.display, lang = data.lang, sc = require("Module:scripts").getByCode("Latn"), tr = "-" } end data.translits[i] = translit end if data.id and type(data.id) ~= "string" then error("The id in the data table should be a string.") end end -- Format a headword with transliterations local function format_headword(data) local m_scriptutils = require("Module:script utilities") -- Are there non-empty transliterations? -- Need to do it this way because translit[1] might be nil while translit[2] is not local has_translits = false local has_manual_translits = false -- Format the headwords for i, head in ipairs(data.heads) do if data.translits[i] or data.transcriptions[i] then has_translits = true end if data.translits[i] and data.translits[i].is_manual or data.transcriptions[i] then has_manual_translits = true end -- Apply processing to the headword, for formatting links and such if head:find("[[", nil, true) and (not data.sc or data.sc:getCode() ~= "Imag") then head = require("Module:links").language_link({term = head, lang = data.lang}, false) end -- Add language and script wrapper if i == 1 then head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil, data.id) else head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil) end data.heads[i] = head end local translits_formatted = "" if has_manual_translits then -- [[Special:WhatLinksHere/Template:tracking/headword/has-manual-translit/LANG]] require("Module:debug/track")("headword/has-manual-translit/" .. data.lang:getCode()) end if has_translits then -- Format the transliterations local translits = data.translits local transcriptions = data.transcriptions if translits then -- using pairs() instead of ipairs() in case there is a gap for i, _ in pairs(translits) do if type(i) == "number" then translits[i] = m_scriptutils.tag_translit(translits[i].display, data.lang:getCode(), "head", nil, translits[i].is_manual) end end end if transcriptions then for i, _ in pairs(transcriptions) do if type(i) == "number" then transcriptions[i] = m_scriptutils.tag_transcription(transcriptions[i], data.lang:getCode(), "head") end end end for i = 1, math.max(#translits, #transcriptions) do local translits_formatted = {} table.insert(translits_formatted, translits[i] and translits[i] or "") table.insert(translits_formatted, (translits[i] and transcriptions[i]) and " " or "") table.insert(translits_formatted, transcriptions[i] and "/" .. transcriptions[i] .. "/" or "") data.translits[i] = table.concat(translits_formatted) end translits_formatted = " (" .. table.concat(data.translits, " <i>or</i> ") .. ")" local transliteration_page = mw.title.new(data.lang:getCanonicalName() .. " transliteration", "Wiktionary") if transliteration_page then local success, exists = pcall(function () return transliteration_page.exists end) if success and exists then translits_formatted = " [[Wiktionary:" .. data.lang:getCanonicalName() .. " transliteration|•]]" .. translits_formatted end end end return table.concat(data.heads, " <i>or</i> ") .. translits_formatted end local function format_genders(data) if data.genders and #data.genders > 0 then local pos_for_cat if not data.nogendercat and not m_data.no_gender_cat[data.lang:getCode()] then local pos_category = data.pos_category:gsub("^reconstructed ", "") pos_for_cat = m_data.pos_for_gender_number_cat[pos_category] end local text, cats = require("Module:gender and number").format_genders(data.genders, data.lang, pos_for_cat) for _, cat in ipairs(cats) do table.insert(data.categories, cat) end return "&nbsp;" .. text else return "" end end local function format_inflection_parts(data, parts) for key, part in ipairs(parts) do if type(part) ~= "table" then part = {term = part} end local qualifiers local reftext if part.qualifiers and #part.qualifiers > 0 then qualifiers = require("Module:qualifier").format_qualifier(part.qualifiers) .. " " -- [[Special:WhatLinksHere/Template:tracking/headword/qualifier]] require("Module:debug/track")("headword/qualifier") end if part.refs and #part.refs > 0 then local refs = {} for _, ref in ipairs(part.refs) do if type(ref) ~= "table" then ref = {text = ref} end local refargs if ref.name or ref.group then refargs = {name = ref.name, group = ref.group} end table.insert(refs, mw.getCurrentFrame():extensionTag("ref", ref.text, refargs)) end reftext = table.concat(refs) end local partaccel = part.accel local face = part.hypothetical and "hypothetical" or "bold" local nolink = part.hypothetical or part.nolink if part.label then -- There should be a better way of italicizing a label. As is, this isn't customizable. part = "<i>" .. part.label .. "</i>" else -- Convert the term into a full link -- Don't show a transliteration here, the consensus seems to be not to -- show them in headword lines to avoid clutter. part = require("Module:links").full_link( { term = not nolink and part.term or nil, alt = part.alt or (nolink and part.term or nil), lang = part.lang or data.lang, sc = part.sc or parts.sc or (not part.lang and data.sc), id = part.id, genders = part.genders, tr = part.translit or (not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil), ts = part.transcription, accel = parts.accel or partaccel, }, face, false ) end if qualifiers then part = qualifiers .. part end if reftext then part = part .. reftext end parts[key] = part end local parts_output = "" if #parts > 0 then parts_output = " " .. table.concat(parts, " <i>or</i> ") elseif parts.request then parts_output = " <small>[please provide]</small>" .. require("Module:utilities/format_categories")( {"Requests for inflections in " .. data.lang:getCanonicalName() .. " entries"}, lang, nil, nil, data.force_cat_output or test_force_categories, data.sc ) end return "<i>" .. parts.label .. "</i>" .. parts_output end -- Format the inflections following the headword local function format_inflections(data) if data.inflections and #data.inflections > 0 then -- Format each inflection individually for key, infl in ipairs(data.inflections) do data.inflections[key] = format_inflection_parts(data, infl) end return " (" .. table.concat(data.inflections, ", ") .. ")" else return "" end end -- Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil -- if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.). -- If you have a POS in its singular form, call pluralize() in [[Module:string utilities]] to -- pluralize it in a smart fashion that knows when to add '-s' and when to add '-es'. -- -- If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess -- based on whether it ends in " forms"; otherwise, return nil. function export.pos_lemma_or_nonlemma(plpos, best_guess) -- Is it a lemma category? if isLemma[plpos] or isLemma[plpos:gsub("^reconstructed ", "")] then return "بن‌واژه" -- Is it a nonlemma category? elseif isNonLemma[plpos] or isNonLemma[plpos:gsub("^reconstructed ", "")] or isLemma[plpos:gsub("^mutated ", "")] or isNonLemma[plpos:gsub("^mutated ", "")] then return "شکل غیر بن‌واژه" elseif best_guess then return plpos:find(" forms$") and "شکل غیر بن‌واژه" or "بن‌واژه" else return nil end end local function show_headword_line(data) local namespace = title.nsText -- Check the namespace against the language type if namespace == "" then if data.lang:getType() == "reconstructed" then error("Entries for this language must be placed in the Reconstruction: namespace.") elseif data.lang:getType() == "appendix-constructed" then error("Entries for this language must be placed in the Appendix: namespace.") end end local tracking_categories = {} if not data.noposcat then local pos_category = data.pos_category .. " " .. data.lang:getCanonicalName() if pos_category ~= "Translingual Han characters" then table.insert(data.categories, 1, pos_category) end end if data.sccat and data.sc then table.insert(data.categories, data.pos_category .. " " .. data.lang:getCanonicalName() .. " در " .. data.sc:getDisplayForm()) end -- Is it a lemma category? local postype = export.pos_lemma_or_nonlemma(data.pos_category) if not postype then -- We don't know what this category is, so tag it with a tracking category. --[=[ [[Special:WhatLinksHere/Template:tracking/headword/unrecognized pos]] ]=] table.insert(tracking_categories, "head tracking/unrecognized pos") require("Module:debug/track"){ "headword/unrecognized pos", "headword/unrecognized pos/lang/" .. data.lang:getCode(), "headword/unrecognized pos/pos/" .. data.pos_category } elseif not data.noposcat then table.insert(data.categories, 1, postype .. "‌های " .. data.lang:getCanonicalName()) end -- Preprocess preprocess(data, postype) if namespace == "" and data.lang:getType() ~= "reconstructed" then local m_links = require("Module:links") for _, head in ipairs(data.heads) do if title.prefixedText ~= m_links.getLinkPage(m_links.remove_links(head), data.lang) then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/pagename spelling mismatch]] ]=] require("Module:debug/track"){ "headword/pagename spelling mismatch", "headword/pagename spelling mismatch/" .. data.lang:getCode() } break end end end -- Format and return all the gathered information return format_headword(data) .. format_genders(data) .. format_inflections(data) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end function export.full_headword(data) local tracking_categories = {} -- Script-tags the topmost header. local pagename = title.text local fullPagename = title.fullText local namespace = title.nsText if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then error("In data, the first argument to full_headword, data.lang should be a language object.") end if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads and data.heads[1] ~= "" and data.heads[1] or pagename, data.lang) else -- Track uses of sc parameter local best = require("Module:scripts").findBestScript(pagename, data.lang) require("Module:debug/track")("headword/sc") if data.sc:getCode() == best:getCode() then require("Module:debug/track")("headword/sc/redundant") require("Module:debug/track")("headword/sc/redundant/" .. data.sc:getCode()) else require("Module:debug/track")("headword/sc/needed") require("Module:debug/track")("headword/sc/needed/" .. data.sc:getCode()) end end local displayTitle -- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace. -- Avoid tagging ASCII as Hani even when it is tagged as Hani in the -- headword, as in [[check]]. The check for ASCII might need to be expanded -- to a check for any Latin characters and whitespace or punctuation. if (namespace == "" and data.sc and toBeTagged[data.sc:getCode()] and not pagename:find "^[%z\1-\127]+$") or (data.sc:getCode() == "Jpan" and (test_script(pagename, "Hira") or test_script(pagename, "Kana"))) then displayTitle = '<span class="' .. data.sc:getCode() .. '">' .. pagename .. '</span>' elseif namespace == "Reconstruction" then displayTitle, matched = mw.ustring.gsub( fullPagename, "^(Reconstruction:[^/]+/)(.+)$", function(before, term) return before .. require("Module:script utilities").tag_text( term, data.lang, data.sc ) end ) if matched == 0 then displayTitle = nil end end if displayTitle then local frame = mw.getCurrentFrame() frame:callParserFunction( "DISPLAYTITLE", displayTitle ) end if data.force_cat_output then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/force cat output]] ]=] require("Module:debug/track")("headword/force cat output") end if data.getCanonicalName then error('The "data" variable supplied to "full_headword" should not be a language object.') end -- Were any categories specified? if data.categories and #data.categories > 0 then local lang_name = require("Module:string/pattern_escape")(data.lang:getCanonicalName()) for _, cat in ipairs(data.categories) do -- Does the category begin with the language name? If not, tag it with a tracking category. if not mw.ustring.find(cat, "^" .. lang_name) then mw.log(cat, data.lang:getCanonicalName()) table.insert(tracking_categories, "head tracking/no lang category") --[=[ [[Special:WhatLinksHere/Template:tracking/head tracking/no lang category]] ]=] require("Module:debug/track"){ "headword/no lang category", "headword/no lang category/lang/" .. data.lang:getCode() } end end if not data.pos_category and mw.ustring.find(data.categories[1], "^" .. data.lang:getCanonicalName()) then data.pos_category = mw.ustring.gsub(data.categories[1], "^" .. data.lang:getCanonicalName() .. " ", "") table.remove(data.categories, 1) end end if not data.pos_category then error( 'No valid part-of-speech categories were found in the list ' .. 'of categories passed to the function "full_headword". ' .. 'The part-of-speech category should consist of a language\'s ' .. 'canonical name plus a part of speech.' ) end -- Categorise for unusual characters local standard = data.lang:getStandardCharacters() if standard then if mw.ustring.len(title.subpageText) ~= 1 and not non_categorizable() then for character in mw.ustring.gmatch(title.subpageText, "([^" .. standard .. "])") do local upper = mw.ustring.upper(character) if not mw.ustring.find(upper, "[" .. standard .. "]") then character = upper end table.insert( data.categories, data.lang:getCanonicalName() .. " terms spelled with " .. character ) end end end -- Categorise for palindromes if title.nsText ~= "Reconstruction" and mw.ustring.len(title.subpageText)>2 and require('Module:palindromes').is_palindrome( title.subpageText, data.lang, data.sc ) then table.insert(data.categories, data.lang:getCanonicalName() .. " palindromes") end -- This may add more categories (e.g. gender categories), so make sure it gets -- evaluated first. local text = show_headword_line(data) return text .. require("Module:utilities/format_categories")( data.categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end return export 9pkgl7b0thx8lro0ed7vrcjueaur9ik 847590 847579 2022-07-23T15:20:37Z Beginneruser 11037 Scribunto text/plain local export = {} local m_data = mw.loadData("Module:headword/data") local title = mw.title.getCurrentTitle() local isLemma = m_data.lemmas local isNonLemma = m_data.nonlemmas local notranslit = m_data.notranslit local toBeTagged = m_data.toBeTagged -- If set to true, categories always appear, even in non-mainspace pages local test_force_categories = false local function test_script(text, script_code) if type(text) == "string" and type(script_code) == "string" then local sc = require("Module:scripts").getByCode(script_code) local characters if sc then characters = sc:getCharacters() end local out if characters then text = mw.ustring.gsub(text, "%W", "") out = mw.ustring.find(text, "[" .. characters .. "]") end if out then return true else return false end else mw.log("Parameters to test_script were incorrect.") return nil end end local spacingPunctuation = "[%s%p]+" --[[ List of punctuation or spacing characters that are found inside of words. Used to exclude characters from the regex above. ]] local wordPunc = "-־׳״'.·*’་•" local notWordPunc = "[^" .. wordPunc .. "]+" -- Return true if the given head is multiword according to the algorithm used -- in full_headword(). function export.head_is_multiword(head) for possibleWordBreak in mw.ustring.gmatch(head, spacingPunctuation) do if mw.ustring.find(possibleWordBreak, notWordPunc) then return true end end return false end -- Add links to a multiword head. function export.add_multiword_links(head) local function workaround_to_exclude_chars(s) return mw.ustring.gsub(s, notWordPunc, "]]%1[[") end head = "[[" .. mw.ustring.gsub( head, spacingPunctuation, workaround_to_exclude_chars ) .. "]]" --[=[ use this when workaround is no longer needed: head = "[[" .. mw.ustring.gsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]" Remove any empty links, which could have been created above at the beginning or end of the string. ]=] head = mw.ustring.gsub(head, "%[%[%]%]", "") return head end local function non_categorizable() return (title:inNamespace("") and title.text:find("^Unsupported titles/")) or (title:inNamespace("پیوست") and title.text:find("^Gestures/")) end local function preprocess(data, postype) --[=[ [[Special:WhatLinksHere/Template:tracking/headword/heads-not-table]] [[Special:WhatLinksHere/Template:tracking/headword/translits-not-table]] ]=] if type(data.heads) ~= "table" then if data.heads then require("Module:debug/track")("headword/heads-not-table") end data.heads = { data.heads } end if type(data.translits) ~= "table" then if data.translits then require("Module:debug/track")("headword/translits-not-table") end data.translits = { data.translits } end if type(data.transcriptions) ~= "table" then if data.transcriptions then require("Module:debug/track")("headword/transcriptions-not-table") end data.transcriptions = { data.transcriptions } end if not data.heads or #data.heads == 0 then data.heads = {""} end -- Determine if term is reconstructed local is_reconstructed = data.lang:getType() == "reconstructed" or title.nsText == "Reconstruction" -- Create a default headword. local subpagename = title.subpageText local pagename = title.text local default_head if is_reconstructed then default_head = require("Module:utilities").plain_gsub(pagename, data.lang:getCanonicalName() .. "/", "") else default_head = subpagename end local unmodified_default_head = default_head -- Add links to multi-word page names when appropriate if data.lang:getCode() ~= "zh" and (not is_reconstructed) and export.head_is_multiword(default_head) then default_head = export.add_multiword_links(default_head) end if is_reconstructed then default_head = "*" .. default_head end -- If a head is the empty string "", then replace it with the default for i, head in ipairs(data.heads) do if head == "" then head = default_head else if head == default_head and data.lang:getCanonicalName() == "English" then table.insert(data.categories, data.lang:getCanonicalName() .. " terms with redundant head parameter") end end data.heads[i] = head end -- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms" if not data.nomultiwordcat and postype == "بن‌واژه" and not m_data.no_multiword_cat[data.lang:getCode()] then -- Check for spaces or hyphens, but exclude prefixes and suffixes. -- Use the pagename, not the head= value, because the latter may have extra -- junk in it, e.g. superscripted text that throws off the algorithm. local checkpattern = ".[%s%-፡]." if m_data.hyphen_not_multiword_sep[data.lang:getCode()] then -- Exclude hyphens if the data module states that they should for this language checkpattern = ".[%s፡]." end if mw.ustring.find(unmodified_default_head, checkpattern) and not non_categorizable() then table.insert(data.categories, "اصطلاح‌های چند واژه‌ای " .. data.lang:getCanonicalName()) end end --[[ Try to detect the script if it was not provided We use the first headword for this, and assume that all of them have the same script This *should* always be true, right? ]] if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads[1], data.lang) end for i, val in pairs(data.translits) do data.translits[i] = {display = val, is_manual = true} end -- Make transliterations for i, head in ipairs(data.heads) do local translit = data.translits[i] -- Try to generate a transliteration if necessary -- Generate it if the script is not Latn or similar, and if no transliteration was provided if translit and translit.display == "-" then translit = nil elseif not translit and not (data.sc:getCode():find("Latn", nil, true) or data.sc:getCode() == "Latinx" or data.sc:getCode() == "None") and (not data.sc or data.sc:getCode() ~= "Imag") then translit = data.lang:transliterate(require("Module:links").remove_links(head), data.sc) -- There is still no transliteration? -- Add the entry to a cleanup category. if not translit and not notranslit[data.lang:getCode()] then translit = "<small>transliteration needed</small>" table.insert(data.categories, "Requests for transliteration of " .. data.lang:getCanonicalName() .. " terms") end if translit then translit = {display = translit, is_manual = false} end end -- Link to the transliteration entry for languages that require this if translit and data.lang:link_tr() then translit.display = require("Module:links").full_link{ term = translit.display, lang = data.lang, sc = require("Module:scripts").getByCode("Latn"), tr = "-" } end data.translits[i] = translit end if data.id and type(data.id) ~= "string" then error("The id in the data table should be a string.") end end -- Format a headword with transliterations local function format_headword(data) local m_scriptutils = require("Module:script utilities") -- Are there non-empty transliterations? -- Need to do it this way because translit[1] might be nil while translit[2] is not local has_translits = false local has_manual_translits = false -- Format the headwords for i, head in ipairs(data.heads) do if data.translits[i] or data.transcriptions[i] then has_translits = true end if data.translits[i] and data.translits[i].is_manual or data.transcriptions[i] then has_manual_translits = true end -- Apply processing to the headword, for formatting links and such if head:find("[[", nil, true) and (not data.sc or data.sc:getCode() ~= "Imag") then head = require("Module:links").language_link({term = head, lang = data.lang}, false) end -- Add language and script wrapper if i == 1 then head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil, data.id) else head = m_scriptutils.tag_text(head, data.lang, data.sc, "head", nil) end data.heads[i] = head end local translits_formatted = "" if has_manual_translits then -- [[Special:WhatLinksHere/Template:tracking/headword/has-manual-translit/LANG]] require("Module:debug/track")("headword/has-manual-translit/" .. data.lang:getCode()) end if has_translits then -- Format the transliterations local translits = data.translits local transcriptions = data.transcriptions if translits then -- using pairs() instead of ipairs() in case there is a gap for i, _ in pairs(translits) do if type(i) == "number" then translits[i] = m_scriptutils.tag_translit(translits[i].display, data.lang:getCode(), "head", nil, translits[i].is_manual) end end end if transcriptions then for i, _ in pairs(transcriptions) do if type(i) == "number" then transcriptions[i] = m_scriptutils.tag_transcription(transcriptions[i], data.lang:getCode(), "head") end end end for i = 1, math.max(#translits, #transcriptions) do local translits_formatted = {} table.insert(translits_formatted, translits[i] and translits[i] or "") table.insert(translits_formatted, (translits[i] and transcriptions[i]) and " " or "") table.insert(translits_formatted, transcriptions[i] and "/" .. transcriptions[i] .. "/" or "") data.translits[i] = table.concat(translits_formatted) end translits_formatted = " (" .. table.concat(data.translits, " <i>or</i> ") .. ")" local transliteration_page = mw.title.new(data.lang:getCanonicalName() .. " transliteration", "Wiktionary") if transliteration_page then local success, exists = pcall(function () return transliteration_page.exists end) if success and exists then translits_formatted = " [[Wiktionary:" .. data.lang:getCanonicalName() .. " transliteration|•]]" .. translits_formatted end end end return table.concat(data.heads, " <i>or</i> ") .. translits_formatted end local function format_genders(data) if data.genders and #data.genders > 0 then local pos_for_cat if not data.nogendercat and not m_data.no_gender_cat[data.lang:getCode()] then local pos_category = data.pos_category:gsub("^reconstructed ", "") pos_for_cat = m_data.pos_for_gender_number_cat[pos_category] end local text, cats = require("Module:gender and number").format_genders(data.genders, data.lang, pos_for_cat) for _, cat in ipairs(cats) do table.insert(data.categories, cat) end return "&nbsp;" .. text else return "" end end local function format_inflection_parts(data, parts) for key, part in ipairs(parts) do if type(part) ~= "table" then part = {term = part} end local qualifiers local reftext if part.qualifiers and #part.qualifiers > 0 then qualifiers = require("Module:qualifier").format_qualifier(part.qualifiers) .. " " -- [[Special:WhatLinksHere/Template:tracking/headword/qualifier]] require("Module:debug/track")("headword/qualifier") end if part.refs and #part.refs > 0 then local refs = {} for _, ref in ipairs(part.refs) do if type(ref) ~= "table" then ref = {text = ref} end local refargs if ref.name or ref.group then refargs = {name = ref.name, group = ref.group} end table.insert(refs, mw.getCurrentFrame():extensionTag("ref", ref.text, refargs)) end reftext = table.concat(refs) end local partaccel = part.accel local face = part.hypothetical and "hypothetical" or "bold" local nolink = part.hypothetical or part.nolink if part.label then -- There should be a better way of italicizing a label. As is, this isn't customizable. part = "<i>" .. part.label .. "</i>" else -- Convert the term into a full link -- Don't show a transliteration here, the consensus seems to be not to -- show them in headword lines to avoid clutter. part = require("Module:links").full_link( { term = not nolink and part.term or nil, alt = part.alt or (nolink and part.term or nil), lang = part.lang or data.lang, sc = part.sc or parts.sc or (not part.lang and data.sc), id = part.id, genders = part.genders, tr = part.translit or (not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil), ts = part.transcription, accel = parts.accel or partaccel, }, face, false ) end if qualifiers then part = qualifiers .. part end if reftext then part = part .. reftext end parts[key] = part end local parts_output = "" if #parts > 0 then parts_output = " " .. table.concat(parts, " <i>or</i> ") elseif parts.request then parts_output = " <small>[please provide]</small>" .. require("Module:utilities/format_categories")( {"Requests for inflections in " .. data.lang:getCanonicalName() .. " entries"}, lang, nil, nil, data.force_cat_output or test_force_categories, data.sc ) end return "<i>" .. parts.label .. "</i>" .. parts_output end -- Format the inflections following the headword local function format_inflections(data) if data.inflections and #data.inflections > 0 then -- Format each inflection individually for key, infl in ipairs(data.inflections) do data.inflections[key] = format_inflection_parts(data, infl) end return " (" .. table.concat(data.inflections, ", ") .. ")" else return "" end end -- Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil -- if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.). -- If you have a POS in its singular form, call pluralize() in [[Module:string utilities]] to -- pluralize it in a smart fashion that knows when to add '-s' and when to add '-es'. -- -- If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess -- based on whether it ends in " forms"; otherwise, return nil. function export.pos_lemma_or_nonlemma(plpos, best_guess) -- Is it a lemma category? if isLemma[plpos] or isLemma[plpos:gsub("^reconstructed ", "")] then return "بن‌واژه" -- Is it a nonlemma category? elseif isNonLemma[plpos] or isNonLemma[plpos:gsub("^reconstructed ", "")] or isLemma[plpos:gsub("^mutated ", "")] or isNonLemma[plpos:gsub("^mutated ", "")] then return "شکل غیر بن‌واژه" elseif best_guess then return plpos:find(" forms$") and "شکل غیر بن‌واژه" or "بن‌واژه" else return nil end end local function show_headword_line(data) local namespace = title.nsText -- Check the namespace against the language type if namespace == "" then if data.lang:getType() == "reconstructed" then error("Entries for this language must be placed in the Reconstruction: namespace.") elseif data.lang:getType() == "appendix-constructed" then error("Entries for this language must be placed in the Appendix: namespace.") end end local tracking_categories = {} if not data.noposcat then local pos_category = data.pos_category .. " " .. data.lang:getCanonicalName() if pos_category ~= "Translingual Han characters" then table.insert(data.categories, 1, pos_category) end end if data.sccat and data.sc then table.insert(data.categories, data.pos_category .. " " .. data.lang:getCanonicalName() .. " در " .. data.sc:getDisplayForm()) end -- Is it a lemma category? local postype = export.pos_lemma_or_nonlemma(data.pos_category) if not postype then -- We don't know what this category is, so tag it with a tracking category. --[=[ [[Special:WhatLinksHere/Template:tracking/headword/unrecognized pos]] ]=] table.insert(tracking_categories, "head tracking/unrecognized pos") require("Module:debug/track"){ "headword/unrecognized pos", "headword/unrecognized pos/lang/" .. data.lang:getCode(), "headword/unrecognized pos/pos/" .. data.pos_category } elseif not data.noposcat then table.insert(data.categories, 1, postype .. "‌های " .. data.lang:getCanonicalName()) end -- Preprocess preprocess(data, postype) if namespace == "" and data.lang:getType() ~= "reconstructed" then local m_links = require("Module:links") for _, head in ipairs(data.heads) do if title.prefixedText ~= m_links.getLinkPage(m_links.remove_links(head), data.lang) then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/pagename spelling mismatch]] ]=] require("Module:debug/track"){ "headword/pagename spelling mismatch", "headword/pagename spelling mismatch/" .. data.lang:getCode() } break end end end -- Format and return all the gathered information return format_headword(data) .. format_genders(data) .. format_inflections(data) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end function export.full_headword(data) local tracking_categories = {} -- Script-tags the topmost header. local pagename = title.text local fullPagename = title.fullText local namespace = title.nsText if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then error("In data, the first argument to full_headword, data.lang should be a language object.") end if not data.sc then data.sc = require("Module:scripts").findBestScript(data.heads and data.heads[1] ~= "" and data.heads[1] or pagename, data.lang) else -- Track uses of sc parameter local best = require("Module:scripts").findBestScript(pagename, data.lang) require("Module:debug/track")("headword/sc") if data.sc:getCode() == best:getCode() then require("Module:debug/track")("headword/sc/redundant") require("Module:debug/track")("headword/sc/redundant/" .. data.sc:getCode()) else require("Module:debug/track")("headword/sc/needed") require("Module:debug/track")("headword/sc/needed/" .. data.sc:getCode()) end end local displayTitle -- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace. -- Avoid tagging ASCII as Hani even when it is tagged as Hani in the -- headword, as in [[check]]. The check for ASCII might need to be expanded -- to a check for any Latin characters and whitespace or punctuation. if (namespace == "" and data.sc and toBeTagged[data.sc:getCode()] and not pagename:find "^[%z\1-\127]+$") or (data.sc:getCode() == "Jpan" and (test_script(pagename, "Hira") or test_script(pagename, "Kana"))) then displayTitle = '<span class="' .. data.sc:getCode() .. '">' .. pagename .. '</span>' elseif namespace == "Reconstruction" then displayTitle, matched = mw.ustring.gsub( fullPagename, "^(Reconstruction:[^/]+/)(.+)$", function(before, term) return before .. require("Module:script utilities").tag_text( term, data.lang, data.sc ) end ) if matched == 0 then displayTitle = nil end end if displayTitle then local frame = mw.getCurrentFrame() frame:callParserFunction( "DISPLAYTITLE", displayTitle ) end if data.force_cat_output then --[=[ [[Special:WhatLinksHere/Template:tracking/headword/force cat output]] ]=] require("Module:debug/track")("headword/force cat output") end if data.getCanonicalName then error('The "data" variable supplied to "full_headword" should not be a language object.') end -- Were any categories specified? if data.categories and #data.categories > 0 then local lang_name = require("Module:string/pattern_escape")(data.lang:getCanonicalName()) for _, cat in ipairs(data.categories) do -- Does the category begin with the language name? If not, tag it with a tracking category. if not mw.ustring.find(cat, "^" .. lang_name) then mw.log(cat, data.lang:getCanonicalName()) table.insert(tracking_categories, "head tracking/no lang category") --[=[ [[Special:WhatLinksHere/Template:tracking/head tracking/no lang category]] ]=] require("Module:debug/track"){ "headword/no lang category", "headword/no lang category/lang/" .. data.lang:getCode() } end end if not data.pos_category and mw.ustring.find(data.categories[1], "^" .. data.lang:getCanonicalName()) then data.pos_category = mw.ustring.gsub(data.categories[1], "^" .. data.lang:getCanonicalName() .. " ", "") table.remove(data.categories, 1) end end if not data.pos_category then error( 'No valid part-of-speech categories were found in the list ' .. 'of categories passed to the function "full_headword". ' .. 'The part-of-speech category should consist of a language\'s ' .. 'canonical name plus a part of speech.' ) end -- Categorise for unusual characters local standard = data.lang:getStandardCharacters() if standard then if mw.ustring.len(title.subpageText) ~= 1 and not non_categorizable() then for character in mw.ustring.gmatch(title.subpageText, "([^" .. standard .. "])") do local upper = mw.ustring.upper(character) if not mw.ustring.find(upper, "[" .. standard .. "]") then character = upper end table.insert( data.categories, data.lang:getCanonicalName() .. " terms spelled with " .. character ) end end end -- Categorise for palindromes if title.nsText ~= "Reconstruction" and mw.ustring.len(title.subpageText)>2 and require('Module:palindromes').is_palindrome( title.subpageText, data.lang, data.sc ) then table.insert(data.categories, data.lang:getCanonicalName() .. " palindromes") end -- This may add more categories (e.g. gender categories), so make sure it gets -- evaluated first. local text = show_headword_line(data) return text .. require("Module:utilities/format_categories")( data.categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) .. require("Module:utilities/format_categories")( tracking_categories, data.lang, data.sort_key, nil, data.force_cat_output or test_force_categories, data.sc ) end return export 5kmuwboish5j5tg94jx8encz32hools پودمان:headword/data 828 159182 847568 844708 2022-07-23T14:02:31Z Beginneruser 11037 Localization Scribunto text/plain local data = {} data.invariable = { "cmavo", "cmene", "fu'ivla", "gismu", "Han tu", "hanzi", "hanja", "jyutping", "kanji", "lujvo", "phrasebook", "pinyin", "rafsi", "romaji", } data.lemmas = { "abbreviations", "acronyms", "adjectives", "adnominals", "adpositions", "adverbs", "affixes", "ambipositions", "articles", "circumfixes", "circumpositions", "classifiers", "cmavo", "cmavo clusters", "cmene", "combining forms", "conjunctions", "counters", "determiners", "diacritical marks", "equative adjectives", "fu'ivla", "gismu", "Han characters", "Han tu", "hanzi", "hanja", "ideophones", "idioms", "infixes", "interfixes", "initialisms", "interjections", "kanji", "letters", "ligatures", "lujvo", "morphemes", "non-constituents", "اسم‌های", "numbers", "numeral symbols", "numerals", "particles", "phrases", "postpositions", "postpositional phrases", "predicatives", "prefixes", "prepositions", "prepositional phrases", "preverbs", "pronominal adverbs", "pronouns", "proverbs", "proper nouns", "punctuation marks", "relatives", "roots", "stems", "suffixes", "syllables", "symbols", "فعل‌های", } data.nonlemmas = { "active participles", "adjectival participles", "adjective forms", "adjective feminine forms", "adjective plural forms", "adverb forms", "adverbial participles", "agent participles", "article forms", "circumfix forms", "combined forms", "comparative adjective forms", "comparative adjectives", "comparative adverb forms", "comparative adverbs", "contractions", "converbs", "determiner comparative forms", "determiner forms", "determiner superlative forms", "diminutive nouns", "equative adjective forms", "equative adjectives", "future participles", "gerunds", "infinitive forms", "infinitives", "interjection forms", "jyutping", "kanji readings", "misspellings", "negative participles", "nominal participles", "noun case forms", "noun dual forms", "noun forms", "noun paucal forms", "noun plural forms", "noun possessive forms", "noun singulative forms", "numeral forms", "participles", "participle forms", "particle forms", "passive participles", "past active participles", "past participles", "past participle forms", "past passive participles", "perfect active participles", "perfect participles", "perfect passive participles", "pinyin", "plurals", "postposition forms", "prefix forms", "preposition contractions", "preposition forms", "prepositional pronouns", "present active participles", "present participles", "present passive participles", "pronoun forms", "pronoun possessive forms", "proper noun forms", "proper noun plural forms", "rafsi", "romanizations", "root forms", "singulatives", "suffix forms", "superlative adjective forms", "superlative adjectives", "superlative adverb forms", "superlative adverbs", "verb forms", "verbal nouns", } -- These languages will not have "LANG multiword terms" categories added. data.no_multiword_cat = { -------- Languages without spaces between words (sometimes spaces between phrases) -------- "aho", -- Ahom "blt", -- Tai Dam "ja", -- Japanese "khb", -- Lü "km", -- Khmer "lo", -- Lao "mnw", -- Mon "my", -- Burmese "nan", -- Min Nan (some words in Latin script; hyphens between syllables) "nod", -- Northern Thai "ojp", -- Old Japanese "tdd", -- Tai Nüa "th", -- Thai "tts", -- Isan "twh", -- Tai Dón "shn", -- Shan "sou", -- Southern Thai "zh", -- Chinese (all varieties with Chinese characters) -------- Languages with spaces between syllables -------- "ahk", -- Akha "aou", -- A'ou "atb", -- Zaiwa "byk", -- Biao --"duu", -- Drung; not sure --"hmx-pro", -- Proto-Hmong-Mien --"hnj", -- Green Hmong; not sure "huq", -- Tsat "ium", -- Iu Mien --"lis", -- Lisu; not sure "mtq", -- Muong --"mww", -- White Hmong; not sure "onb", -- Lingao --"sit-gkh", -- Gokhy; not sure --"swi", -- Sui; not sure "tbq-lol-pro", -- Proto-Loloish "tdh", -- Thulung "ukk", -- Muak Sa-aak "vi", -- Vietnamese "yig", -- Wusa Nasu "zng", -- Mang -------- Languages with ~ with surrounding spaces used to separate variants -------- "mkh-ban-pro", -- Proto-Bahnaric "sit-pro", -- Proto-Sino-Tibetan; listed above -------- Other weirdnesses -------- "mul", -- Translingual; gestures, Morse code, etc. "aot", -- Atong (India); bullet is a letter -------- All sign languages -------- "ads", "aed", "aen", "afg", "ase", "asf", "asp", "asq", "asw", "bfi", "bfk", "bog", "bqn", "bqy", "bvl", "bzs", "cds", "csc", "csd", "cse", "csf", "csg", "csl", "csn", "csq", "csr", "doq", "dse", "dsl", "ecs", "esl", "esn", "eso", "eth", "fcs", "fse", "fsl", "fss", "gds", "gse", "gsg", "gsm", "gss", "gus", "hab", "haf", "hds", "hks", "hos", "hps", "hsh", "hsl", "icl", "iks", "ils", "inl", "ins", "ise", "isg", "isr", "jcs", "jhs", "jls", "jos", "jsl", "jus", "kgi", "kvk", "lbs", "lls", "lsl", "lso", "lsp", "lst", "lsy", "lws", "mdl", "mfs", "mre", "msd", "msr", "mzc", "mzg", "mzy", "nbs", "ncs", "nsi", "nsl", "nsp", "nsr", "nzs", "okl", "pgz", "pks", "prl", "prz", "psc", "psd", "psg", "psl", "pso", "psp", "psr", "pys", "rms", "rsl", "rsm", "sdl", "sfb", "sfs", "sgg", "sgx", "slf", "sls", "sqk", "sqs", "ssp", "ssr", "svk", "swl", "syy", "tse", "tsm", "tsq", "tss", "tsy", "tza", "ugn", "ugy", "ukl", "uks", "vgt", "vsi", "vsl", "vsv", "xki", "xml", "xms", "ygs", "ysl", "zib", "zsl", } -- In these languages, the hyphen is not considered a word separator for the "multiword terms" category. data.hyphen_not_multiword_sep = { "akk", -- Akkadian; hyphens between syllables "akl", -- Aklanon; hyphens for mid-word glottal stops "ber-pro", -- Proto-Berber; morphemes separated by hyphens "ceb", -- Cebuano; hyphens for mid-word glottal stops "cnk", -- Khumi Chin; hyphens used in single words "cpi", -- Chinese Pidgin English; Chinese-derived words with hyphens between syllables "de", -- too many false positives "esx-esk-pro", -- hyphen used to separate morphemes "fi", -- Finnish; hyphen used to separate components in compound words if the final and initial vowels match, respectively "hil", -- Hiligaynon; hyphens for mid-word glottal stops "ilo", -- Ilocano; hyphens for mid-word glottal stops "lcp", -- Western Lawa; dash as syllable joiner "lwl", -- Eastern Lawa; dash as syllable joiner "mkh-vie-pro", -- Proto-Vietic; morphemes separated by hyphens "msb", -- Masbatenyo; too many false positives "tl", -- Tagalog; too many false positives "war", -- Waray-Waray; too many false positives "yo", -- Yoruba; hyphens used to show lengthened nasal vowels } -- These languages will not have "LANG masculine nouns" and similar categories added. data.no_gender_cat = { -- Languages without gender but which use the gender field for other purposes "ja", "th", } data.notranslit = { "ams", "az", "bbc", "bug", "cia", "cjm", "cmn", "hak", "ja", "kzg", "lad", "lzh", "ms", "mul", "mvi", "nan", "oj", "okn", "pi", "ro", "ryn", "rys", "ryu", "sh", "tgt", "th", "tkn", "tly", "txg", "und", "vi", "xug", "yue", "yoi", "yox", "za", "zh", } -- Script codes for which a script-tagged display title will be added. data.toBeTagged = { "Ahom", "Arab", "Avst", "Bali", "Cham", "Copt", "Deva", "Kali", "Hani", "Hebr", "Lana", "Linb", "Mand", "Mong", "polytonic", "Rjng", "Samr", "Sund", "Sylo", "Syrc", "Tang", "Tavt", "Ugar", "Xsux", } for key, list in pairs(data) do data[key] = {} for _, item in ipairs(list) do data[key][item] = true end end -- Parts of speech for which categories like "German masculine nouns" or "Russian imperfective verbs" -- will be generated if the headword is of the appropriate gender/number. We put this at the bottom -- because it's a map, not a list. data.pos_for_gender_number_cat = { ["nouns"] = "اسم‌های", ["proper nouns"] = "اسم‌های", ["suffixes"] = "پسوند‌های", -- We include verbs because impf and pf are valid "genders". ["verbs"] = "فعل‌های", } return data pbnbhjhg7xla9b7rhjozdgxgb4lp8ll بحث کاربر:Praxidicae 3 159345 847594 769604 2022-07-23T16:19:53Z 2409:4071:6E97:D9BC:0:0:4388:9403 Slurp wikitext text/x-wiki Drink [[User:Ritchie333|Ritchie's]] piss [[User:Praxidicae|Chrissy]]. [[ویژه:مشارکت‌ها/2409:4071:6E97:D9BC:0:0:4388:9403|2409:4071:6E97:D9BC:0:0:4388:9403]] ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۶:۱۹ (UTC) == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۱۷، ساعت ۱۴:۵۵ (UTC) cg5q2u55z2adqnetxzp8xnpeepydxws 847601 847594 2022-07-23T18:06:47Z 20041027 tatsu 28285 ویرایش [[Special:Contributions/2409:4071:6E97:D9BC:0:0:4388:9403|2409:4071:6E97:D9BC:0:0:4388:9403]] ([[User talk:2409:4071:6E97:D9BC:0:0:4388:9403|بحث]]) به آخرین تغییری که [[User:TonyBallioni|TonyBallioni]] انجام داده بود واگردانده شد wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۱۷، ساعت ۱۴:۵۵ (UTC) qhj0jgncgvc6n16is1k9m20f3c16pbr بحث کاربر:Arianaboutalebi 3 187077 847599 833605 2022-07-23T17:41:41Z EmausBot 19188 ربات: اصلاح تغییرمسیر دوتایی به [[بحث کاربر:Abt1379]] wikitext text/x-wiki #تغییر_مسیر [[بحث کاربر:Abt1379]] 6j2l2y3iljnqzpvnp9gsqxy8ocknskm پایگاه خبری بهگزین 0 187102 847556 847419 2022-07-23T13:14:11Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} پایگاه خبری بهگزین یک پایگاه خبری به زبان فارسی در جمهوری اسلامی ایران است. 9merw5hz95c3wjsz3dnr1jr59xiz23y پایدار (گروه موسیقی) 0 187320 847561 847548 2022-07-23T13:15:24Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} پایدار یک گروه رپ فارسی است که به دست عرفان حاجی رسولی(عرفان)به وجود امد.اعضای گروه پایدار مدگل جیدال عرفان پایدار تهم ایمانمون اعضای پیشین لیتو چاقال . سوگند و .... jj0lkb1xyrr8xj83bh6640x265xn0xq سمفونی‌های سیارات 0 193053 847549 847328 2022-07-23T13:11:45Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} در واقع سمفونی سیاره نظم گردشی سیاره ها در مدار خود در گردش به خورشید هستند که حالات اوج وحضیض و هم راستا شدن biqwd5nvb100trblwjkdwrn8qh7usq3 سجاد عبادی 0 193058 847550 847338 2022-07-23T13:12:00Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} ''بله درست است من گفتم'' juv2ts9hioc74os869hvl2f0giyzgkv سید اسماعیل حیدری 0 193059 847551 847339 2022-07-23T13:12:12Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} سید اسماعیل حیدری gbxnbx9is3ffyof7l96fyccj6t05b3f علی فهامی فر بازیگر کمدین 0 193072 847552 847376 2022-07-23T13:13:32Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} علی فهامی فر بازیگر متولد /۱۳۸۲/۹/۱ در اصفهان حرفه کمدین استعداد او در حرفه بازیگری کارها و نقش های کمدی است که او به راحتی با آن ها سرکار دارد m9h6ulbfmx08iohyipawspo5z339ng0 علی فهامی فر 0 193073 847553 847378 2022-07-23T13:13:39Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} علی فهامی فر بازیگر کمدین حرفه: بازیگر کمدی 489qgstz3sla2mcatqpxwdw271t0bt4 آرزو آفری 0 193077 847554 847383 2022-07-23T13:13:49Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} آرزو آفری متولد ۱۳۵۸ در تهران متولد شد. او فعالیت دوبله را از سال ۱۳۸۲ آغاذ کرد و او در انجمن گویندگان جوان(گلوری) حضور داشته است انیمیشن هایی که او به عنوان مدیر دوبلاژ بوده است. شیرشاه ۲=گلوری انترتینمنت خانه هیولا= هر دو پسر،زی = گلوری انترتینمنت مسابقه بی سابقه(لاکپشت ها علیه خرگوش ها)=گلوری انترتینمنت آن سوی پرچین=راسو=گلوری انترتینمنت و... انیمیشن هایی که او به عنوان گوینده بوده است شیرشاه ۱=همسر سیمبا داستان اسباب بازی۲و۳=جسی=گلوری انترتینمنت تارزان ۱=میمون(دوست تارزان)=گلوری انترتینمنت زندگی جدید امپراتور=ایزما،زن پاچا،هردو بچه پاچا=گلوری عصر یخبندان۱=تنبل بنفش،یکی از بچه های توی نفت=گلوری در جستجوی نمو=دوری،نمو=گلوری انترتینمنت خرس برادر=کودا=گلوری انترتینمنت شگفت انگیزان۱=دش=گلوری انترتینمنت شرک۲=ملکه(مادر فیونا)=گلوری انترتینمنت ربات ها=مادر شخصیت اول=گلوری انترتینمنت عروس مردگان=مادر ویکتوریا=گلوری انترتینمنت جوجه کوچولو=اردک=گلوری انترتینمنت ماشین ها=ماشین آبی(دوست مک کویین)=گلوری انترتینمنت عصر یخبندان۲=الی=گلوری انترتینمنت خانه هیولا=هردو پسر،زی=گلوری انترتینمنت آن سوی پرچین=راسو =گلوری انترتینمنت فصل شکار۱=جیزل=گلوری انترتینمنت رئیس مزرعه=مرغ و جوجه=گلوری انترتینمنت شرک۳=ملکه،سیندرلا=گلوری انترتینمنت موش سرآشپز=آشپز زن=گلوری انترتینمنت بالا=راسل=گلوری انترتینمنت عصریخبندان۳=الی=گلوری انترتینمنت شرک۴=ملکه،پسر چاق=گلوری انترتینمنت من نفرت انگیز۱=اگنس=گلوری گیسو کمند=مادرگاتل =گلوری انترتینمنت ابری با احتمال بارش کوفته قلقلی۱=بچگی فلینت=گلوری عصریخبندان۴=الی=گلوری انترتینمنت ماداگاسکار=گلوریا=گلوری غارنشینان=ایپ=گلوری مینیون ها=اسکارلت=گلوری انترتینمنت سرنشینان(درون بیرون)=شادی،رایلی=گلوری انترتینمنت در جستجوی دوری=نمو،دوری=آواژه عصر یخبندان=الی=تهران دابشو شگفت انگیزان=دش=آواژه غارنشینان۲=ایپ=تهران دابشو روح=مادر جو=استدیو مهبانگ لوکا=لوکا=آواژه قرمز شدن=شخصیت اول=سام استدیو 6hmusuvy8aa6n73zlm7hqfs90xtdnbo جام والیبال مردان آسیا ۲۰۱۶ 0 193082 847555 847397 2022-07-23T13:13:58Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} ايران در اين بازى نفر اول است ايران تا tkvftxzbvm259fioek2kc8g64vwvzy4 ویکی‌واژه:GUS2Wiki 4 193083 847604 847427 2022-07-23T20:50:46Z Alexis Jazz 27983 Updating gadget usage statistics from [[Special:GadgetUsage]] ([[phab:T121049]]) wikitext text/x-wiki {{#ifexist:Project:GUS2Wiki/top|{{/top}}|This page provides a historical record of [[Special:GadgetUsage]] through its page history. To get the data in CSV format, see wikitext. To customize this message or add categories, create [[/top]].}} داده‌های زیر در حافظهٔ نهانی وجود دارند و آخرین بار در 2022-07-23T02:54:15Z روزآمدسازی شده‌اند. حداکثر {{PLURAL:5000|یک نتیجه|5000 نتیجه}} در حافظۀ نهان موجود است. {| class="sortable wikitable" ! ابزار !! data-sort-type="number" | شمار کاربران !! data-sort-type="number" | کاربران فعال |- |Extra-Editbuttons || 82 || 2 |- |HotCat || 52 || 1 |- |RTRC || 23 || 1 |- |Twinkle || 48 || 1 |- |adddefinition || 41 || 1 |- |defaultsummaries || 25 || 1 |- |editzero || 43 || 1 |- |lastdiff || 45 || 1 |- |mySandbox || 33 || 1 |- |purgetab || 45 || 1 |- |userinfo || 48 || 2 |} * [[ویژه:استفاده ابزار]] * [[w:en:Wikipedia:GUS2Wiki/Script|GUS2Wiki]] <!-- data in CSV format: Extra-Editbuttons,82,2 HotCat,52,1 RTRC,23,1 Twinkle,48,1 adddefinition,41,1 defaultsummaries,25,1 editzero,43,1 lastdiff,45,1 mySandbox,33,1 purgetab,45,1 userinfo,48,2 --> nzgvglebeiugoq7cznzva0091g3gqlp بخارست (فیلم ۱۴٠۱) 0 193097 847557 847435 2022-07-23T13:14:50Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} بخارست rkx9hjgarxo4mm208qaej2oeq4bqv0r لاستیکماشین 0 193102 847598 847477 2022-07-23T17:41:31Z EmausBot 19188 ربات: اصلاح تغییرمسیر دوتایی به [[لاستیک‌ماشین]] wikitext text/x-wiki #تغییر_مسیر [[لاستیک‌ماشین]] j1eglr72rebbeph81gpe34m07dpz1q8 وفا، وصال، پیام 0 193106 847558 847506 2022-07-23T13:14:58Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} محمدجواد ابراهیمی n2fk3ywzrqzk2mq8cfk6h7aqf3cp3ic حبیب شاطرحاجی 0 193108 847559 847509 2022-07-23T13:15:07Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} حبیب شاطر حاجی متولد ۱۲۵۶ درگذشته:۱۳۲۷ (۷۱سال) وی ۱۲۷۵شروع به فعالیت کرد تا سال ۱۳۲۷ شاگردانش تاج اصفهانی بود ۱۳۲۷ بخاطر مریضی بد درگذشت در ۷۱صالگی روحش شاد یادش گرامی باد. lesaba50xuv6vkmccnswfbqje7dplss فیلم سوپر‌ها 0 193113 847560 847519 2022-07-23T13:15:15Z Beginneruser 11037 wikitext text/x-wiki {{حذف سریع|خارج از محدوده پروژه}} خودم mirfe4b73hqkoox3n1xu2bedyki9hv7 الگو:صفحه کاربری 10 193121 847609 847529 2022-07-24T05:49:26Z JECFNYSXSBYKBCDHT 34871 wikitext text/x-wiki {| id="userpage" align="center" style="text-align:center; border: {{{border-s|1}}}px solid {{{border-c|#ffc9c9}}}; background-color:{{{background|#FFFFF3}}}; margin:4px 0;" |- padding:1em;padding-top:0.5em;" |style="font-size: 85%"|'''این یک [[راهنما:واژه‌نامه|صفحه کاربری]] ویکی‌واژه است.''' این نوشتار بخشی از ویکی‌واژه است. اگر شما این صفحه را در هر وب‌گاهی به جز ویکی‌واژه مشاهده می‌کنید از یکی از وب‌گاه‌های آینهٔ ویکی‌کتاب دیدن می‌کنید. این صفحه ممکن است به‌روز نباشد و کاربری هم که این صفحه متعلق به اوست هیچ ارتباطی با وب‌گاهی به جز خود ویکی‌کتاب نداشته باشد. |} tv9ypun4ptxylhrizsosrnn2lotrkq6 کاربر:Narges 2020/صفحه تمرین 2 193122 847564 847533 2022-07-23T13:24:55Z Narges 2020 34862 wikitext text/x-wiki های 3x6vzkl465xpplndkjt0byl36cg861c 847565 847564 2022-07-23T13:25:05Z Narges 2020 34862 wikitext text/x-wiki های''' ''' egrv99x1eezhph33h447xyv6uzhmo22 بحث کاربر:MOMHADZDI 3 193128 847563 2022-07-23T13:16:41Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۳:۱۶ (UTC) jiwu0fzv2nbjk7t8rbyzqywab9zikqw رده:بن‌واژه‌های انگلیسی 14 193129 847581 2022-07-23T14:49:55Z Beginneruser 11037 صفحه‌ای تازه حاوی «[[رده:زبان انگلیسی]]» ایجاد کرد wikitext text/x-wiki [[رده:زبان انگلیسی]] slilmhk4iwwpf9mw7gv4m5k33xpi1af 847593 847581 2022-07-23T15:25:19Z Beginneruser 11037 wikitext text/x-wiki [[رده:زبان انگلیسی]] [[رده:بن‌واژه‌ها بر اساس زبان]] d0v22txtpl8bcjtd3t7easvexh2obom پودمان:multiple images 828 193130 847583 2022-07-23T14:57:17Z Beginneruser 11037 Import from [[en:Module:multiple images]] Scribunto text/plain -- implements [[template:multiple image]] local p = {} local autoscaledimages local nonautoscaledimages local function isnotempty(s) return s and s:match( '^%s*(.-)%s*$' ) ~= '' end local function removepx(s) return tostring(s or ''):match('^(.*)[Pp][Xx]%s*$') or s end local function getdimensions(s, w, h) if tonumber(w) and tonumber(h) then nonautoscaledimages = true return tonumber(w), tonumber(h) end local file = s and mw.title.new('File:' .. mw.uri.decode(mw.ustring.gsub(s,'%|.*$',''), 'WIKI')) file = file and file.file or {width = 0, height = 0} w = tonumber(file.width) or 0 h = tonumber(file.height) or 0 autoscaledimages = true return w, h end local function renderImageCell(image, width, height, link, alt, thumbtime, caption, textalign, istyle) local root = mw.html.create('') local altstr = '|alt=' .. (alt or '') local linkstr = link and ('|link=' .. link) or '' local widthstr = '|' .. tostring(width) .. 'px' local thumbtimestr = '' if isnotempty( thumbtime ) then thumbtimestr = '|thumbtime=' .. thumbtime end local imagediv = root:tag('div') imagediv:addClass('thumbimage') imagediv:cssText(istyle) if( height ) then imagediv:css('height', tostring(height) .. 'px') imagediv:css('overflow', 'hidden') end imagediv:wikitext('[[file:' .. image .. widthstr .. linkstr .. altstr .. thumbtimestr .. ']]') if isnotempty(caption) then local captiondiv = root:tag('div') captiondiv:addClass('thumbcaption') if isnotempty(textalign) then captiondiv:addClass('text-align-' .. textalign) end captiondiv:wikitext(caption) end return tostring(root) end local function getWidth(w1, w2) local w if isnotempty(w1) then w = tonumber(w1) elseif isnotempty(w2) then w = tonumber(w2) end return w or 200 end local function getPerRow(pstr, ic) -- split string into array using any non-digit as a dilimiter local pr = mw.text.split(pstr or '', '[^%d][^%d]*') -- if split failed, assume a single row if (#pr < 1) then pr = {tostring(ic)} end -- convert the array of strings to an array of numbers, -- adding any implied/missing numbers at the end of the array local r = 1 local thisrow = tonumber(pr[1] or ic) or ic local prownum = {} while( ic > 0 ) do prownum[r] = thisrow ic = ic - thisrow r = r + 1 -- use the previous if the next is missing and -- make sure we don't overstep the number of images thisrow = math.min(tonumber(pr[r] or thisrow) or ic, ic) end return prownum end local function renderMultipleImages(frame) local pargs = frame:getParent().args local args = frame.args local width = removepx(pargs['width'] or '') local dir = pargs['direction'] or '' local border = pargs['border'] or args['border'] or '' local align = pargs['align'] or args['align'] or (border == 'infobox' and 'center' or '') local capalign = pargs['caption_align'] or args['caption_align'] or '' local totalwidth = removepx(pargs['total_width'] or args['total_width'] or '') local imgstyle = pargs['image_style'] or args['image_style'] local header = pargs['header'] or pargs['title'] or '' local footer = pargs['footer'] or '' local imagegap = tonumber(pargs['image_gap'] or '1') or 1 local perrow = nil local thumbclass = { ["left"] = 'tleft', ["none"] = 'tnone', ["center"] = 'tnone', ["centre"] = 'tnone', ["right"] = 'tright' } -- find all the nonempty images local imagenumbers = {} local imagecount = 0 for k, v in pairs( pargs ) do local i = tonumber(tostring(k):match( '^%s*image([%d]+)%s*$' ) or '0') if( i > 0 and isnotempty(v) ) then table.insert( imagenumbers, i) imagecount = imagecount + 1 end end -- sort the imagenumbers table.sort(imagenumbers) -- create an array with the number of images per row perrow = getPerRow(dir == 'vertical' and '1' or pargs['perrow'], imagecount) -- compute the number of rows local rowcount = #perrow -- store the image widths and compute row widths and maximum row width local heights = {} local widths = {} local widthmax = 0 local widthsum = {} local k = 0 for r=1,rowcount do widthsum[r] = 0 for c=1,perrow[r] do k = k + 1 if( k <= imagecount ) then local i = imagenumbers[k] if( isnotempty(totalwidth) ) then widths[k], heights[k] = getdimensions(pargs['image' .. i], pargs['width' .. i], pargs['height' .. i]) else widths[k] = getWidth(width, pargs['width' .. i]) end widthsum[r] = widthsum[r] + widths[k] end end widthmax = math.max(widthmax, widthsum[r]) end -- make sure the gap is non-negative if imagegap < 0 then imagegap = 0 end -- if total_width has been specified, rescale the image widths if( isnotempty(totalwidth) ) then totalwidth = tonumber(totalwidth) widthmax = 0 local k = 0 for r=1,rowcount do local koffset = k local tw = totalwidth - (3 + imagegap) * (perrow[r] - 1) - 12 local ar = {} local arsum = 0 for j=1,perrow[r] do k = k + 1 if( k<= imagecount ) then local i = imagenumbers[k] local h = heights[k] or 0 if (h > 0) then ar[j] = widths[k]/h heights[k] = h else ar[j] = widths[k]/100 end arsum = arsum + ar[j] end end local ht = tw/arsum local ws = 0 k = koffset for j=1,perrow[r] do k = k + 1 if( k<= imagecount ) then local i = imagenumbers[k] widths[k] = math.floor(ar[j]*ht + 0.5) ws = ws + widths[k] if heights[k] then heights[k] = math.floor(ht) end end end widthsum[r] = ws widthmax = math.max(widthmax, widthsum[r]) end end -- start building the array of images, if there are images if( imagecount > 0 ) then -- compute width of outer div local bodywidth = 0 for r=1,rowcount do if( widthmax == widthsum[r] ) then bodywidth = widthmax + (3 + imagegap) * (perrow[r] - 1) + 12 end end -- The body has a min-width of 100, which needs to be taken into account on specific widths bodywidth = math.max( 100, bodywidth - 8); local bg = pargs['background color'] or '' -- create the array of images local root = mw.html.create('div') root:addClass('thumb') root:addClass('tmulti') -- root:addClass('tmulti-sandbox') root:addClass(thumbclass[align] or 'tright') if( align == 'center' or align == 'centre' ) then root:addClass('center') end if( bg ~= '' ) then root:css('background-color', bg) end local div = root:tag('div') div:addClass('thumbinner') div:css('width', tostring(bodywidth) .. 'px') :css('max-width', tostring(bodywidth) .. 'px') if( bg ~= '' ) then div:css('background-color', bg) end if( border == 'infobox' or border == 'none') then div:css('border', 'none') end -- add the header if( isnotempty(header) ) then div:tag('div') :addClass('trow') :tag('div') :addClass('theader') :css('text-align', pargs['header_align']) :css('background-color', pargs['header_background']) :wikitext(header) end -- loop through the images local k = 0 for r=1,rowcount do local rowdiv = div:tag('div'):addClass('trow'); for j=1,perrow[r] do k = k + 1 if( k <= imagecount ) then local imagediv = rowdiv:tag('div') imagediv:addClass('tsingle') if bg ~= '' then imagediv:css('background-color', bg); end if ((imagegap > 1) and (j < perrow[r])) then imagediv:css('margin-right', tostring(imagegap) .. 'px') end local i = imagenumbers[k] local img = pargs['image' .. i] local w = widths[k] imagediv:css('width', tostring(2 + w) .. 'px') :css('max-width', tostring(2 + w) .. 'px') imagediv:wikitext(renderImageCell(img, w, heights[k], pargs['link' .. i], pargs['alt' .. i], pargs['thumbtime' .. i], pargs['caption' .. i], capalign, imgstyle)) end end end -- add the footer if( isnotempty(footer) ) then local falign = string.lower(pargs['footer_align'] or args['footer_align'] or 'left') falign = (falign == 'centre') and 'center' or falign div:tag('div') :addClass('trow') :css('display', (falign ~= 'left') and 'flow-root' or 'flex') :tag('div') :addClass('thumbcaption') :css('text-align', (falign ~= 'left') and falign or nil) :css('background-color', pargs['footer_background']) :wikitext(footer) end return tostring(root) end return '' end function p.render( frame ) autoscaledimages = false nonautoscaledimages = false return frame:extensionTag {name = 'templatestyles', args = {src = 'multiple images/styles.css', wrapper = ".tmulti"}} .. renderMultipleImages( frame ) -- .. (autoscaledimages and '[[Category:Pages using multiple image with auto scaled images]]' or '') -- .. (nonautoscaledimages and '[[Category:Pages using multiple image with manual scaled images]]' or '') end return p at1nouw6xuppjj5a0fyw51oa0ns58vy 847587 847583 2022-07-23T15:08:07Z Beginneruser 11037 Scribunto text/plain -- implements [[template:multiple image]] local p = {} local autoscaledimages local nonautoscaledimages local function isnotempty(s) return s and s:match( '^%s*(.-)%s*$' ) ~= '' end local function removepx(s) return tostring(s or ''):match('^(.*)[Pp][Xx]%s*$') or s end local function getdimensions(s, w, h) if tonumber(w) and tonumber(h) then nonautoscaledimages = true return tonumber(w), tonumber(h) end local file = s and mw.title.new('File:' .. mw.uri.decode(mw.ustring.gsub(s,'%|.*$',''), 'WIKI')) file = file and file.file or {width = 0, height = 0} w = tonumber(file.width) or 0 h = tonumber(file.height) or 0 autoscaledimages = true return w, h end local function renderImageCell(image, width, height, link, alt, thumbtime, caption, textalign, istyle) local root = mw.html.create('') local altstr = '|alt=' .. (alt or '') local linkstr = link and ('|link=' .. link) or '' local widthstr = '|' .. tostring(width) .. 'px' local thumbtimestr = '' if isnotempty( thumbtime ) then thumbtimestr = '|thumbtime=' .. thumbtime end local imagediv = root:tag('div') imagediv:addClass('thumbimage') imagediv:cssText(istyle) if( height ) then imagediv:css('height', tostring(height) .. 'px') imagediv:css('overflow', 'hidden') end imagediv:wikitext('[[file:' .. image .. widthstr .. linkstr .. altstr .. thumbtimestr .. ']]') if isnotempty(caption) then local captiondiv = root:tag('div') captiondiv:addClass('thumbcaption') if isnotempty(textalign) then captiondiv:addClass('text-align-' .. textalign) end captiondiv:wikitext(caption) end return tostring(root) end local function getWidth(w1, w2) local w if isnotempty(w1) then w = tonumber(w1) elseif isnotempty(w2) then w = tonumber(w2) end return w or 200 end local function getPerRow(pstr, ic) -- split string into array using any non-digit as a dilimiter local pr = mw.text.split(pstr or '', '[^%d][^%d]*') -- if split failed, assume a single row if (#pr < 1) then pr = {tostring(ic)} end -- convert the array of strings to an array of numbers, -- adding any implied/missing numbers at the end of the array local r = 1 local thisrow = tonumber(pr[1] or ic) or ic local prownum = {} while( ic > 0 ) do prownum[r] = thisrow ic = ic - thisrow r = r + 1 -- use the previous if the next is missing and -- make sure we don't overstep the number of images thisrow = math.min(tonumber(pr[r] or thisrow) or ic, ic) end return prownum end local function renderMultipleImages(frame) local pargs = frame:getParent().args local args = frame.args local width = removepx(pargs['width'] or '') local dir = pargs['direction'] or '' local border = pargs['border'] or args['border'] or '' local align = pargs['align'] or args['align'] or (border == 'infobox' and 'center' or '') local capalign = pargs['caption_align'] or args['caption_align'] or '' local totalwidth = removepx(pargs['total_width'] or args['total_width'] or '') local imgstyle = pargs['image_style'] or args['image_style'] local header = pargs['header'] or pargs['title'] or '' local footer = pargs['footer'] or '' local imagegap = tonumber(pargs['image_gap'] or '1') or 1 local perrow = nil local thumbclass = { ["left"] = 'tleft', ["none"] = 'tnone', ["center"] = 'tnone', ["centre"] = 'tnone', ["right"] = 'tright' } -- find all the nonempty images local imagenumbers = {} local imagecount = 0 for k, v in pairs( pargs ) do local i = tonumber(tostring(k):match( '^%s*image([%d]+)%s*$' ) or '0') if( i > 0 and isnotempty(v) ) then table.insert( imagenumbers, i) imagecount = imagecount + 1 end end -- sort the imagenumbers table.sort(imagenumbers) -- create an array with the number of images per row perrow = getPerRow(dir == 'vertical' and '1' or pargs['perrow'], imagecount) -- compute the number of rows local rowcount = #perrow -- store the image widths and compute row widths and maximum row width local heights = {} local widths = {} local widthmax = 0 local widthsum = {} local k = 0 for r=1,rowcount do widthsum[r] = 0 for c=1,perrow[r] do k = k + 1 if( k <= imagecount ) then local i = imagenumbers[k] if( isnotempty(totalwidth) ) then widths[k], heights[k] = getdimensions(pargs['image' .. i], pargs['width' .. i], pargs['height' .. i]) else widths[k] = getWidth(width, pargs['width' .. i]) end widthsum[r] = widthsum[r] + widths[k] end end widthmax = math.max(widthmax, widthsum[r]) end -- make sure the gap is non-negative if imagegap < 0 then imagegap = 0 end -- if total_width has been specified, rescale the image widths if( isnotempty(totalwidth) ) then totalwidth = tonumber(totalwidth) widthmax = 0 local k = 0 for r=1,rowcount do local koffset = k local tw = totalwidth - (3 + imagegap) * (perrow[r] - 1) - 12 local ar = {} local arsum = 0 for j=1,perrow[r] do k = k + 1 if( k<= imagecount ) then local i = imagenumbers[k] local h = heights[k] or 0 if (h > 0) then ar[j] = widths[k]/h heights[k] = h else ar[j] = widths[k]/100 end arsum = arsum + ar[j] end end local ht = tw/arsum local ws = 0 k = koffset for j=1,perrow[r] do k = k + 1 if( k<= imagecount ) then local i = imagenumbers[k] widths[k] = math.floor(ar[j]*ht + 0.5) ws = ws + widths[k] if heights[k] then heights[k] = math.floor(ht) end end end widthsum[r] = ws widthmax = math.max(widthmax, widthsum[r]) end end -- start building the array of images, if there are images if( imagecount > 0 ) then -- compute width of outer div local bodywidth = 0 for r=1,rowcount do if( widthmax == widthsum[r] ) then bodywidth = widthmax + (3 + imagegap) * (perrow[r] - 1) + 12 end end -- The body has a min-width of 100, which needs to be taken into account on specific widths bodywidth = math.max( 100, bodywidth - 8); local bg = pargs['background color'] or '' -- create the array of images local root = mw.html.create('div') root:addClass('thumb') root:addClass('tmulti') -- root:addClass('tmulti-sandbox') root:addClass(thumbclass[align] or 'tleft') if( align == 'center' or align == 'centre' ) then root:addClass('center') end if( bg ~= '' ) then root:css('background-color', bg) end local div = root:tag('div') div:addClass('thumbinner') div:css('width', tostring(bodywidth) .. 'px') :css('max-width', tostring(bodywidth) .. 'px') if( bg ~= '' ) then div:css('background-color', bg) end if( border == 'infobox' or border == 'none') then div:css('border', 'none') end -- add the header if( isnotempty(header) ) then div:tag('div') :addClass('trow') :tag('div') :addClass('theader') :css('text-align', pargs['header_align']) :css('background-color', pargs['header_background']) :wikitext(header) end -- loop through the images local k = 0 for r=1,rowcount do local rowdiv = div:tag('div'):addClass('trow'); for j=1,perrow[r] do k = k + 1 if( k <= imagecount ) then local imagediv = rowdiv:tag('div') imagediv:addClass('tsingle') if bg ~= '' then imagediv:css('background-color', bg); end if ((imagegap > 1) and (j < perrow[r])) then imagediv:css('margin-right', tostring(imagegap) .. 'px') end local i = imagenumbers[k] local img = pargs['image' .. i] local w = widths[k] imagediv:css('width', tostring(2 + w) .. 'px') :css('max-width', tostring(2 + w) .. 'px') imagediv:wikitext(renderImageCell(img, w, heights[k], pargs['link' .. i], pargs['alt' .. i], pargs['thumbtime' .. i], pargs['caption' .. i], capalign, imgstyle)) end end end -- add the footer if( isnotempty(footer) ) then local falign = string.lower(pargs['footer_align'] or args['footer_align'] or 'left') falign = (falign == 'centre') and 'center' or falign div:tag('div') :addClass('trow') :css('display', (falign ~= 'left') and 'flow-root' or 'flex') :tag('div') :addClass('thumbcaption') :css('text-align', (falign ~= 'left') and falign or nil) :css('background-color', pargs['footer_background']) :wikitext(footer) end return tostring(root) end return '' end function p.render( frame ) autoscaledimages = false nonautoscaledimages = false return frame:extensionTag {name = 'templatestyles', args = {src = 'multiple images/styles.css', wrapper = ".tmulti"}} .. renderMultipleImages( frame ) -- .. (autoscaledimages and '[[Category:Pages using multiple image with auto scaled images]]' or '') -- .. (nonautoscaledimages and '[[Category:Pages using multiple image with manual scaled images]]' or '') end return p mvr0hisszzxr9uj3myrbqrlad6avvj6 الگو:multiple images/styles.css 10 193131 847584 2022-07-23T14:59:13Z Beginneruser 11037 Import from [[en:Template:multiple images/styles.css]] sanitized-css text/css /* this is a block */ .thumbinner { display: flex; flex-direction: column; } .trow { display: flex; flex-direction: row; clear: left; flex-wrap: wrap; width: 100%; box-sizing: border-box; } /* this is a cell */ .tsingle { margin: 1px; float: left; } .theader { clear: both; font-weight: bold; text-align: center; align-self: center; background-color: transparent; width: 100%; } .thumbcaption { background-color: transparent; } .text-align-left { text-align: left; } .text-align-right { text-align: right; } .text-align-center { text-align: center; } @media all and ( max-width: 720px ) { .thumbinner { /* not !important usage can be removed when these are no longer inline styles inside Template:Multiple image and media query using min-width is introduced */ width: 100% !important; box-sizing: border-box; max-width: none !important; align-items: center; } .trow { justify-content: center; } .tsingle { /* not !important usage can be removed when these are no longer inline styles inside Template:Multiple image and media query using min-width is introduced */ float: none !important; max-width: 100% !important; box-sizing: border-box; } .trow > .thumbcaption { text-align: center; } } 536isqb97aaq73ow3h92tpv9eehuy92 الگو:multiple images 10 193132 847585 2022-07-23T15:00:17Z Beginneruser 11037 Import from [[en:Template:multiple images]] wikitext text/x-wiki {{#invoke:multiple images|render}}<!-- --><noinclude>{{documentation}}</noinclude> 2erdplbcijevz3xjpo31wv56fuzhqn9 الگو:تصویرهای چندتایی 10 193133 847586 2022-07-23T15:01:07Z Beginneruser 11037 تغییرمسیر به [[الگو:multiple images]] wikitext text/x-wiki #تغییرمسیر [[الگو:multiple images]] ezawfpeg7cyy71kjj4q4lo4zbobcplv رده:اصطلاح‌های چند واژه‌ای انگلیسی 14 193134 847591 2022-07-23T15:22:13Z Beginneruser 11037 صفحه‌ای تازه حاوی «[[رده:بن‌واژه‌های انگلیسی]]» ایجاد کرد wikitext text/x-wiki [[رده:بن‌واژه‌های انگلیسی]] 248o5vdnndz6utkut09t4jt3hcn44kl بحث کاربر:Chromer030 3 193135 847592 2022-07-23T15:23:47Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۵:۲۳ (UTC) dcbwzhjez0zo4imjsh4vqi9rr4a7irt بحث کاربر:Antonklroberts 3 193136 847595 2022-07-23T16:43:46Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:Mardetanha|'''مرد تنها''']] ([[بحث کاربر:Mardetanha|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۶:۴۳ (UTC) 36xi492gilxhvk0l999m8lhkvl3qj0q Italian Social Republic 0 193137 847596 2022-07-23T17:19:56Z 5.213.51.253 هیچ wikitext text/x-wiki Italian Social Republic iselrvh7vvshiszs7sf6462w7rrnq9e بحث کاربر:MishaSchutt 3 193138 847600 2022-07-23T17:49:43Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:Mardetanha|'''مرد تنها''']] ([[بحث کاربر:Mardetanha|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۷:۴۹ (UTC) 1x8q7iwej2x9b0rl7u8pjzuhfa5q9x0 پویا ساکی 0 193139 847602 2022-07-23T18:25:07Z 207.244.231.77 صفحه‌ای تازه حاوی «==فارسی== ===اسم=== {{اسم-فا}} # # <!-- آن که در جهت پیشرفت حرکت می کند. اگر چندین توصیف داشت با گذاشتن علامت # در خط بعد، توصیف دیگر آن را نیز بنویسید -->» ایجاد کرد wikitext text/x-wiki ==فارسی== ===اسم=== {{اسم-فا}} # # <!-- آن که در جهت پیشرفت حرکت می کند. اگر چندین توصیف داشت با گذاشتن علامت # در خط بعد، توصیف دیگر آن را نیز بنویسید --> 1426tfbpebyx2mboecxwn7uu5cmvsz6 بحث کاربر:Shahrokh zangeneh 3 193140 847603 2022-07-23T19:48:27Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۱۹:۴۸ (UTC) 0kg0s1aia82l7hxav1xz08eh67x5e0f یه‌سویا 0 193141 847605 2022-07-23T21:27:21Z 5.123.161.61 صفحه‌ای تازه حاوی «یه سویا همسر امپراطور جومونگ و مادر جانشین او یوری بود» ایجاد کرد wikitext text/x-wiki یه سویا همسر امپراطور جومونگ و مادر جانشین او یوری بود 7p62ft6iis7bu89zfk5hic812fn1q9d بحث کاربر:Mhdbmsh 3 193142 847606 2022-07-23T22:15:58Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۲۲:۱۵ (UTC) 91wr64mf3n4cf95tii2o4uka3y51hd2 بحث کاربر:Popopynn1286 3 193143 847607 2022-07-23T23:57:29Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:Mardetanha|'''مرد تنها''']] ([[بحث کاربر:Mardetanha|بحث]]) ‏۲۳ ژوئیهٔ ۲۰۲۲، ساعت ۲۳:۵۷ (UTC) hi8f3mcgynuyp6klikn5h9s2rwlo4co بحث کاربر:Tahanazi 3 193144 847608 2022-07-24T00:57:06Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۴ ژوئیهٔ ۲۰۲۲، ساعت ۰۰:۵۷ (UTC) 3qkanrwxzbjmpr2pg9f0tsykc6v238w بحث کاربر:Ahouraprvish 3 193145 847610 2022-07-24T05:56:23Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۴ ژوئیهٔ ۲۰۲۲، ساعت ۰۵:۵۶ (UTC) 0gs4n3p6d3vbaphjmoux22m32hl192v بحث کاربر:Waranî 3 193146 847611 2022-07-24T09:06:01Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:AFlorence|'''فلورانس''']] ([[بحث کاربر:AFlorence|بحث]]) ‏۲۴ ژوئیهٔ ۲۰۲۲، ساعت ۰۹:۰۶ (UTC) n6006cp0gb49xqhk5fxv06rgfm03bfx بحث کاربر:Sadramousavi88 3 193147 847612 2022-07-24T10:24:37Z پیام به کاربر جدید 26498 افزودن [[الگو:خوشامدید|پیام خوش‌آمد]] به صفحهٔ بحث کاربر تازه wikitext text/x-wiki == خوش آمدید == [[ویکی‌واژه:تازه‌واردان، خوش آمدید|'''به ویکی‌واژه خوش‌آمدید''']]!<br /> امیدوارم حضوری طولانی مدت در ویکی‌واژه داشته باشید و بتوانیم با همکاری یکدیگر در جهت پیشرفت هر چه بیشتر این وبگاه گام برداریم. ویکی‌واژه منتظر نوشتارهای خوب شماست.<br /> این پیوندها می‌تواند سودمند باشد: {| |- |[[پرونده:Noia 64 apps help index.png|30px|right|link=ویکی‌واژه:راهنما|راهنما]] || [[ویکی‌واژه:راهنما|راهنما]] برای راهنمایی گرفتن |- | [[پرونده:Nuvola apps ksig.png|30px|right|link=ویکی‌واژه:آموزش سریع|آموزش سریع]] || [[ویکی‌واژه:آموزش سریع|آموزش سریع]] |- |||[[راهنما:افزودن سرواژه نو|افزودن سرواژهٔ نو]] راهنمای افزودن سرواژهٔ نو |- |||[[ویکی‌واژه:شیوه‌نامه|شیوه‌نامه]] شیوه‌نامهٔ ویکی‌واژه |- |[[File:Bucket in the sand.svg|right|50px]]||[[ویکی‌واژه:صفحه تمرین|صفحه تمرین]] برای تمرین ویرایش |- | [[پرونده:Nuvola apps chat.png|30px|right|link=ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]]||[[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] برای گفتگو دربارهٔ مسائل فنی و سیاست‌ها. |- |[[پرونده:Farsi.svg|30px|right|link=ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]]||[[ویکی‌واژه:فارسی‌نویسی|فارسی‌نویسی]] |- |[[پرونده:Nuvola apps agent.svg|30px|right|link=w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]]||[[w:ویکی‌پدیا:خودآموز|آموزش پیشرفته]] |- | |- | |- |'''پروژه‌های دیگر بنیاد'''||[[پرونده:Wikipedia-logo.png|25px|link=w:صفحه_اصلی|ویکی‌پدیا]][[پرونده:HSWikimedia.svg|30px|link=m:Special:Recentchanges|فراویکی]] [[پرونده:HSCommons.svg|30px|link=commons:Special:Recentchanges|ویکی‌انبار]][[پرونده:HSWNews.svg|30px|link=n:ویژه:تغییرات اخیر|ویکی‌خبر]] [[پرونده:HSWBooks.svg|30px|link=b:صفحه_اصلی|ویکی‌نَسک]] [[پرونده:HSWVoyage.svg|30px|link=voy:صفحه_اصلی|ویکی‌سفر]][[پرونده:HSWQuote.svg|30px|link=q:صفحه_اصلی|ویکی‌گفتاورد]][[پرونده:HSWSource.svg|30px|link=s:صفحه_اصلی|ویکی‌نبشته]] |} امیدوارم از ''[[ویکی‌واژه:ویکی‌واژه نویسان|ویکی‌واژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~&#126;~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکی‌واژه:قهوه‌خانه|قهوه‌خانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد می‌گویم!&nbsp;شاد باشید! -- [[کاربر:Mardetanha|'''مرد تنها''']] ([[بحث کاربر:Mardetanha|بحث]]) ‏۲۴ ژوئیهٔ ۲۰۲۲، ساعت ۱۰:۲۴ (UTC) l4wao9lb3bi5pzl3mp1a25xvm2pujhm