ویکیواژه
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 " " .. 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 " " .. 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 " " .. 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 " " .. 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 " " .. 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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم!شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم!شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر: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:صفحه_اصلی|ویکینبشته]]
|}
امیدوارم از ''[[ویکیواژه:ویکیواژه نویسان|ویکیواژه نویس]]'' بودن لذت ببرید! لطفاً در صفحات گفتگو نام خود را با چهار علامت مدک امضا کنید، (~~~~)، با این کار نام شما و تاریخ به عنوان امضا درج خواهد شد. در صورتی که سوال داشتید، به صفحهٔ [[ویکیواژه:قهوهخانه|قهوهخانه]] بروید، یا اینکه از من در صفحهٔ بحثم بپرسید. باز هم خوش آمد میگویم! شاد باشید!
-- [[کاربر:Mardetanha|'''مرد تنها''']] ([[بحث کاربر:Mardetanha|بحث]]) ۲۴ ژوئیهٔ ۲۰۲۲، ساعت ۱۰:۲۴ (UTC)
l4wao9lb3bi5pzl3mp1a25xvm2pujhm