Module:fr-headword: difference between revisions
Kc kennylau (talk | contribs) No edit summary |
should negate it after calling it |
||
Line 24: | Line 24: | ||
end |
end |
||
-- mw.title.new() |
-- mw.title.new() returns nil if there are weird chars in |
||
-- the pagename. |
-- the pagename. |
||
local function exists(pagename) |
local function exists(pagename) |
||
local title = mw.title.new(pagename) |
local title = mw.title.new(pagename) |
||
return title and |
return title and title.exists |
||
end |
end |
||
Line 272: | Line 272: | ||
end |
end |
||
if exists(pl) then |
if not exists(pl) then |
||
table.insert(data.categories, "French nouns with missing plurals") |
table.insert(data.categories, "French nouns with missing plurals") |
||
end |
end |
||
Line 290: | Line 290: | ||
for _, f in ipairs(feminines) do |
for _, f in ipairs(feminines) do |
||
if exists(f) then |
if not exists(f) then |
||
table.insert(data.categories, "French nouns with missing forms") |
table.insert(data.categories, "French nouns with missing forms") |
||
end |
end |
||
Line 301: | Line 301: | ||
for _, m in ipairs(masculines) do |
for _, m in ipairs(masculines) do |
||
if exists(m) then |
if not exists(m) then |
||
table.insert(data.categories, "French nouns with missing forms") |
table.insert(data.categories, "French nouns with missing forms") |
||
end |
end |
||
Line 461: | Line 461: | ||
for key, val in pairs(data.inflections) do |
for key, val in pairs(data.inflections) do |
||
for i, form in ipairs(val) do |
for i, form in ipairs(val) do |
||
if exists(form) then |
if not exists(form) then |
||
table.insert(data.categories, "French adjectives with missing forms") |
table.insert(data.categories, "French adjectives with missing forms") |
||
return |
return |
Revision as of 19:34, 31 August 2017
- The following documentation is located at Module:fr-headword/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module is used for French headword-line templates. This module currently implements {{fr-noun}}
, {{fr-verb}}
, {{fr-adj}}
, {{fr-adv}}
, {{fr-intj}}
, {{fr-phrase}}
and several others; see the documentation of those templates for more information.
The module is always invoked the same way, by passing a single parameter to the "show" function. This parameter is the name of the part of speech, but in plural (examples given are for nouns, and for adjective forms respectively):
{{#invoke:fr-headword|show|nouns}} {{#invoke:fr-headword|show|adjective forms}}
The template will, by default, accept the following parameters (specific parts of speech may accept or require others):
|head=
- Override the headword display, used to add links to individual words in a multiword term.
|nolinkhead=1
- Don't link individual words in the headword of a multiword term. Useful for foreign terms like a posteriori and top model where the expression functions as a whole in French but the individual parts are not French words.
|splithyph=1
- Indicate that automatic splitting and linking of words should split on hyphens in multiword expressions with spaces in them (splitting on hyphens is automatic if there are no spaces in the term).
|pagename=
- Override the page name used to compute default values of various sorts. Useful when testing, for documentation pages, etc.
There is no parameter for the sort key, because this is not necessary. The sort key is automatically generated according to the normal alphabetical ordering in French.
Autosplitting
All templates using this module use an intelligent autosplitting algorithm to link portions of multipart and multiword expressions, as follows:
- The module will automatically split and link distinct space-separated words, similarly to
{{head}}
; hence, tout le monde will be linked as[[tout]] [[le]] [[monde]]
. - It also splits on apostrophes in the middle of words and includes the apostrophe in the preceding portion. Hence, n’importe quoi will be linked as
[[n']][[importe]] [[quoi]]
. (An exception is made for three words, quelqu’un, c’est and aujourd’hui, which will not be split if they occur as part of larger expressions.) - In addition, parts of hyphenated compounds in single-word expressions will be linked individually, e.g. grand-chose will be linked as
[[grand]]-[[chose]]
. Hyphenated compound words will not be split if they occur in multiword expressions unless|splithyph=1
is specified, since the compound itself might be a valid word.
Suffix handling
If the term begins with a hyphen (-
), it is assumed to be a suffix rather than a base form, and is categorized into Category:French suffixes and Category:French POS-forming suffixes rather than Category:French POSs (e.g. Category:French noun-forming suffixes rather than Category:French nouns).
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
-- mw.title.new() returns nil if there are weird chars in
-- the pagename.
local function exists(pagename)
local title = mw.title.new(pagename)
return title and title.exists
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
if not exists(pl) 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 exists(f) 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 exists(m) 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
-- Check existence
for key, val in pairs(data.inflections) do
for i, form in ipairs(val) do
if not exists(form) then
table.insert(data.categories, "French adjectives with missing forms")
return
end
end
end
end
}
return export