Module:etymology/templates: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
local export = {}
local require_when_needed = require("Module:utilities/require when needed")


local m_languages = require("Module:languages")
local concat = table.concat
local m_etymology = require("Module:etymology")
local format_categories = require_when_needed("Module:utilities", "format_categories")
 
local insert = table.insert
local rsplit = mw.text.split
local process_params = require_when_needed("Module:parameters", "process")
local rsubn = mw.ustring.gsub
local trim = mw.text.trim
 
local lower = mw.ustring.lower
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
 
local function fetch_lang(lang, parameter)
return m_languages.getByCode(lang) or m_languages.err(lang, parameter)
end


local export = {}


local function fetch_source(code, disallow_family)
local m_internal = require("Module:etymology/templates/internal")
local source =
m_languages.getByCode(code)
or require("Module:etymology languages").getByCode(code)
or not disallow_family and require("Module:families").getByCode(code)
if source then
return source
else
error("The language" .. (not disallow_family and ", family" or "") .. " or etymology language code \"" .. code .. "\" is not valid.")
end
end
 
 
local function fetch_script(sc)
return require("Module:scripts").getByCode(sc) or error("The script code \"" .. sc .. "\" is not valid.")
end


-- For testing
local force_cat = false


function export.etyl(frame)
function export.etyl(frame)
local params = {
local params = {
[1] = {required = true, default = "und"},
[1] = {required = true, type = "language", default = "und"},
[2] = {},
[2] = {type = "language", default = "en"},
["sort"] = {},
["sort"] = {},
}
}
local args = require("Module:parameters").process(frame:getParent().args, params)
local source = fetch_source(args[1])
local lang = args[2]
local sort_key = args["sort"]
-- Empty language means English, but "-" means no language. Yes, confusing...
-- Empty language means English, but "-" means no language. Yes, confusing...
if not lang then
local args = frame:getParent().args
lang = "en"
if args[2] and trim(args[2]) == "-" then
elseif lang == "-" then
params[2] = nil
lang = nil
args = process_params({
[1] = args[1],
["sort"] = args["sort"]
}, params)
else
args = process_params(args, params)
end
end
if lang then
return require("Module:etymology").format_etyl(args[2], args[1], args["sort"])
lang = fetch_lang(lang, 2)
end
return m_etymology.format_etyl(lang, source, sort_key)
end
end




function export.cognate(frame)
-- Supports various specialized types of borrowings, according to `frame.args.bortype`:
--  "learned" = {{lbor}}/{{learned borrowing}}
--  "semi-learned" = {{slbor}}/{{semi-learned borrowing}}
--  "orthographic" = {{obor}}/{{orthographic borrowing}}
--  "unadapted" = {{ubor}}/{{unadapted borrowing}}
--  "calque" = {{cal}}/{{calque}}
--  "partial-calque" = {{pcal}}/{{partial calque}}
--  "semantic-loan" = {{sl}}/{{semantic loan}}
--  "transliteration" = {{translit}}/{{transliteration}}
--  "phono-semantic-matching" = {{psm}}/{{phono-semantic matching}}
function export.specialized_borrowing(frame)
local bortype = frame.args.bortype
local args = frame:getParent().args
local args = frame:getParent().args
if args.gloss then
local params = {
require("Module:debug").track("borrowing/" .. bortype .. "/gloss param")
[1] = {required = true, default = "und"},
[2] = {},
[3] = {alias_of = "alt"},
[4] = {alias_of = "t"},
["alt"] = {},
["g"] = {list = true},
["id"] = {},
["lit"] = {},
["pos"] = {},
["t"] = {},
["gloss"] = {alias_of = "t"},
["tr"] = {},
["ts"] = {},
["sc"] = {},
["sort"] = {},
}
args = require("Module:parameters").process(args, params)
local source = fetch_source(args[1])
local sc = fetch_script(args["sc"])
 
return m_etymology.format_cognate(
{
lang = source,
sc = sc,
term = args[2],
alt = args["alt"],
id = args["id"],
genders = args["g"],
tr = args["tr"],
ts = args["ts"],
gloss = args["t"],
pos = args["pos"],
lit = args["lit"]
},
args["sort"])
end
 
 
function export.noncognate(frame)
return export.cognate(frame)
end
 
local function parse_2_lang_args(frame, has_text, no_family)
local params = {
[1] = {required = true, default = "und"},
[2] = {required = true, default = "und"},
[3] = {},
[4] = {alias_of = "alt"},
[5] = {alias_of = "t"},
["alt"] = {},
["g"] = {list = true},
["gloss"] = {alias_of = "t"},
["id"] = {},
["lit"] = {},
["pos"] = {},
["t"] = {},
["tr"] = {},
["ts"] = {},
["sc"] = {},
 
["nocat"] = {type = "boolean"},
["sort"] = {},
}
 
if has_text then
params["notext"] = {type = "boolean"}
params["nocap"] = {type = "boolean"}
end
end


local args = require("Module:parameters").process(frame:getParent().args, params)
-- More informative error message for {{calque}}, which used to support other params.
if bortype == "calque" and (args["etyl lang"] or args["etyl term"] or args["etyl t"] or args["etyl tr"]) then
local lang = fetch_lang(args[1], 1)
local source = fetch_source(args[2], no_family)
local sc = fetch_script(args["sc"])
 
return args, lang, {
lang = source,
sc = sc,
term = args[3],
alt = args["alt"],
id = args["id"],
genders = args["g"],
tr = args["tr"],
ts = args["ts"],
gloss = args["t"],
pos = args["pos"],
lit = args["lit"],
nocont = true,
}
end
 
function export.derived(frame)
local args, lang, term = parse_2_lang_args(frame)
return m_etymology.format_derived(lang, term, args["sort"], args["nocat"], "derived")
end
 
function export.inherited(frame)
local args, lang, term = parse_2_lang_args(frame, nil, "no family")
return m_etymology.format_inherited(lang, term, args["sort"], args["nocat"])
end
 
function export.borrowed(frame)
local args, lang, term = parse_2_lang_args(frame)
return m_etymology.format_borrowed(lang, term, args["sort"],
false, true, args["nocat"], "plain")
end
 
function export.learned_borrowing(frame)
 
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.format_borrowed(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"], "learned")
end
 
function export.semi_learned_borrowing(frame)
 
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.format_borrowed(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"], "semi-learned")
end
 
function export.orthographic_borrowing(frame)
 
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.format_borrowed(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"], "orthographic")
end
 
function export.unadapted_borrowing(frame)
 
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.format_borrowed(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"], "unadapted")
end
 
function export.calque(frame)
local args = frame:getParent().args
-- More informative error message.
if args["etyl lang"] or args["etyl term"] or args["etyl t"] or args["etyl tr"] then
error("{{[[Template:calque|calque]]}} no longer supports parameters beginning with etyl. " ..
error("{{[[Template:calque|calque]]}} no longer supports parameters beginning with etyl. " ..
"The parameters supported are similar to those used by " ..
"The parameters supported are similar to those used by " ..
Line 220: Line 61:
end
end
local args, lang, term = parse_2_lang_args(frame, "has text")
local lang, term, sources
return m_etymology.calque(lang, term, args["sort"],
args, lang, term, sources = m_internal.parse_2_lang_args(frame, "has text")
args["nocap"], args["notext"], args["nocat"])
local m_etymology_specialized = require("Module:etymology/specialized")
end
if sources then
 
return m_etymology_specialized.specialized_multi_borrowing(bortype, lang, term.sc, sources, term,
function export.partial_calque(frame)
args.sort, args.nocap, args.notext, args.nocat, args.conj, args.senseid)
 
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.partial_calque(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"])
end
 
function export.semantic_loan(frame)
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.semantic_loan(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"])
end
 
function export.psm(frame)
local args, lang, term = parse_2_lang_args(frame, "has text")
return m_etymology.phono_semantic_matching(lang, term, args["sort"],
args["nocap"], args["notext"], args["nocat"])
end
 
local function qualifier(content)
if content then
return table.concat{
'<span class="ib-brac qualifier-brac">(</span>',
'<span class="ib-content qualifier-content">',
content,
'</span>',
'<span class="ib-brac qualifier-brac">)</span>'
}
end
end
 
local function desc_or_desc_tree(frame, desc_tree)
local params
if desc_tree then
params = {
[1] = {required = true, default = "gem-pro"},
[2] = {required = true, default = "*fuhsaz"},
["notext"] = { type = "boolean" },
["noalts"] = { type = "boolean" },
["noparent"] = { type = "boolean" },
}
else
else
params = {
return m_etymology_specialized.specialized_borrowing(bortype, lang, term, args.sort,
[1] = { required = true },
args.nocap, args.notext, args.nocat, args.senseid)
[2] = {},
["alts"] = { type = "boolean" }
}
end
 
for k, v in pairs({
[3] = {},
[4] = { alias_of = "gloss" },
["g"] = {list = true},
["gloss"] = {},
["id"] = {},
["lit"] = {},
["pos"] = {},
["t"] = { alias_of = "gloss" },
["tr"] = {},
["ts"] = {},
["sc"] = {},
["bor"] = { type = "boolean" },
["lbor"] = { type = "boolean" },
["slb"] = { type = "boolean" },
["der"] = { type = "boolean" },
["clq"] = { type = "boolean" },
["cal"] = { alias_of = "clq" },
["calq"] = { alias_of = "clq" },
["calque"] = { alias_of = "clq" },
["pclq"] = { type = "boolean" },
["sml"] = { type = "boolean" },
["unc"] = { type = "boolean" },
["sclb"] = { type = "boolean" },
["nolb"] = { type = "boolean" },
["q"] = {},
["sandbox"] = { type = "boolean" },
}) do
params[k] = v
end
 
local namespace = mw.title.getCurrentTitle().nsText
 
local args
if frame.args[1] then
args = require("Module:parameters").process(frame.args, params)
else
args = require("Module:parameters").process(frame:getParent().args, params)
end
 
if args.sandbox then
if namespace == "" or namespace == "Reconstruction" then
error('The sandbox module, Module:descendants tree/sandbox, should not be used in entries.')
end
end
local lang = args[1]
local term = args[2]
local alt = args[3]
local gloss = args["gloss"]
local tr = args["tr"]
local ts = args["ts"]
local sc = args["sc"]
local id = args["id"]
if namespace == "Template" then
if not ( sc or lang ) then
sc = "Latn"
end
if not lang then
lang = "en"
end
if not term then
term = "word"
end
end
lang = m_languages.getByCode(lang)
or require("Module:etymology languages").getByCode(lang)
or m_languages.err(lang, 1)
local entryLang = m_etymology.getNonEtymological(lang)
if not desc_tree and entryLang:getType() == "family" then
error("Cannot use language family code in [[Template:desc]].")
end
if sc then
sc = require("Module:scripts").getByCode(sc) or error("The script code \"" .. sc .. "\" is not valid.")
end
local languageName = lang:getCanonicalName()
languageName = mw.ustring.gsub(languageName, "^Proto%-", "")
 
local link = ""
if term ~= "-" then
link = require("Module:links").full_link(
{
lang = entryLang,
sc = sc,
term = term,
alt = alt,
id = id,
tr = tr,
ts = ts,
genders = args["g"],
gloss = gloss,
pos = args["pos"],
lit = args["lit"],
},
nil,
true)
elseif ts or gloss or #args["g"] > 0 then
link = require("Module:links").full_link(
{
lang = entryLang,
sc = sc,
ts = ts,
gloss = gloss,
genders = args["g"],
},
nil,
true)
link = link
:gsub("<small>%[Term%?%]</small> ", "")
:gsub("<small>%[Term%?%]</small>&nbsp;", "")
:gsub("%[%[Category:[^%[%]]+ term requests%]%]", "")
end
local function add_tooltip(text, tooltip)
return '<span class="desc-arr" title="' .. tooltip .. '">' .. text .. '</span>'
end
local label, arrow, descendants, alts, semi_learned, calque, partial_calque, semantic_loan, qual
if args["sclb"] then
if sc then
label = sc:getCanonicalName()
else
label = require("Module:scripts").findBestScript(term, lang):getCanonicalName()
end
else
label = languageName
end
if args["bor"] then
arrow = add_tooltip("→", "borrowed")
elseif args["lbor"] then
arrow = add_tooltip("→", "learned borrowed")
elseif args["slb"] then
arrow = add_tooltip("→", "semi-learned borrowing")
elseif args["clq"] then
arrow = add_tooltip("→", "calque")
elseif args["pclq"] then
arrow = add_tooltip("→", "partial calque")
elseif args["sml"] then
arrow = add_tooltip("→", "semantic loan")
elseif args["unc"] and not args["der"] then
arrow = add_tooltip(">", "inherited")
else
arrow = ""
end
-- allow der=1 in conjunction with bor=1 to indicate e.g. English "pars recta"
-- derived and borrowed from Latin "pars".
if args["der"] then
arrow = arrow .. add_tooltip("⇒", "reshaped by analogy or addition of morphemes")
end
if args["unc"]then
arrow = arrow .. add_tooltip("?", "uncertain")
end
 
local m_desctree
if desc_tree or args["alts"] then
if args.sandbox or require("Module:yesno")(frame.args.sandbox, false) then
m_desctree = require("Module:descendants tree/sandbox")
else
m_desctree = require("Module:descendants tree")
end
end
 
if desc_tree then
descendants = m_desctree.getDescendants(entryLang, term, id)
end
if desc_tree and not args["noalts"] or not desc_tree and args["alts"] then
alts = m_desctree.getAlternativeForms(entryLang, term, id)
end
if args["lbor"] then
learned = " " .. qualifier("learned")
else
learned = ""
end
if args["slb"] then
semi_learned = " " .. qualifier("semi-learned")
else
semi_learned = ""
end
if args["clq"] then
calque = " " .. qualifier("calque")
else
calque = ""
end
if args["pclq"] then
partial_calque = " " .. qualifier("partial calque")
else
partial_calque = ""
end
 
if args["sml"] then
semantic_loan = " " .. qualifier("semantic loan")
else
semantic_loan = ""
end
if args["q"] then
qual = " " .. require("Module:qualifier").format_qualifier(args["q"])
else
qual = ""
end
 
if args["noparent"] then
return descendants
end
if arrow and arrow ~= "" then
arrow = arrow .. " "
end
local linktext = table.concat{link, alts or "", learned, semi_learned, calque,
partial_calque, semantic_loan, qual, descendants or ""}
if args["notext"] then
return linktext
elseif args["nolb"] then
return arrow .. linktext
else
return table.concat{arrow, label, ":", linktext ~= "" and " " or "", linktext}
end
end
end
function export.descendant(frame)
return desc_or_desc_tree(frame, false) .. require("Module:TemplateStyles")("Template:descendant/style.css")
end
end


function export.descendants_tree(frame)
return desc_or_desc_tree(frame, true)
end


-- Implementation of miscellaneous templates such as {{back-formation}}, {{clipping}},
-- Implementation of miscellaneous templates such as {{back-formation}}, {{clipping}},
-- {{ellipsis}}, {{rebracketing}}, and {{reduplication}} that have a single
-- {{ellipsis}}, {{rebracketing}}, and {{reduplication}} that have a single
-- associated term.
-- associated term.
function export.misc_variant(frame)
do
local params = {
local function get_args(frame)
[1] = {required = true, default = "und"},
local alias_of_t = {alias_of = "t"}
[2] = {},
local boolean = {type = "boolean"}
[3] = {alias_of = "alt"},
local plain = {}
[4] = {alias_of = "t"},
local params = {
[1] = {required = true, type = "language", default = "und"},
["alt"] = {},
[2] = plain,
["gloss"] = {alias_of = "t"},
[3] = {alias_of = "alt"},
["g"] = {list = true},
[4] = alias_of_t,
["id"] = {},
["lit"] = {},
["alt"] = plain,
["pos"] = {},
["gloss"] = alias_of_t,
["t"] = {},
["g"] = {list = true},
["tr"] = {},
["id"] = plain,
["ts"] = {},
["lit"] = plain,
["sc"] = {},
["pos"] = plain,
["t"] = plain,
["nocap"] = {type = "boolean"}, -- should be processed in the template itself
["tr"] = plain,
["notext"] = {type = "boolean"},
["ts"] = plain,
["nocat"] = {type = "boolean"},
["sc"] = {type = "script"},
["sort"] = {},
}
["nocap"] = boolean, -- should be processed in the template itself
["notext"] = boolean,
-- |ignore-params= parameter to module invocation specifies
["nocat"] = boolean,
-- additional parameter names to allow  in template invocation, separated by
["sort"] = plain,
-- commas. They must consist of ASCII letters or numbers or hyphens.
}
local ignore_params = frame.args["ignore-params"]
-- |ignore-params= parameter to module invocation specifies
if ignore_params then
-- additional parameter names to allow  in template invocation, separated by
ignore_params = mw.text.trim(ignore_params)
-- commas. They must consist of ASCII letters or numbers or hyphens.
if not ignore_params:match "^[%w%-,]+$" then
local ignore_params = frame.args["ignore-params"]
error("Invalid characters in |ignore-params=: " .. ignore_params:gsub("[%w%-,]+", ""))
if ignore_params then
end
ignore_params = trim(ignore_params)
for param in ignore_params:gmatch "[%w%-]+" do
if not ignore_params:match("^[%w%-,]+$") then
if params[param] then
error("Invalid characters in |ignore-params=: " .. ignore_params:gsub("[%w%-,]+", ""))
error("Duplicate param |" .. param
end
.. " in |ignore-params=: already specified in params")
for param in ignore_params:gmatch("[%w%-]+") do
if params[param] then
error("Duplicate param |" .. param
.. " in |ignore-params=: already specified in params")
end
params[param] = plain
end
end
params[param] = {}
end
end
return process_params(frame:getParent().args, params)
end
end
local args = require("Module:parameters").process(frame:getParent().args, params)
function export.misc_variant(frame)
local args = get_args(frame)
local lang = fetch_lang(args[1], 1)
local lang = args[1]
local sc = fetch_script(args["sc"])
local sc = args["sc"]


local parts = {}
local parts = {}
if not args["notext"] then
table.insert(parts, frame.args["text"])
end
if args[2] or args["alt"] then
if not args["notext"] then
if not args["notext"] then
table.insert(parts, " ")
insert(parts, frame.args["text"])
table.insert(parts, frame.args["oftext"] or "of")
end
table.insert(parts, " ")
if args[2] or args["alt"] then
if not args["notext"] then
insert(parts, " ")
insert(parts, frame.args["oftext"] or "of")
insert(parts, " ")
end
insert(parts, require("Module:links").full_link(
{
lang = lang,
sc = sc,
term = args[2],
alt = args["alt"],
id = args["id"],
tr = args["tr"],
ts = args["ts"],
genders = args["g"],
gloss = args["t"],
pos = args["pos"],
lit = args["lit"],
nocont = true,
},
"term"))
end
end
table.insert(parts, require("Module:links").full_link(
-- Allow |cat=, |cat2=, |cat3=, etc. They must be sequential. If |cat=
{
-- is not defined, |cat2= will not be checked. Empty categories are ignored.
lang = lang,
local categories = {}
sc = sc,
if not args["nocat"] and frame.args["cat"] then
term = args[2],
local cat_number
alt = args["alt"],
while true do
id = args["id"],
local cat = frame.args["cat" .. (cat_number or "")]
tr = args["tr"],
if not cat then break end
ts = args["ts"],
cat = trim(cat)
genders = args["g"],
if cat ~= "" then
gloss = args["t"],
insert(categories, lang:getFullName() .. " " .. cat)
pos = args["pos"],
end
lit = args["lit"],
cat_number = (cat_number or 1) + 1
},
"term",
true))
end
-- Allow |cat=, |cat2=, |cat3=, etc. They must be sequential. If |cat=
-- is not defined, |cat2= will not be checked. Empty categories are ignored.
local categories = {}
if not args["nocat"] and frame.args["cat"] then
local cat_number
while true do
local cat = frame.args["cat" .. (cat_number or "")]
if not cat then break end
cat = mw.text.trim(cat)
if cat ~= "" then
table.insert(categories, lang:getCanonicalName() .. " " .. cat)
end
end
cat_number = (cat_number or 1) + 1
end
end
if #categories > 0 then
insert(
parts,
format_categories(categories, lang, args["sort"], nil, force_cat))
end
return concat(parts)
end
end
if #categories > 0 then
table.insert(
parts,
require("Module:utilities").format_categories(categories, lang, args["sort"]))
end
return table.concat(parts)
end
end




local function get_parsed_part(template, lang, args, terms, i)
-- Implementation of miscellaneous templates such as {{unknown}} that have no
local term = terms[i]
-- associated terms.
local alt = args["alt"][i]
do
local id = args["id"][i]
local function get_args(frame)
local sc = fetch_script(args["sc"][i])
local boolean = {type = "boolean"}
local plain = {}
local params = {
[1] = {required = true, type = "language", default = "und"},


local tr = args["tr"][i]
["title"] = plain,
local ts = args["ts"][i]
["nocap"] = boolean, -- should be processed in the template itself
local gloss = args["t"][i]
["notext"] = boolean,
local pos = args["pos"][i]
["nocat"] = boolean,
local lit = args["lit"][i]
["sort"] = plain,
local g = args["g"][i]
}
 
if frame.args["title2_alias"] then
if term or alt or tr or ts then
params[2] = {alias_of = "title"}
return require("Module:links").full_link(
end
{ term = term, alt = alt, id = id, lang = lang, sc = sc, tr = tr,
return process_params(frame:getParent().args, params)
ts = ts, gloss = gloss, pos = pos, lit = lit,
genders = g and rsplit(g, ",") or {}
}, "term", true)
end
end
end


 
function export.misc_variant_no_term(frame)
local function get_parsed_parts(template, lang, args, terms)
local args = get_args(frame)
local parts = {}
local lang = args[1]
 
-- Find the maximum index among any of the list parameters.
local parts = {}
local maxmaxindex = 0
if not args["notext"] then
for k, v in pairs(args) do
insert(parts, args["title"] or frame.args["text"])
if type(v) == "table" and v.maxindex and v.maxindex > maxmaxindex then
end
maxmaxindex = v.maxindex
if not args["nocat"] and frame.args["cat"] then
local categories = {}
insert(categories, lang:getFullName() .. " " .. frame.args["cat"])
insert(parts, format_categories(categories, lang, args["sort"], nil, force_cat))
end
end
end


for index = 1, maxmaxindex do
return concat(parts)
table.insert(parts, get_parsed_part(template, lang, args, terms, index))
end
end
return parts
end


--This function works similarly to misc_variant_no_term(), but with some automatic linking to the glossary in `title`.
function export.onomatopoeia(frame)
local args = get_args(frame)


-- Implementation of miscellaneous templates such as {{doublet}} that can take
if args["title"] and (lower(args["title"]) == "imitative" or lower(args["title"]) == "imitation") then
-- multiple terms. Doesn't handle {{blend}} or {{univerbation}}, which display
args["title"] = "[[Appendix:Glossary#imitative|" .. args["title"] .. "]]"
-- + signs between elements and use compound_like in [[Module:compound/templates]].
end
function export.misc_variant_multiple_terms(frame)
local params = {
[1] = {required = true, default = "und"},
[2] = {list = true, allow_holes = true},


["t"] = {list = true, allow_holes = true, require_index = true},
local lang = args[1]
["gloss"] = {list = true, allow_holes = true, require_index = true, alias_of = "t"},
["tr"] = {list = true, allow_holes = true, require_index = true},
local parts = {}
["ts"] = {list = true, allow_holes = true, require_index = true},
["g"] = {list = true, allow_holes = true, require_index = true},
["id"] = {list = true, allow_holes = true, require_index = true},
["alt"] = {list = true, allow_holes = true, require_index = true},
["lit"] = {list = true, allow_holes = true, require_index = true},
["pos"] = {list = true, allow_holes = true, require_index = true},
["sc"] = {list = true, allow_holes = true, require_index = true},
 
["nocap"] = {type = "boolean"}, -- should be processed in the template itself
["notext"] = {type = "boolean"},
["nocat"] = {type = "boolean"},
["sort"] = {},
}
 
local args = require("Module:parameters").process(frame:getParent().args, params)
local lang = fetch_lang(args[1], 1)
 
local parts = {}
if not args["notext"] then
table.insert(parts, frame.args["text"])
end
if #args[2] > 0 or #args["alt"] > 0 then
if not args["notext"] then
if not args["notext"] then
table.insert(parts, " ")
insert(parts, args["title"] or frame.args["text"])
table.insert(parts, frame.args["oftext"] or "of")
end
table.insert(parts, " ")
if not args["nocat"] and frame.args["cat"] then
local categories = {}
insert(categories, lang:getFullName() .. " " .. frame.args["cat"])
insert(parts, format_categories(categories, lang, args["sort"], nil, force_cat))
end
end
local formatted_terms = get_parsed_parts(mw.ustring.lower(
-- Remove link and convert uppercase to lowercase to get an
-- approximation of the original template name.
rsub(rsub(frame.args["text"], "^%[%[.*|", ""), "%]%]$", "")),
lang, args, args[2])
table.insert(parts, require("Module:table").serialCommaJoin(formatted_terms))
end
if not args["nocat"] and frame.args["cat"] then
local categories = {}
table.insert(categories, lang:getCanonicalName() .. " " .. frame.args["cat"])
table.insert(parts, require("Module:utilities").format_categories(categories, lang, args["sort"]))
end


return table.concat(parts)
return concat(parts)
end
 
 
-- Implementation of miscellaneous templates such as {{unknown}} that have no
-- associated terms.
function export.misc_variant_no_term(frame)
local params = {
[1] = {required = true, default = "und"},
 
["title"] = {},
["nocap"] = {type = "boolean"}, -- should be processed in the template itself
["notext"] = {type = "boolean"},
["nocat"] = {type = "boolean"},
["sort"] = {},
}
 
if frame.args["title2_alias"] then
params[2] = {alias_of = "title"}
end
end
local args = require("Module:parameters").process(frame:getParent().args, params)
local lang = fetch_lang(args[1], 1)
local parts = {}
if not args["notext"] then
table.insert(parts, args["title"] or frame.args["text"])
end
if not args["nocat"] and frame.args["cat"] then
local categories = {}
table.insert(categories, lang:getCanonicalName() .. " " .. frame.args["cat"])
table.insert(parts, require("Module:utilities").format_categories(categories, lang, args["sort"]))
end
return table.concat(parts)
end
end


return export
return export

Latest revision as of 10:25, 7 August 2024



local require_when_needed = require("Module:utilities/require when needed")

local concat = table.concat
local format_categories = require_when_needed("Module:utilities", "format_categories")
local insert = table.insert
local process_params = require_when_needed("Module:parameters", "process")
local trim = mw.text.trim
local lower = mw.ustring.lower

local export = {}

local m_internal = require("Module:etymology/templates/internal")

-- For testing
local force_cat = false

function export.etyl(frame)
	local params = {
		[1] = {required = true, type = "language", default = "und"},
		[2] = {type = "language", default = "en"},
		["sort"] = {},
	}
	-- Empty language means English, but "-" means no language. Yes, confusing...
	local args = frame:getParent().args
	if args[2] and trim(args[2]) == "-" then
		params[2] = nil
		args = process_params({
			[1] = args[1],
			["sort"] = args["sort"]
		}, params)
	else
		args = process_params(args, params)
	end
	return require("Module:etymology").format_etyl(args[2], args[1], args["sort"])
end


-- Supports various specialized types of borrowings, according to `frame.args.bortype`:
--   "learned" = {{lbor}}/{{learned borrowing}}
--   "semi-learned" = {{slbor}}/{{semi-learned borrowing}}
--   "orthographic" = {{obor}}/{{orthographic borrowing}}
--   "unadapted" = {{ubor}}/{{unadapted borrowing}}
--   "calque" = {{cal}}/{{calque}}
--   "partial-calque" = {{pcal}}/{{partial calque}}
--   "semantic-loan" = {{sl}}/{{semantic loan}}
--   "transliteration" = {{translit}}/{{transliteration}}
--   "phono-semantic-matching" = {{psm}}/{{phono-semantic matching}}
function export.specialized_borrowing(frame)
	local bortype = frame.args.bortype
	local args = frame:getParent().args
	if args.gloss then
		require("Module:debug").track("borrowing/" .. bortype .. "/gloss param")
	end

	-- More informative error message for {{calque}}, which used to support other params.
	if bortype == "calque" and (args["etyl lang"] or args["etyl term"] or args["etyl t"] or args["etyl tr"]) then
		error("{{[[Template:calque|calque]]}} no longer supports parameters beginning with etyl. " ..
			"The parameters supported are similar to those used by " ..
			"{{[[Template:der|der]]}}, {{[[Template:inh|inh]]}}, " ..
			"{{[[Template:bor|bor]]}}. See [[Template:calque/documentation]] for more.")
	end
	
	local lang, term, sources
	args, lang, term, sources = m_internal.parse_2_lang_args(frame, "has text")
	local m_etymology_specialized = require("Module:etymology/specialized")
	if sources then
		return m_etymology_specialized.specialized_multi_borrowing(bortype, lang, term.sc, sources, term,
			args.sort, args.nocap, args.notext, args.nocat, args.conj, args.senseid)
	else
		return m_etymology_specialized.specialized_borrowing(bortype, lang, term, args.sort,
			args.nocap, args.notext, args.nocat, args.senseid)
	end
end


-- Implementation of miscellaneous templates such as {{back-formation}}, {{clipping}},
-- {{ellipsis}}, {{rebracketing}}, and {{reduplication}} that have a single
-- associated term.
do
	local function get_args(frame)
		local alias_of_t = {alias_of = "t"}
		local boolean = {type = "boolean"}
		local plain = {}
		local params = {
			[1] = {required = true, type = "language", default = "und"},
			[2] = plain,
			[3] = {alias_of = "alt"},
			[4] = alias_of_t,
			
			["alt"] = plain,
			["gloss"] = alias_of_t,
			["g"] = {list = true},
			["id"] = plain,
			["lit"] = plain,
			["pos"] = plain,
			["t"] = plain,
			["tr"] = plain,
			["ts"] = plain,
			["sc"] = {type = "script"},
			
			["nocap"] = boolean, -- should be processed in the template itself
			["notext"] = boolean,
			["nocat"] = boolean,
			["sort"] = plain,
		}
		-- |ignore-params= parameter to module invocation specifies
		-- additional parameter names to allow  in template invocation, separated by
		-- commas. They must consist of ASCII letters or numbers or hyphens.
		local ignore_params = frame.args["ignore-params"]
		if ignore_params then
			ignore_params = trim(ignore_params)
			if not ignore_params:match("^[%w%-,]+$") then
				error("Invalid characters in |ignore-params=: " .. ignore_params:gsub("[%w%-,]+", ""))
			end
			for param in ignore_params:gmatch("[%w%-]+") do
				if params[param] then
					error("Duplicate param |" .. param
						.. " in |ignore-params=: already specified in params")
				end
				params[param] = plain
			end
		end
		return process_params(frame:getParent().args, params)
	end
	
	function export.misc_variant(frame)		
		local args = get_args(frame)
		local lang = args[1]
		local sc = args["sc"]

		local parts = {}
		if not args["notext"] then
			insert(parts, frame.args["text"])
		end
		if args[2] or args["alt"] then
			if not args["notext"] then
				insert(parts, " ")
				insert(parts, frame.args["oftext"] or "of")
				insert(parts, " ")
			end
			insert(parts, require("Module:links").full_link(
				{
					lang = lang,
					sc = sc,
					term = args[2],
					alt = args["alt"],
					id = args["id"],
					tr = args["tr"],
					ts = args["ts"],
					genders = args["g"],
					gloss = args["t"],
					pos = args["pos"],
					lit = args["lit"],
					nocont = true,
				},
				"term"))
		end
		-- Allow |cat=, |cat2=, |cat3=, etc. They must be sequential. If |cat=
		-- is not defined, |cat2= will not be checked. Empty categories are ignored.
		local categories = {}
		if not args["nocat"] and frame.args["cat"] then
			local cat_number
			while true do
				local cat = frame.args["cat" .. (cat_number or "")]
				if not cat then break end
				cat = trim(cat)
				if cat ~= "" then
					insert(categories, lang:getFullName() .. " " .. cat)
				end
				cat_number = (cat_number or 1) + 1
			end
		end
		if #categories > 0 then
			insert(
				parts,
				format_categories(categories, lang, args["sort"], nil, force_cat))
		end

		return concat(parts)
	end
end


-- Implementation of miscellaneous templates such as {{unknown}} that have no
-- associated terms.
do
	local function get_args(frame)
		local boolean = {type = "boolean"}
		local plain = {}
		local params = {
			[1] = {required = true, type = "language", default = "und"},

			["title"] = plain,
			["nocap"] = boolean, -- should be processed in the template itself
			["notext"] = boolean,
			["nocat"] = boolean,
			["sort"] = plain,
		}
		if frame.args["title2_alias"] then
			params[2] = {alias_of = "title"}
		end
		return process_params(frame:getParent().args, params)
	end

	function export.misc_variant_no_term(frame)
		local args = get_args(frame)
		local lang = args[1]
		
		local parts = {}
		if not args["notext"] then
			insert(parts, args["title"] or frame.args["text"])
		end
		if not args["nocat"] and frame.args["cat"] then
			local categories = {}
			insert(categories, lang:getFullName() .. " " .. frame.args["cat"])
			insert(parts, format_categories(categories, lang, args["sort"], nil, force_cat))
		end

		return concat(parts)
	end

	--This function works similarly to misc_variant_no_term(), but with some automatic linking to the glossary in `title`.
	function export.onomatopoeia(frame)
		local args = get_args(frame)

		if args["title"] and (lower(args["title"]) == "imitative" or lower(args["title"]) == "imitation") then
			args["title"] = "[[Appendix:Glossary#imitative|" .. args["title"] .. "]]"
		end

		local lang = args[1]
		
		local parts = {}
		if not args["notext"] then
			insert(parts, args["title"] or frame.args["text"])
		end
		if not args["nocat"] and frame.args["cat"] then
			local categories = {}
			insert(categories, lang:getFullName() .. " " .. frame.args["cat"])
			insert(parts, format_categories(categories, lang, args["sort"], nil, force_cat))
		end

		return concat(parts)
	end
end

return export