local m_languages = require("Module:languages")
local m_links = require("Module:links")
local m_utilities = require("Module:utilities")
local m_table = require("Module:table")
local export = {}
local rfind = mw.ustring.find
local rmatch = mw.ustring.match
local rsubn = mw.ustring.gsub
-- 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 join_terms(terms, include_langname, do_language_link)
local links = {}
local langnametext
for _, term in ipairs(terms) do
if include_langname and not langnametext then
langnametext = term.lang:getCanonicalName() .. " "
end
term.lang = m_languages.getNonEtymological(term.lang)
if do_language_link and term.lang:getCode() == "en" then
link = "''" .. m_links.language_link(term, true) .. "''"
else
link = m_links.full_link(term, "term", true)
end
table.insert(links, link)
end
return (langnametext or "") .. m_table.serialCommaJoin(links, {conj = "or"})
end
local function join_names(lang, terms, alts, trs, ts, scs)
local term_objs = {}
local i = 1
local do_language_link = false
if not lang then
lang = m_languages.getByCode("en")
do_language_link = true
end
while terms[i] do
table.insert(term_objs, {
lang = lang, term = terms[i], alt = alts[i], tr = trs[i], gloss = ts[i],
sc = scs[i] and require("Module:scripts").getByCode(scs[i], "error if invalid"),
})
i = i + 1
end
return join_terms(term_objs, nil, do_language_link), #term_objs
end
local function get_eqtext(args)
local eqsegs = {}
local i = 1
local lastlang = nil
local last_eqseg = {}
while args.eq[i] do
local eqlang, eqterm = rmatch(args.eq[i], "^(.-):(.*)$")
if not eqlang then
eqlang = "en"
eqterm = args.eq[i]
end
if lastlang and lastlang ~= eqlang then
if #last_eqseg > 0 then
table.insert(eqsegs, last_eqseg)
end
last_eqseg = {}
end
lastlang = eqlang
table.insert(last_eqseg, {
lang = m_languages.getByCode(eqlang, "eq" .. (i == 1 and "" or i), "allow etym lang"),
term = eqterm,
alt = args.eqalt[i],
tr = args.eqtr[i],
gloss = args.eqt[i],
sc = args.eqsc[i] and require("Module:scripts").getByCode(args.eqsc[i], "error if invalid"),
})
i = i + 1
end
if #last_eqseg > 0 then
table.insert(eqsegs, last_eqseg)
end
local eqtextsegs = {}
for _, eqseg in ipairs(eqsegs) do
table.insert(eqtextsegs, join_terms(eqseg, "include langname"))
end
return m_table.serialCommaJoin(eqtextsegs)
end
local function get_fromtext(args)
local fromsegs = {}
local i = 1
local last_fromseg = nil
while args.from[i] do
local from = args.from[i]
local prefix, suffix
if from == "surnames" then
prefix = "transferred from the "
suffix = "surname"
elseif from == "place names" then
prefix = "transferred from the "
suffix = "place name"
elseif from == "coinages" then
prefix = "originating as "
suffix = "a coinage"
else
prefix = "from "
local fromlang, fromterm = rmatch(from, "^(.-):(.*)$")
if fromlang then
fromlang = m_languages.getByCode(fromlang, "from" .. (i == 1 and "" or i), "allow etym lang")
suffix = fromlang:getCanonicalName() .. " " .. m_links.full_link({
lang = m_languages.getNonEtymological(fromlang),
term = fromterm,
alt = args.fromalt[i],
tr = args.fromtr[i],
gloss = args.fromt[i],
pos = args.frompos[i],
lit = args.fromlit[i],
id = args.fromid[i],
sc = args.fromsc[i] and require("Module:scripts").getByCode(args.fromsc[i], "error if invalid"),
}, nil, true)
elseif rfind(from, " languages$") then
suffix = "the " .. from
else
suffix = from
end
end
if last_fromseg and last_fromseg.prefix ~= prefix then
table.insert(fromsegs, last_fromseg)
last_fromseg = nil
end
if not last_fromseg then
last_fromseg = {prefix = prefix, suffixes = {}}
end
table.insert(last_fromseg.suffixes, suffix)
i = i + 1
end
table.insert(fromsegs, last_fromseg)
local fromtextsegs = {}
for _, fromseg in ipairs(fromsegs) do
table.insert(fromtextsegs, fromseg.prefix ..
m_table.serialCommaJoin(fromseg.suffixes, {conj = "or"}))
end
return m_table.serialCommaJoin(fromtextsegs, {conj = "or"})
end
-- The main entry point.
function export.given_name(frame)
local parent_args = frame:getParent().args
local compat = parent_args.lang
local offset = compat and 0 or 1
local function track(page)
require("Module:debug").track("given name/" .. page)
end
local params = {
[compat and "lang" or 1] = { required = true },
["gender"] = { default = "unknown-gender" },
[1 + offset] = { alias_of = "gender", default = "unknown-gender" },
-- second gender
["or"] = {},
["from"] = { list = true },
[2 + offset] = { alias_of = from, list = true },
["fromt"] = { list = "from=t", allow_holes = true },
["fromalt"] = { list = "from=alt", allow_holes = true },
["fromtr"] = { list = "from=tr", allow_holes = true },
["frompos"] = { list = "from=pos", allow_holes = true },
["fromlit"] = { list = "from=lit", allow_holes = true },
["fromid"] = { list = "from=id", allow_holes = true },
["fromsc"] = { list = "from=sc", allow_holes = true },
["usage"] = {},
["meaning"] = { list = true },
["dim"] = { list = true },
["dimalt"] = { list = "dim=alt", allow_holes = true },
["dimtr"] = { list = "dim=tr", allow_holes = true },
["dimt"] = { list = "dim=t", allow_holes = true },
["dimsc"] = { list = "dim=sc", allow_holes = true },
["diminutive"] = { list = true, alias_of = "dim" },
["diminutivealt"] = { list = "diminutive=alt", alias_of = "dimalt", allow_holes = true },
["diminutivetr"] = { list = "diminutive=tr", alias_of = "dimtr", allow_holes = true },
["diminutivet"] = { list = "diminutive=t", alias_of = "dimt", allow_holes = true },
["diminutivesc"] = { list = "diminutive=sc", alias_of = "dimsc", allow_holes = true },
["eq"] = { list = true },
["eqalt"] = { list = "eq=alt", allow_holes = true },
["eqtr"] = { list = "eq=tr", allow_holes = true },
["eqt"] = { list = "eq=t", allow_holes = true },
["eqsc"] = { list = "eq=sc", allow_holes = true },
["xlit"] = { list = true },
["xlitalt"] = { list = "xlit=alt", allow_holes = true },
["var"] = { list = true },
["varalt"] = { list = "var=alt", allow_holes = true },
["vartr"] = { list = "var=tr", allow_holes = true },
["vart"] = { list = "var=t", allow_holes = true },
["varsc"] = { list = "var=sc", allow_holes = true },
["m"] = { list = true },
["malt"] = { list = "m=alt", allow_holes = true },
["mtr"] = { list = "m=tr", allow_holes = true },
["mt"] = { list = "m=t", allow_holes = true },
["msc"] = { list = "m=sc", allow_holes = true },
["f"] = { list = true },
["falt"] = { list = "f=alt", allow_holes = true },
["ftr"] = { list = "f=tr", allow_holes = true },
["ft"] = { list = "f=t", allow_holes = true },
["fsc"] = { list = "f=sc", allow_holes = true },
-- initial article: A or An
["A"] = {},
["sort"] = {},
["dimtype"] = {},
}
local args = require("Module:parameters").process(parent_args, params)
local textsegs = {}
local lang = args[compat and "lang" or 1]
if not lang and mw.title.getCurrentTitle().nsText == "Template" then
lang = "und"
end
lang = lang and m_languages.getByCode(lang, compat and "lang" or 1)
local dimtext, numdims =
join_names(lang, args.dim, args.dimalt, args.dimtr, args.dimt, args.dimsc)
local xlittext = join_names(nil, args.xlit, args.xlitalt, {}, {}, {})
local vartext = join_names(lang, args.var, args.varalt, args.vartr, args.vart, args.varsc)
local mtext = join_names(lang, args.m, args.malt, args.mtr, args.mt, args.msc)
local ftext = join_names(lang, args.f, args.falt, args.ftr, args.ft, args.fsc)
local meaningsegs = {}
for _, meaning in ipairs(args.meaning) do
table.insert(meaningsegs, '"' .. meaning .. '"')
end
local meaningtext = m_table.serialCommaJoin(meaningsegs, {conj = "or"})
local eqtext = get_eqtext(args)
table.insert(textsegs, "<span class='use-with-mention'>")
local dimtype = args.dimtype
local article = args.A or
dimtype and rfind(dimtype, "^[aeiouAEIOU]") and "An" or
args.gender == "unknown-gender" and "An" or
"A"
table.insert(textsegs, article .. " ")
if numdims > 0 then
table.insert(textsegs,
(dimtype and dimtype .. " " or "") ..
"[[diminutive]]" ..
(xlittext ~= "" and ", " .. xlittext .. "," or "") ..
" of the ")
end
local genders = {}
table.insert(genders, args.gender)
table.insert(genders, args["or"])
table.insert(textsegs, table.concat(genders, " or ") .. " ")
table.insert(textsegs, numdims > 1 and "[[given name|given names]]" or
"[[given name]]")
local need_comma = false
if numdims > 0 then
table.insert(textsegs, " " .. dimtext)
need_comma = true
elseif xlittext ~= "" then
table.insert(textsegs, ", " .. xlittext)
need_comma = true
end
if #args.from > 0 then
if need_comma then
table.insert(textsegs, ",")
end
need_comma = true
table.insert(textsegs, " ")
table.insert(textsegs, get_fromtext(args))
end
if meaningtext ~= "" then
if need_comma then
table.insert(textsegs, ",")
end
need_comma = true
table.insert(textsegs, " meaning " .. meaningtext)
end
if args.usage then
if need_comma then
table.insert(textsegs, ",")
end
need_comma = true
table.insert(textsegs, " of " .. args.usage .. " usage")
end
if vartext ~= "" then
table.insert(textsegs, ", variant of " .. vartext)
end
if mtext ~= "" then
table.insert(textsegs, ", masculine equivalent " .. mtext)
end
if ftext ~= "" then
table.insert(textsegs, ", feminine equivalent " .. ftext)
end
if eqtext ~= "" then
table.insert(textsegs, ", equivalent to " .. eqtext)
end
table.insert(textsegs, "</span>")
local categories = {}
local langname = lang:getCanonicalName() .. " "
local function insert_cats(isdim)
if isdim == "" then
-- No category such as "English diminutives of given names"
table.insert(categories, langname .. isdim .. "given names")
end
local function insert_cats_gender(g)
if g == "unknown-gender" then
track("unknown gender")
return
end
if g ~= "male" and g ~= "female" and g ~= "unisex" then
error("Unrecognized gender: " .. g)
end
if g == "unisex" then
insert_cats_gender("male")
insert_cats_gender("female")
end
table.insert(categories, langname .. isdim .. g .. " given names")
for i, from in ipairs(args.from) do
local fromcatform
local fromlang, fromterm = rmatch(from, "^(.-):(.*)$")
if fromlang then
fromcatform = m_languages.getByCode(fromlang, "from" .. (i == 1 and "" or i), "allow etym lang"):getCanonicalName()
elseif from == "surnames" or from == "place names" or from == "coinages" then
fromcatform = from
else
local family = rmatch(from, "^(.*) languages$")
if family then
if require("Module:families").getByCanonicalName(family) then
fromcatform = from
end
elseif m_languages.getByCanonicalName(from, nil, "allow etym") then
fromcatform = from
end
end
if fromcatform then
table.insert(categories, langname .. isdim .. g .. " given names from " .. fromcatform)
else
track("unrecognized from")
track("unrecognized from/" .. from)
end
end
end
insert_cats_gender(args.gender)
if args["or"] then
insert_cats_gender(args["or"])
end
end
insert_cats("")
if numdims > 0 then
insert_cats("diminutives of ")
end
return table.concat(textsegs, "") ..
m_utilities.format_categories(categories, lang, args.sort)
end
return export
-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet: