local export = {}
local pos_functions = {}
local rfind = mw.ustring.find
local rsubn = mw.ustring.gsub
local lang = require("Module:languages").getByCode("fr")
local suffix_categories = {
["adjectives"] = true,
["adverbs"] = true,
["nouns"] = true,
["verbs"] = true,
}
-- 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 track(page)
require("Module:debug").track("fr-headword/" .. page)
return true
end
local function add_suffix(list, suffix)
local newlist = {}
for _, item in ipairs(list) do
local form
if suffix == "s" then
if rfind(item, "[sx]$") then
form = item
elseif rfind(item, "al$") then
form = rsub(item, "al$", "aux")
else
form = item .. suffix
end
elseif suffix == "e" then
if rfind(item, "e$") then
form = item
elseif rfind(item, "en$") then
form = item .. "ne"
elseif rfind(item, "er$") then
form = rsub(item, "er$", "ère")
elseif rfind(item, "el$") then
form = item .. "le"
elseif rfind(item, "et$") then
form = item .. "te"
elseif rfind(item, "on$") then
form = item .. "ne"
elseif rfind(item, "ieur$") then
form = item .. "e"
elseif rfind(item, "teur$") then
form = rsub(item, "teur$", "trice")
elseif rfind(item, "eu[rx]$") then
form = rsub(item, "eu[rx]$", "euse")
elseif rfind(item, "if$") then
form = rsub(item, "if$", "ive")
elseif rfind(item, "c$") then
form = rsub(item, "c$", "que")
else
form = item .. suffix
end
else
form = item .. suffix
end
table.insert(newlist, form)
end
return newlist
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local PAGENAME = mw.title.getCurrentTitle().text
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, default = ""},
["suff"] = {type = "boolean"},
}
if mw.ustring.find(PAGENAME, " ") then
track("space")
end
if pos_functions[poscat] then
for key, val in pairs(pos_functions[poscat].params) do
params[key] = val
end
end
local parargs = frame:getParent().args
local args = require("Module:parameters").process(parargs, params)
local data = {lang = lang, pos_category = poscat, categories = {}, heads = args["head"], genders = {}, inflections = {}, categories = {}}
if args["suff"] then
data.pos_category = "suffixes"
if suffix_categories[poscat] then
local singular_poscat = poscat:gsub("s$", "")
table.insert(data.categories, lang:getCanonicalName() .. " " .. singular_poscat .. "-forming suffixes")
else
error("No category exists for suffixes forming " .. poscat .. ".")
end
end
if pos_functions[poscat] then
pos_functions[poscat].func(args, data)
end
return require("Module:headword").full_headword(data)
end
local allowed_genders = {
["m"] = true,
["f"] = true,
["m-p"] = true,
["f-p"] = true,
["m-s"] = true,
["f-s"] = true,
}
pos_functions["nouns"] = {
params = {
[1] = {},
["g"] = {list = true},
[2] = {list = true},
["f"] = {list = true},
["m"] = {list = true},
["dim"] = {list = true},
},
func = function(args, data)
local PAGENAME = mw.title.getCurrentTitle().text
local function default_plural()
if mw.ustring.find(PAGENAME, 'x$') then
track("default-x")
end
if mw.ustring.find(PAGENAME, 'z$') then
track("default-z")
end
if mw.ustring.find(PAGENAME,'[sxz]$') then
return PAGENAME
elseif mw.ustring.find(PAGENAME,'[ae]u$') then
return "x"
elseif mw.ustring.find(PAGENAME,'al$') then
return mw.ustring.sub(PAGENAME, 1, -3) .. 'aux'
else
return "s"
end
end
-- Gather genders
local function insert_gender(g)
if g == "mf" then
table.insert(data.genders, "m")
table.insert(data.genders, "f")
else
table.insert(data.genders, g)
end
end
insert_gender(args[1])
for _, g in ipairs(args.g) do
insert_gender(g)
end
-- Gather all the plural parameters from the numbered parameters.
local plurals = args[2]
plurals.label = "plural"
plurals.accel = "plural-form-of"
plurals.request = true
-- Gather all the feminine parameters
local feminines = args["f"]
feminines.label = "feminine"
-- Gather all the masculine parameters
local masculines = args["m"]
masculines.label = "masculine"
-- Add categories for genders
if #data.genders == 0 then
table.insert(data.genders, "?")
end
local mode = nil
for _, g in ipairs(data.genders) do
if g == "m-p" or g == "f-p" then
mode = "p"
end
if g == "?" and mw.title.getCurrentTitle().nsText == "Template" then
-- allow unknown gender in template example
elseif g and g ~= "" and not allowed_genders[g] then
error("Unrecognized French gender: " .. g)
end
if g == "m" or g == "m-p" or g == "m-s" then
table.insert(data.categories, "French masculine nouns")
elseif g == "f" or g == "f-p" or g == "f-s" then
table.insert(data.categories, "French feminine nouns")
end
end
-- Decide how to show the plurals
mode = mode or plurals[1]
-- Plural is not attested
if mode == "!" then
table.insert(data.inflections, {label = "plural not attested"})
table.insert(data.categories, "French nouns with unattested plurals")
-- Plural-only noun, doesn't have a plural
elseif mode == "p" then
table.insert(data.inflections, {label = "plural only"})
table.insert(data.categories, "French pluralia tantum")
else
-- Plural is unknown
if mode == "?" then
table.remove(plurals, 1) -- Remove the mode parameter
-- Uncountable noun; may occasionally have a plural
elseif mode == "-" then
table.remove(plurals, 1) -- Remove the mode parameter
table.insert(data.categories, "French uncountable nouns")
-- If plural forms were given explicitly, then show "usually"
if #plurals > 0 then
track("count-uncount")
table.insert(data.inflections, {label = "usually [[Appendix:Glossary#uncountable|uncountable]]"})
table.insert(data.categories, "French countable nouns")
else
table.insert(data.inflections, {label = "[[Appendix:Glossary#uncountable|uncountable]]"})
end
-- Mixed countable/uncountable noun, always has a plural
elseif mode == "~" then
table.remove(plurals, 1) -- Remove the mode parameter
table.insert(data.inflections, {label = "[[Appendix:Glossary#countable|countable]] and [[Appendix:Glossary#uncountable|uncountable]]"})
table.insert(data.categories, "French uncountable nouns")
table.insert(data.categories, "French countable nouns")
-- If no plural was given, add a default one now
if #plurals == 0 then
table.insert(plurals, default_plural())
end
-- The default, always has a plural
else
table.insert(data.categories, "French countable nouns")
-- If no plural was given, add a default one now
if #plurals == 0 then
table.insert(plurals, default_plural())
end
end
-- Process the plural forms
for i, pl in ipairs(plurals) do
if pl == "*" then
pl = PAGENAME
elseif pl == "s" then
pl = PAGENAME .. "s"
elseif pl == "x" then
pl = PAGENAME .. "x"
end
-- mw.title.new() can return nil if there are weird chars in
-- the plural
local newtitle = mw.title.new(pl)
if newtitle and not newtitle.exists then
table.insert(data.categories, "French nouns with missing plurals")
end
plurals[i] = pl
end
-- Add the plural forms
if mode ~= "-" or #plurals > 0 then
table.insert(data.inflections, plurals)
end
end
-- Add the feminine forms
if #feminines > 0 then
table.insert(data.inflections, feminines)
for _, f in ipairs(feminines) do
if not mw.title.new(f).exists then
table.insert(data.categories, "French nouns with missing forms")
end
end
end
-- Add the masculine forms
if #masculines > 0 then
table.insert(data.inflections, masculines)
for _, m in ipairs(masculines) do
if not mw.title.new(m).exists then
table.insert(data.categories, "French nouns with missing forms")
end
end
end
-- Handle diminutives
if #args.dim > 0 then
local dims_infl = mw.clone(args.dim)
dims_infl.label = "diminutive"
dims_infl.accel = "diminutive-form-of"
table.insert(data.inflections, dims_infl)
end
end
}
pos_functions["adjectives"] = {
params = {
[1] = {},
["inv"] = {},
["m2"] = {},
["onlyg"] = {},
["f"] = {list = true},
["mp"] = {list = true},
["fp"] = {list = true},
["p"] = {list = true},
["current"] = {list = true},
["comp"] = {list = true},
["sup"] = {list = true},
},
func = function(args, data)
local PAGENAME = mw.title.getCurrentTitle().text
if args.onlyg == "p" or args.onlyg == "m-p" or args.onlyg == "f-p" then
table.insert(data.categories, "French pluralia tantum")
end
if args.onlyg == "s" or args.onlyg == "f-s" or args.onlyg == "f-s" then
table.insert(data.categories, "French singularia tantum")
end
if args.onlyg then
table.insert(data.categories, "French defective adjectives")
end
if args.onlyg == "p" then
table.insert(data.inflections, {label = "plural only"})
if args[1] ~= "mf" then
-- Handle feminine plurals
if #args.fp > 0 then
local fplurals_infl = mw.clone(args.fp)
fplurals_infl.label = "feminine plural"
fplurals_infl.accel = "feminine-plural-form-of"
table.insert(data.inflections, fplurals_infl)
end
end
elseif args.onlyg == "s" then
table.insert(data.inflections, {label = "singular only"})
if not (args[1] == "mf" or #args.f == 0 and rfind(PAGENAME, "e$")) then
-- Handle feminines
local feminines = #args.f > 0 and args.f or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "e")
local feminines_infl = mw.clone(feminines)
feminines_infl.label = "feminine singular"
feminines_infl.accel = "feminine-singular-form-of"
table.insert(data.inflections, feminines_infl)
end
elseif args.onlyg == "m" then
table.insert(data.genders, "m")
table.insert(data.inflections, {label = "masculine only"})
-- Handle masculine plurals
local mplurals = #args.mp > 0 and args.mp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
local mplurals_infl = mw.clone(mplurals)
mplurals_infl.label = "masculine plural"
mplurals_infl.accel = "masculine-plural-form-of"
table.insert(data.inflections, mplurals_infl)
elseif args.onlyg == "f" then
table.insert(data.genders, "f")
table.insert(data.inflections, {label = "feminine only"})
-- Handle feminine plurals
local fplurals = #args.fp > 0 and args.fp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
local fplurals_infl = mw.clone(fplurals)
fplurals_infl.label = "feminine plural"
fplurals_infl.accel = "feminine-plural-form-of"
table.insert(data.inflections, fplurals_infl)
elseif args.onlyg then
table.insert(data.genders, args.onlyg)
table.insert(data.inflections, {label = "defective"})
else
-- Gather genders
local gender = args[1]
-- Default to mf if base form ends in -e and no feminine,
-- feminine plural or gender specified
if not gender and #args.f == 0 and #args.fp == 0 and rfind(PAGENAME, "e$") then
gender = "mf"
end
if #args.current > 0 then
track("adj-current")
end
if args.inv then
table.insert(data.inflections, {label = "invariable"})
end
-- Handle plurals of mf adjectives
local plurals = #args.p > 0 and args.p or {PAGENAME .. "s"}
if not args.inv and gender == "mf" then
local plurals_infl = mw.clone(plurals)
plurals_infl.label = "plural"
plurals_infl.accel = "plural-form-of"
table.insert(data.inflections, plurals_infl)
end
if not args.inv and gender ~= "mf" then
-- Handle case of special masculine singular before vowel
if args.m2 then
local masc_before_vowel = {args.m2}
masc_before_vowel.label = "masculine singular before vowel"
masc_before_vowel.accel = "masculine-singular-form-of"
table.insert(data.inflections, masc_before_vowel)
end
-- Handle feminines
local feminines = #args.f > 0 and args.f or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "e")
local feminines_infl = mw.clone(feminines)
feminines_infl.label = "feminine singular"
feminines_infl.accel = "feminine-singular-form-of"
table.insert(data.inflections, feminines_infl)
-- Handle masculine plurals
local mplurals = #args.mp > 0 and args.mp or add_suffix(#args.current > 0 and args.current or {PAGENAME}, "s")
local mplurals_infl = mw.clone(mplurals)
mplurals_infl.label = "masculine plural"
mplurals_infl.accel = "masculine-plural-form-of"
table.insert(data.inflections, mplurals_infl)
-- Handle feminine plurals
local fplurals = #args.fp > 0 and args.fp or add_suffix(feminines, "s")
local fplurals_infl = mw.clone(fplurals)
fplurals_infl.label = "feminine plural"
fplurals_infl.accel = "feminine-plural-form-of"
table.insert(data.inflections, fplurals_infl)
end
end
-- Handle comparatives
if #args.comp > 0 then
local comps_infl = mw.clone(args.comp)
comps_infl.label = "comparative"
comps_infl.accel = "comparative-form-of"
table.insert(data.inflections, comps_infl)
end
-- Handle superlatives
if #args.sup > 0 then
local sups_infl = mw.clone(args.sup)
sups_infl.label = "superlative"
sups_infl.accel = "superlative-form-of"
table.insert(data.inflections, sups_infl)
end
end
}
return export