text:
Module:de-noun

local export = {}

--[=[

Authorship:

]=]

--[=[

TERMINOLOGY:

-- "slot" = A particular combination of case/number. Example slot names for nouns are "voc_s" (vocative singular) and "gen_p" (genitive plural). Each slot is filled with zero or more forms.

-- "form" = The declined German form representing the value of a given slot.

-- "lemma" = The dictionary form of a given German term. Generally the nominative masculine singular, but may occasionally be another form if the nominative masculine singular is missing. ]=]

--[=[ FIXME:

1. Qualifiers in genders should appear as footnotes on the articles. 2. Support notation like  on feminine/diminutive/masculine, e.g. used for Gespons (neuter with the meaning  "wife", masculine with the meaning "husband"). 3. Fix CSS gender-specific class in table. 4. Support adjectival nouns and adjective-noun combinations. (DONE) 5. Allow period and comma in forms e.g. for Eigent.-Whg., Eigt.-Whg. (using a backslash). (DONE) 6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=!weiblicher Geschäftspartner'. 7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article. 8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE) 9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE) ]=]

local lang = require("Module:languages").getByCode("de") local m_str_utils = require("Module:string utilities") local m_table = require("Module:table") local m_links = require("Module:links") local m_string_utilities = require("Module:string utilities") local iut = require("Module:inflection utilities") local com = require("Module:de-common")

local pretend_from_headword = false -- may be set during debugging local force_cat = false -- may be set during debugging

local u = m_str_utils.char local rfind = m_str_utils.find local rmatch = m_str_utils.match local rsubn = m_str_utils.gsub local usub = m_str_utils.sub

local SUB_ESCAPED_PERIOD = u(0xFFF0) local SUB_ESCAPED_COMMA = u(0xFFF1)

local archaic_dative_note = "[now rare, see notes]"

-- 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("de-noun/" .. page) return true end

local states = { "str", "wk", "mix" } local definitenesses = { "ind", "def" } local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" } local basic_cases = { "nom", "gen", "dat", "acc" } local numbers = { "s", "p" } local gender_spec_to_full_gender = { m = "masculine", f = "feminine", n = "neuter", }

local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)

local function add_equiv(slot_list) table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun end

-- Construct noun slots.

local noun_slot_list = {} add_equiv(noun_slot_list) local noun_slot_set = {} for _, number in ipairs(numbers) do	for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do local slot = case .. "_" .. number local accel = case .. "|" .. number table.insert(noun_slot_list, {slot, accel}) noun_slot_set[slot] = true end end

-- Construct noun surname slots.

local surname_slot_list = { } local surname_slot_set = {} local surname_endings = { {"m_s", "m|s"}, {"f_s", "f|s"}, {"p", "p"}, } for _, case in ipairs(basic_cases) do	for _, ending_and_accel in ipairs(surname_endings) do		local ending, ending_accel = unpack(ending_and_accel) local slot = case .. "_" .. ending local accel = case .. "|" .. ending_accel table.insert(surname_slot_list, {slot, accel}) surname_slot_set[slot] = true end end

-- Construct noun langname slots.

local langname_slot_list = { } local langname_slot_set = {} for _, case in ipairs(basic_cases) do	for _, number in ipairs(numbers) do		for _, is_alt in ipairs { false, true } do local slot = case .. "_" .. number .. (is_alt and "_alt" or "") -- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator -- code in Module:inflection utilities to specify the alternative lemma; e.g. genitive singular -- Deutschen needs to have lemma Deutsche not Deutsch. local accel = is_alt and "-" or case .. "|" .. number table.insert(langname_slot_list, {slot, accel}) langname_slot_set[slot] = true end end end

-- Construct adjectival slots.

local adjectival_slot_list = {} add_equiv(adjectival_slot_list) local adjectival_slot_set = {} for _, state in ipairs(states) do	for _, case in ipairs(basic_cases) do		for _, number in ipairs(numbers) do local slot = state .. "_" .. case .. "_" .. number local accel = state .. "|" .. case .. "|" .. number table.insert(adjectival_slot_list, {slot, accel}) adjectival_slot_set[slot] = true end end end

-- Construct expanded slot lists including linked variants.

local noun_slot_list_with_linked = m_table.shallowcopy(noun_slot_list) table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"}) table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})

local surname_slot_list_with_linked = m_table.shallowcopy(surname_slot_list) table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})

local langname_slot_list_with_linked = m_table.shallowcopy(langname_slot_list) table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})

local adjectival_slot_list_with_linked = m_table.shallowcopy(adjectival_slot_list) table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"}) table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})

-- Construct expanded slot lists including linked variants and articles.

local function add_slot_articles(slot_list, cases, numbers) for _, case in ipairs(cases) do		for _, number in ipairs(numbers) do			for _, def in ipairs(definitenesses) do local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"} table.insert(slot_list, slotaccel) end end end end

local noun_slot_list_with_linked_and_articles = m_table.shallowcopy(noun_slot_list_with_linked) add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)

local surname_slot_list_with_linked_and_articles = m_table.shallowcopy(surname_slot_list_with_linked) add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})

local langname_slot_list_with_linked_and_articles = m_table.shallowcopy(langname_slot_list_with_linked) add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})

local adjectival_slot_list_with_linked_and_articles = m_table.shallowcopy(adjectival_slot_list_with_linked) add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)

-- Return true if `prop` is a recognized indicator that can be specified on adjectives in Module:de-adjective. local function is_adjectival_decl_indicator(prop) return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns" end

local function skip_slot(number, slot) return number == "sg" and rfind(slot, "_p$") or		number == "pl" and rfind(slot, "_s$") end

local function combine_stem_ending(props, stem, ending) if ending:find("^%^") then -- Umlaut requested ending = rsub(ending, "^%^", "") stem = com.apply_umlaut(stem) end if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then stem = rsub(stem, "ß$", "ss") end return stem .. ending end

-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a -- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings) -- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is -- used to ensure that the correct article is attached to the form when there are multiple forms with differing -- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil -- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies -- any extra footnotes to add to the resulting form, and should be either nil or a list of strings. -- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used -- currently to add an -n to the dative plural.) local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending) if not ending or skip_slot(base.number, slot) then return end

local function do_combine_stem_ending(stem, ending) local retval = combine_stem_ending(base.props, stem, ending) if process_combined_stem_ending then retval = process_combined_stem_ending(retval) end -- For now, don't do this. -- If gender specified, add a special character to the beginning of the value to indicate the -- gender. This gets propagated to the end and used in Module:de-headword. -- if gender then --	retval = gender_to_gender_char[gender] .. retval -- end return retval end

footnotes = iut.combine_footnotes(base.footnotes, footnotes) local ending_obj = iut.combine_form_and_footnotes(ending, footnotes) -- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to -- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv", -- "f_equiv", "n_equiv", which are the same in nouns and adjectives. if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then for _, state in ipairs(states) do iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending) end else iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending) end end

-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, -- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the -- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If -- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as -- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as -- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates -- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an -- English description of what kind of spec is being processed, for error messages. `process` is called for each -- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that -- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM -- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that -- umlauts are not handled in process_spec; if the spec passed in specifies an umlaut, e.g. "^chen", process -- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled -- inside of add.) local function process_spec(endings, literal_endings, default, literal_default, desc, process) for _, ending in ipairs(endings) do		local function sub_form(form) return {form = form, footnotes = ending.footnotes} end

if ending.form == "--" then -- do nothing elseif ending.form == "+" then if not default then -- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter, -- where no default is available. error("Form '+' found for " .. desc .. " but no default is available") end process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process) else local full_eform if literal_endings or rfind(ending.form, "^" .. com.CAP) then full_eform = true elseif rfind(ending.form, "^!") then full_eform = true ending = sub_form(rsub(ending.form, "^!", "")) end if full_eform then process(ending, "") else local expanded_endings local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" ) if umlaut then expanded_endings = {"es", "s"} end if not umlaut then umlaut = rmatch(ending.form, "^(%^?)%(s%)$") if umlaut then expanded_endings = {"s", ""} end end if not umlaut then umlaut = rmatch(ending.form, "^(%^?)%(es%)$") if umlaut then expanded_endings = {"es", ""} end end if expanded_endings then local new_endings = {} for _, expanded_ending in ipairs(expanded_endings) do table.insert(new_endings, sub_form(umlaut .. expanded_ending)) end process(nil, new_endings) else if ending.form == "-" then ending = sub_form("") end process(nil, ending) end end end end end

-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural, -- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs, -- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or -- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add. -- For the meaning of `default` and `literal_default`, see process_spec. local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending) local function do_add(stem, ending) add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending) end process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add) end

local function process_slot_overrides(base) for slot, overrides in pairs(base.overrides) do		if skip_slot(base.number, slot) then error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction") end local origforms = base.forms[slot] base.forms[slot] = nil -- Gender is not given by the user. add_spec(base, slot, overrides, nil, origforms, "literal default") end end

local function add_archaic_dative_singular(base, gender, def_gen) for _, ending in ipairs(base.gens) do		local dat_ending local ending_form = ending.form if ending_form == "+" then ending_form = def_gen end if ending_form == "es" or ending_form == "(e)s" then dat_ending = "e" elseif ending_form == "ses" then dat_ending = "se" elseif base.props.dat_with_e then dat_ending = "e" end if dat_ending then add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note})) end end end

local function get_n_ending(base, stem, is_sg) if rfind(stem, "e$") then -- typical feminine or weak masculine in -e return "n" elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then -- Kammer, Feier, Leier, but not Spur, Beer, Manier, Schmier or Vier -- similarly, Achsel, Gabel, Tafel, etc. but not Ziel return "n" elseif base.props.weak_n then -- des Nachbarn, des Herrn, des Satyrn, etc.		return "n" elseif rfind(stem, "[^aeAE]in$") then -- Chinesin, Doktorin, etc.; but not words in -ein or -ain such as Pein return "nen" else return "en" end end

local function get_default_gen(base, gender) if gender == "f" then return "" elseif base.props.weak then return get_n_ending(base, base.lemma, "is singular") elseif rfind(base.lemma, "nis$") then -- neuter like Erlebnis, Geheimnis or occasional masculine like Firnis, Penis return "ses" elseif rfind(base.lemma, com.NV .. "us$") then -- Euphemismus, Exitus, Exodus, etc.		return "" elseif rfind(base.lemma, "[sßxz]$") then return "es" else return "s" end end

local function get_default_pl(base, gender) if rfind(base.lemma, "nis$") then -- neuter like Erlebnis, Geheimnis or feminine like Kenntnis, Wildnis, -- or occasional masculine like Firnis, Penis return "se" elseif gender == "f" or base.props.weak then return get_n_ending(base, base.lemma) elseif rfind(base.lemma, "e$") then track("default-pl-e-not-f-or-weak") -- FIXME: This should return "s" return get_n_ending(base, base.lemma) elseif gender == "n" and rfind(base.lemma, "lein$") then -- Diminutives in -lein (those in -chen will automatically get a null ending from -en below) return "" elseif gender == "n" and rfind(base.lemma, "um$") then -- Museum -> Museen, Vakuum -> Vakuen; not masculine Baum (plural Bäume) -- or Reichtum (plural Reichtümer) return "!" .. rsub(base.lemma, "um$", "en") elseif rfind(base.lemma, "mus$") then -- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen return "!" .. rsub(base.lemma, "us$", "en") elseif rfind(base.lemma, com.NV .. "us$") then -- Abakus -> Abakusse, Zirkus -> Zirkusse, Autobus -> Autobusse; -- not Applaus (plural Applause) return "se" elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then -- check for weak ending -el, -em, -en, -er, e.g. Adler, Meier, Riedel; but exclude Heer, -- Bier, Ziel, which take -e by default return "" else return "e" end end

local function decline_singular(base, gender, def_gen) add(base, "nom_s", nil, "", gender) add_spec(base, "gen_s", base.gens, gender, def_gen) if base.props.weak then local ending = get_n_ending(base, base.lemma, "is singular") add(base, "dat_s", nil, ending, gender) add(base, "acc_s", nil, gender == "m" and ending or "", gender) else add(base, "dat_s", nil, "", gender) add_archaic_dative_singular(base, gender, def_gen) add(base, "acc_s", nil, "", gender) end end

local function decline_plural(base, def_pl) local function process_nom_pl_for_decl_type(stem_ending) if base.props.saw_mn and base.number ~= "pl" then if base.props.weak then m_table.insertIfNot(base.decl_type, "weak") elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then m_table.insertIfNot(base.decl_type, "mixed") else m_table.insertIfNot(base.decl_type, "strong") end end return stem_ending end

local function process_dat_pl_to_add_n(stem_ending) if base.props.nodatpln then return stem_ending elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then return stem_ending .. "n" else return stem_ending end end

add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type) add_spec(base, "gen_p", base.pls, nil, def_pl) add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n) add_spec(base, "acc_p", base.pls, nil, def_pl) end

local function decline_noun(base) if base.number == "pl" then decline_plural(base, "") if rfind(base.lemma, "innen$") then --- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen. local masc = rsub(base.lemma, "innen$", "") if rfind(masc, "es$") then masc = masc .. "en" end -- No need to specify gender for *_equiv; will be handled correctly in Module:de-headword. add(base, "m_equiv", masc, "") else -- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen. local femstem = rsub(base.lemma, "en$", "") add(base, "f_equiv", femstem, "innen") end else base.decl_type = {} for _, genderspec in ipairs(base.genders) do			local gender = genderspec.form decline_singular(base, gender, get_default_gen(base, gender)) decline_plural(base, get_default_pl(base, gender)) if gender == "m" then add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine elseif gender == "f" then -- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese -- (e.g. Chinesin -> Chinese). local masc = rsub(base.lemma, "in$", "") if rfind(masc, "es$") then masc = masc .. "e" end add(base, "m_equiv", masc, "") end -- do nothing for neuter end end end

local function decline_surname(base) -- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in -- Module:de-headword. add(base, "nom_m_s", nil, "") add(base, "nom_f_s", nil, "") local gen_m_s if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then -- Marx, Engels, Weiß, Schulz -- also names with silent -s or -x like Delacroix gen_m_s = "'" else gen_m_s = "s" end add_spec(base, "gen_m_s", base.gens, nil, gen_m_s) add(base, "gen_m_s", nil, "", nil, {"[with an article]"}) add(base, "gen_f_s", nil, "") add(base, "dat_m_s", nil, "") add(base, "dat_f_s", nil, "") add(base, "acc_m_s", nil, "") add(base, "acc_f_s", nil, "") local pl_ending if rfind(base.lemma, "[sxß]$") then -- Marx, Engels, Weiß pl_ending = {"", "ens"} elseif rfind(base.lemma, "z$") then -- Schulz, Schmitz pl_ending = {"", "es", "ens"} elseif rfind(base.lemma, "ce$") then pl_ending = {"", "ns"} elseif rfind(base.lemma, "e[nlr]?$") then -- Müller, Goethe, Dürer, Schlegel, Münchhausen pl_ending = {"s", ""} else -- Schmidt, Bergmann, Brentano pl_ending = {"s"} end add_spec(base, "nom_p", base.pls, nil, pl_ending) add_spec(base, "gen_p", base.pls, nil, pl_ending) add_spec(base, "dat_p", base.pls, nil, pl_ending) add_spec(base, "acc_p", base.pls, nil, pl_ending) end

local function decline_toponym(base) -- We don't specify gender here, which is always neuter. add(base, "nom_s", nil, "") local gen_s local null_footnote if rfind(base.lemma, "[sxzß]$") then gen_s = "'" null_footnote = "[with an article]" else gen_s = "s" null_footnote = "[optionally with an article]" end add_spec(base, "gen_s", base.gens, nil, gen_s) add(base, "gen_s", nil, "", nil, {null_footnote}) add(base, "dat_s", nil, "") add(base, "acc_s", nil, "") if base.number == "both" then -- only with explicitly given plural add_spec(base, "nom_p", base.pls) add_spec(base, "gen_p", base.pls) add_spec(base, "dat_p", base.pls) add_spec(base, "acc_p", base.pls) end end

local function decline_langname(base) -- We don't specify gender here, which is always neuter. add(base, "nom_s", nil, "") add(base, "gen_s", nil, "") -- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s. add_spec(base, "gen_s", base.gens, nil, "s") add(base, "dat_s", nil, "") add(base, "acc_s", nil, "") add(base, "nom_s_alt", nil, "e") add(base, "gen_s_alt", nil, "en") add(base, "dat_s_alt", nil, "en") add(base, "acc_s_alt", nil, "e") end

local function decline_adjective(base) -- Construct an equivalent call to based on the adjective indicators we fetched. local adj_spec_parts = {} local function ins(val) table.insert(adj_spec_parts, val) end local function ins_dot if #adj_spec_parts > 0 then ins(".") end end local function insert_footnotes(footnotes) if footnotes then for _, footnote in ipairs(footnotes) do				ins(footnote) end end end if base.adj_stem then ins("stem") for _, stem in ipairs(base.adj_stem) do			ins(":") ins(stem.form) insert_footnotes(stem.footnotes) end end if base.adj_suppress then ins_dot ins("suppress:") ins(base.adj_suppress) end if base.footnotes then ins_dot insert_footnotes(base.footnotes) end for prop, _ in pairs(base.props) do		if is_adjectival_decl_indicator(prop) then ins_dot ins(prop) end end local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(		{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}	) local function copy(from_slot, to_slot) base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot] end local function copy_gender_forms(gender) local number = gender == "p" and "p" or "s" for _, state in ipairs(states) do			for _, case in ipairs(basic_cases) do copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number) end end end

if base.number == "pl" then copy_gender_forms("p") -- No need to specify gender for *_equiv; will be handled correctly in Module:de-headword. add(base, "m_equiv", base.lemma, "e") add(base, "f_equiv", base.lemma, "e") add(base, "n_equiv", base.lemma, "e") else -- Normally there should be only one gender. for _, genderspec in ipairs(base.genders) do			local gender = genderspec.form copy_gender_forms(gender) -- No need to specify gender for *_equiv; will be handled correctly in Module:de-headword. add(base, "m_equiv", base.lemma, "er") -- masculine add(base, "f_equiv", base.lemma, "e") -- feminine add(base, "n_equiv", base.lemma, "es") -- neuter end if base.number ~= "sg" then copy_gender_forms("p") end end end

-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table, -- coming either from `base` or `alternant_multiword_spec`. local function get_lemma_slots(props) if props.surname then return {"nom_m_s"} elseif props.overall_adj then return {"str_nom_s", "str_nom_p"} else return {"nom_s", "nom_p"} end end

-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}. -- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user), -- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any -- footnotes attached to the lemmas. function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes) local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props) local linked_suf = linked_variant and "_linked" or "" for _, slot in ipairs(slots_to_fetch) do if alternant_multiword_spec.forms[slot .. linked_suf] then local lemmas = alternant_multiword_spec.forms[slot .. linked_suf] if remove_footnotes then local lemmas_no_footnotes = {} for _, lemma in ipairs(lemmas) do					table.insert(lemmas_no_footnotes, {form = lemma.form}) end return lemmas_no_footnotes else return lemmas end end end return {} end

local function handle_derived_slots_and_overrides(base) process_slot_overrides(base)

-- Compute linked versions of potential lemma slots, for use in. -- We substitute the original lemma (before removing links) for forms that -- are the same as the lemma, if the original lemma has links. for _, slot in ipairs(get_lemma_slots(base.props)) do iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form) if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then return base.orig_lemma else return form end end)) end end

-- Like iut.split_alternating_runs_and_strip_spaces, but ensure that backslash-escaped commas and periods are not -- treated as separators. local function split_alternating_runs_with_escapes(segments, splitchar) for i, segment in ipairs(segments) do		segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA) segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD) end local separated_groups = iut.split_alternating_runs_and_strip_spaces(segments, splitchar) for _, separated_group in ipairs(separated_groups) do		for i, segment in ipairs(separated_group) do			separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",") separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".") end end return separated_groups end

--[=[ Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them). Return value is an object of the form

{ overrides = { SLOT = {OVERRIDE, OVERRIDE, ...}, ... }, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if		beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while "--" suppresses the slot entirely, i.e. it is defective gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above forms = {}, -- forms for a single spec alternant; see `forms` below props = { PROP = true, PROP = true, ... }, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+"); "ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling); "nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el') number = "NUMBER", -- "sg", "pl", "both"; may be missing adj = true, -- may be missing

-- The following additional fields are added by other functions: orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed lemma = "LEMMA", -- `orig_lemma_no_links`, forms = { SLOT = { {		form = "FORM", footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing },	 ...	},	...  }, } ]=] local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun) if lemma == "" then lemma = pagename end local base = {forms = {}, overrides = {}, props = {prop = proper_noun}} base.orig_lemma = lemma base.orig_lemma_no_links = m_links.remove_links(lemma) base.lemma = base.orig_lemma_no_links local inside = rmatch(angle_bracket_spec, "^<(.*)>$") assert(inside)

local function parse_err(msg) error(msg .. ": <" .. inside .. ">") end

--[=[	Parse a single override spec and return three values: the slot the override applies to, the original indicator spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]', the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en", "[in most cases in writing]", ""} ]=]	local function parse_override(segments) local part = segments[1] local offset = 4 local case = usub(part, 1, 3) if not case_set_with_abl_voc[case] then parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'") end local indicator = case local rest = usub(part, offset) local slot if rfind(rest, "^pl") then rest = rsub(rest, "^pl", "") slot = case .. "_p" indicator = indicator .. "pl" else slot = case .. "_s" end if rfind(rest, "^:") then rest = rsub(rest, "^:", "") else parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'") end if not noun_slot_set[slot] then parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'") end segments[1] = rest return slot, indicator, com.fetch_specs(iut, segments, ":", "override", nil, parse_err) end

if inside ~= "" then local segments = iut.parse_balanced_segment_run(inside, "[", "]") local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.") for i, dot_separated_group in ipairs(dot_separated_groups) do			local part = dot_separated_group[1] if i == 1 then local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",") base.genders = com.fetch_specs(iut, comma_separated_groups[1], ":", "gender", nil, parse_err) local saw_sg = false local saw_pl = false local saw_gendered_pl = false local saw_non_gendered_pl = false local saw_adj = false local special_variant = nil for _, genderspec in ipairs(base.genders) do					local g = genderspec.form if g == "m" or g == "n" then -- Set this on `base.props` as it's used in various other places. base.props.saw_mn = true saw_sg = true elseif g == "f" then saw_sg = true elseif g == "p" then saw_pl = true saw_non_gendered_pl = true elseif rfind(g, "^[mfn]p$") then saw_pl = true saw_gendered_pl = true elseif g == "+" or g == "p+" or g == "+p" then if #base.genders > 1 then parse_err("Can't specify multiple genders with adjectival declension") end saw_adj = true if g ~= "+" then saw_pl = true end elseif g == "surname" or g == "toponym" or g == "langname" then if #base.genders > 1 then parse_err("Can't specify multiple genders with " .. g .. " declension") end special_variant = g					else parse_err("Unrecognized gender spec '" .. g .. "'") end end if saw_sg and saw_pl then parse_err("Can't specify both singular and plural gender specs") end if saw_gendered_pl and saw_non_gendered_pl then parse_err("Can't specify both 'p' and gendered plural specs") end local gen_index = (base.props.saw_mn or special_variant) and 2 or 1 local pl_index = (saw_adj or saw_pl) and 1 or					(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or					2 if #comma_separated_groups > pl_index then if saw_adj then parse_err("Can't specify plurals or genitives with adjectival declension") elseif saw_pl then parse_err("Can't specify plurals or genitives with plural-only nouns") elseif base.props.saw_mn then parse_err("Can specify at most three comma-separated specs when the gender is masculine or "							.. "neuter (gender, genitive, plural)") elseif special_variant == "surname" or special_variant == "toponym" then parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "							.. "nouns ('" .. special_variant .. "', genitive, plural)") elseif special_variant == "langname" then parse_err("Can specify at most two comma-separated specs with 'langname' "							.. " ('langname', genitive)") else parse_err("Can specify at most two comma-separated specs when the gender is feminine "							.. "(gender, plural)") end end if #comma_separated_groups >= gen_index and gen_index > 1 then base.gens = com.fetch_specs(iut, comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err) end if #comma_separated_groups >= pl_index and pl_index > gen_index then base.pls = com.fetch_specs(iut, comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err) end if special_variant then if #base.genders > 1 then parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'") else base.props[special_variant] = true if special_variant == "surname" then -- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)? base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}} else base.genders = end end elseif saw_adj then if #base.genders > 1 then parse_err("Internal error: More than one gender spec for adjectival declension") else base.props.adj = true if saw_pl then base.number = "pl" base.genders = else -- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender -- in determine_adjectival_genders, which will set base.genders appropriately. base.adj_footnotes = base.genders[1].footnotes base.genders = {} end end elseif saw_pl then -- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what Module:gender and number expects. for _, genderspec in ipairs(base.genders) do						local gender = rmatch(genderspec.form, "^([mfn])p$") if gender then genderspec.form = gender .. "-p" end end base.number = "pl" end elseif base.props.adj and part:find("^stem:") then dot_separated_group[1] = rsub(part, "^stem:", "") base.adj_stem = com.fetch_specs(iut, dot_separated_group, ":", "adjectival stem", nil, parse_err) elseif base.props.adj and part:find("^suppress:") then if #dot_separated_group > 1 then parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'") end -- No need to parse or validate more. Will happen in Module:de-adjective. base.adj_suppress = rsub(part, "suppress:", "") elseif part == "" then if #dot_separated_group == 1 then parse_err("Blank indicator") end base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err) elseif part:find(":") then -- override -- FIXME: Handle adjectival overrides local case_prefix = usub(part, 1, 3) if case_set_with_abl_voc[case_prefix] then local slot, slot_indicator, override = parse_override(dot_separated_group) if base.overrides[slot] then parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'") else base.overrides[slot] = override end else parse_err("Unrecognized indicator '" .. part .. "'") end elseif #dot_separated_group > 1 then local errmsg if base.props.adj then errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves" else errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves" end parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'") elseif part == "sg" or part == "both" then if base.number then if base.number ~= part then parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'") else parse_err("Can't specify '" .. part .. "' twice") end end base.number = part elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then if base.props[part] then parse_err("Can't specify '" .. part .. "' twice") end base.props[part] = true if part == "weak_n" then -- weak_n implies weak base.props.weak = true end elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then if base.props[part] then parse_err("Can't specify '" .. part .. "' twice") end base.props[part] = true else parse_err("Unrecognized indicator '" .. part .. "'") end end end return base end

-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the -- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that. local function synthesize_adj_lemma(base) local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$") if not stem then error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'") end base.lemma = stem -- Will be ignored if number == "pl" if ending == "er" then base.autodetected_gender = "m" elseif ending == "e" then base.autodetected_gender = "f" else base.autodetected_gender = "n" end end

local function detect_indicator_spec(alternant_multiword_spec, base) if base.props.article then alternant_multiword_spec.props.article = true end for _, prop in ipairs {"surname", "toponym", "langname"} do		if alternant_multiword_spec.props[prop] == nil then alternant_multiword_spec.props[prop] = base.props[prop] elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then -- We do this because we have a special table with its own slots for each of these special variants. -- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival -- declensions to the appropriate per-variant slots. error("If some alternants set '" .. prop .. "', all must do so") end end if base.props.adj then alternant_multiword_spec.props.overall_adj = true synthesize_adj_lemma(base) else -- Set default values. base.number = base.number or			base.props.surname and "both" or			base.pls and "both" or			(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or			"both" if not base.props.surname then if base.number == "pl" then if base.gens then error("Internal error: With plural-only noun, no genitive singular specs should be allowed") end if base.pls then error("Internal error: With plural-only noun, no plural specs should be allowed") end end if base.pls and base.number == "sg" then error("Can't specify explicit plural specs along with explicit '.sg'") end end base.gens = base.gens or 		base.pls = base.pls or 	end end

local function detect_all_indicator_specs(alternant_multiword_spec) iut.map_word_specs(alternant_multiword_spec, function(base)		detect_indicator_spec(alternant_multiword_spec, base)	end) -- Now propagate some properties downwards. iut.map_word_specs(alternant_multiword_spec, function(base)		base.props.overall_adj = alternant_multiword_spec.props.overall_adj	end) end

local propagate_multiword_properties

local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only) local seen_property for _, multiword_spec in ipairs(alternant_spec.alternants) do		propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only) if seen_property == nil then seen_property = multiword_spec[property] elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then seen_property = mixed_value end end alternant_spec[property] = seen_property end

propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only) local seen_property = nil local last_seen_nounal_pos = 0 local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs for i = 1, #word_specs do		local is_nounal if word_specs[i].alternants then propagate_alternant_properties(word_specs[i], property, mixed_value) is_nounal = not not word_specs[i][property] elseif nouns_only then is_nounal = not word_specs[i].props.adj else is_nounal = not not word_specs[i][property] end if is_nounal then if not word_specs[i][property] then error("Internal error: noun-type word spec without " .. property .. " set") end for j = last_seen_nounal_pos + 1, i - 1 do				word_specs[j][property] = word_specs[j][property] or word_specs[i][property] end last_seen_nounal_pos = i			if seen_property == nil then seen_property = word_specs[i][property] elseif seen_property ~= word_specs[i][property] then seen_property = mixed_value end end end if last_seen_nounal_pos > 0 then for i = last_seen_nounal_pos + 1, #word_specs do			word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property] end end multiword_spec[property] = seen_property end

local function propagate_properties_downward(alternant_multiword_spec, property, default_propval) local propval1 = alternant_multiword_spec[property] or default_propval alternant_multiword_spec[property] = propval1 for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do		local propval2 = alternant_or_word_spec[property] or propval1 if alternant_or_word_spec.alternants then for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do				local propval3 = multiword_spec[property] or propval2 for _, word_spec in ipairs(multiword_spec.word_specs) do					local propval4 = word_spec[property] or propval3 if propval4 == "mixed" then error("Attempt to assign mixed " .. property .. " to word") end word_spec[property] = propval4 end end else if propval2 == "mixed" then error("Attempt to assign mixed " .. property .. " to word") end alternant_or_word_spec[property] = propval2 end end end

--[=[ Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows: 1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec. 2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a  multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property (recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of  the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is  `mixed_value` (which is "mixed" gender, but "both" for number). 3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword  spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs. 4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its neighbors. ]=] local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value) propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only") propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false) propagate_properties_downward(alternant_multiword_spec, property, default_propval) end

-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma, -- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma because we don't know -- until later (i.e. when propagate_properties is called) whether an adjectival form in -e is feminine or plural. -- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'. local function determine_adjectival_genders(alternant_multiword_spec) iut.map_word_specs(alternant_multiword_spec, function(base)		if base.props.adj and #base.genders == 0 then			base.genders = 		end	end) end

-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun -- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj -- similarly. If there is a first noun, we use its properties to determine the overall expression's -- properties; otherwise we use the first adjective's properties, otherwise the first word's properties. -- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise -- we use the properties of the first noun (or failing that the first adjective, or failing that the -- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the -- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec, -- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the -- first noun alternant spec. local function determine_noun_status(alternant_multiword_spec) for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do		if alternant_or_word_spec.alternants then local alternant_type for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do				for j, word_spec in ipairs(multiword_spec.word_specs) do					if not word_spec.props.adj then multiword_spec.first_noun = j						alternant_type = "noun" break elseif not multiword_spec.first_adj then multiword_spec.first_adj = j						if not alternant_type then alternant_type = "adj" end end end end if alternant_type == "noun" then alternant_multiword_spec.first_noun = i				return elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then alternant_multiword_spec.first_adj = i			end else if not alternant_or_word_spec.props.adj then alternant_multiword_spec.first_noun = i				return elseif not alternant_multiword_spec.first_adj then alternant_multiword_spec.first_adj = i			end end end end

local function decline_noun_or_adjective(base) if base.props.surname then decline_surname(base) elseif base.props.toponym then decline_toponym(base) elseif base.props.langname then decline_langname(base) elseif base.props.adj then decline_adjective(base) else decline_noun(base) end handle_derived_slots_and_overrides(base) end

-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g. -- 'der und der' for conjoined nouns. local function compute_non_surname_articles(alternant_multiword_spec) if alternant_multiword_spec.number ~= "pl" then iut.map_word_specs(alternant_multiword_spec, function(base)			for _, genderspec in ipairs(base.genders) do				for _, case in ipairs(cases_with_abl_voc) do					for _, def in ipairs(definitenesses) do						iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s", {form = com.articles[genderspec.form][def .. "_" .. case]})					end				end			end		end) end for _, case in ipairs(basic_cases) do		for _, def in ipairs(definitenesses) do iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",				{form = com.articles.p[def .. "_" .. case]}) end end end

-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g. -- 'der und der' for conjoined nouns. local function compute_surname_articles(alternant_multiword_spec) for _, gender in ipairs {"m", "f"} do		for _, case in ipairs(basic_cases) do			for _, def in ipairs(definitenesses) do iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",					{form = "(" .. com.articles[gender][def .. "_" .. case] .. ")"}) end end end for _, case in ipairs(basic_cases) do iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",			{form = "(" .. com.articles.p["def_" .. case] .. ")"}) end end

local function compute_articles(alternant_multiword_spec) if alternant_multiword_spec.props.surname then compute_surname_articles(alternant_multiword_spec) else compute_non_surname_articles(alternant_multiword_spec) end end

-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each -- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an -- adjectival noun). local function map_first_noun(alternant_multiword_spec, fun) local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1 if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry] if alternant_or_word_spec.alternants then for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do				key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1 if #multiword_spec.word_specs >= key_entry then fun(multiword_spec.word_specs[key_entry]) end end else fun(alternant_or_word_spec) end end end

-- Compute the categories to add the noun to, as well as the annotation to display in the -- declension title bar. We combine the code to do these functions as both categories and -- title bar contain similar information. local function compute_categories_and_annotation(alternant_multiword_spec) alternant_multiword_spec.categories = {} alternant_multiword_spec.decl_type = {}

local function insert(cattype) cattype = rsub(cattype, "~", alternant_multiword_spec.pos) m_table.insertIfNot(alternant_multiword_spec.categories, "German " .. cattype) end if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then insert("uncountable ~") elseif alternant_multiword_spec.number == "pl" then insert("pluralia tantum") end local annotation local annparts = {} local genderdescs = {} local decldescs = {}

if alternant_multiword_spec.number == "sg" then table.insert(annparts, "sg-only") elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then -- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers -- onto it. Note that when 'p' is the gender, there can be only one gender. table.insert(annparts, "pl-only") end

for i, genderspec in ipairs(alternant_multiword_spec.genders) do		local genderdesc_parts = {} local gender = genderspec.spec if gender == "p" then table.insert(genderdesc_parts, "pl-only") else gender = rsub(gender, "%-p$", "") table.insert(genderdesc_parts, gender_spec_to_full_gender[gender]) end if genderspec.qualifiers then table.insert(genderdesc_parts, " (")			table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))			table.insert(genderdesc_parts, ")") end table.insert(genderdescs, table.concat(genderdesc_parts)) end

local function insert_decl_type(decl_type) m_table.insertIfNot(decldescs, decl_type) m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type) end

local function do_word_spec(base) if base.props.surname then m_table.insertIfNot(decldescs, "surname") elseif base.props.toponym then m_table.insertIfNot(decldescs, "toponym") elseif base.props.langname then m_table.insertIfNot(decldescs, "langname") elseif base.decl_type and #base.decl_type > 0 then -- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural for _, decl_type in ipairs(base.decl_type) do				if decl_type == "weak" then insert("weak ~") elseif decl_type == "mixed" then insert("mixed ~") end insert_decl_type(decl_type) end elseif base.props.saw_mn then -- For singular-only masculine or neuter nouns, we can still classify as strong or weak. -- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are -- strong (-en is part of the stem), mixed or weak. if base.props.weak then insert("weak ~") insert_decl_type("weak") else insert_decl_type("strong") end end end

-- Use the surname/toponym/langname/weak/strong properties of the noun(s). map_first_noun(alternant_multiword_spec, do_word_spec)

if #genderdescs > 0 then table.insert(annparts, table.concat(genderdescs, " // ")) end if #decldescs > 0 then table.insert(annparts, table.concat(decldescs, " // ")) end if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then insert("adjectival ~") table.insert(annparts, "adjectival") end if alternant_multiword_spec.props.langname then insert("specially-declined language names") end alternant_multiword_spec.annotation = table.concat(annparts, ", ") end

local function compute_headword_genders(alternant_multiword_spec) alternant_multiword_spec.genders = {} -- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations -- because that will cause issues in plural-only expressions like Kanarische Inseln, where Inseln may be -- 'f-p' but Kanarische will be just 'p', and we'd end up with both genders. map_first_noun(alternant_multiword_spec, function(base)		for _, genderspec in ipairs(base.genders) do			-- Create the new spec to insert.			local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}			-- See if the gender of the spec is already present; if so, combine qualifiers.			local saw_existing = false			for _, existing_spec in ipairs(alternant_multiword_spec.genders) do				if existing_spec.spec == spec.spec then					existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)					saw_existing = true					break				end			end			-- If not, add gender.			if not saw_existing then				table.insert(alternant_multiword_spec.genders, spec)			end		end	end) -- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any -- footnote abbreviations. for _, genderspec in ipairs(alternant_multiword_spec.genders) do		if genderspec.qualifiers then local processed_qualifiers = {} for _, qualifier in ipairs(genderspec.qualifiers) do				m_table.insertIfNot(processed_qualifiers,					iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs")) end genderspec.qualifiers = processed_qualifiers end end end

-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in -- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or -- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like -- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma -- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`, -- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a -- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of ordenlicher Professor, -- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English -- description of the form whose specs are being processed, for display in error messages. local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc) -- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the -- syntax `.[footnote]` is used, which attaches a footnote to every form. local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes") lemmas = iut.map_forms(lemmas, function(form)		return rsub(form, "e$", "")	end)

for _, spec in ipairs(arg_specs) do		local function parse_err(msg) error(msg .. ": " .. spec) end local segments = iut.parse_balanced_segment_run(spec, "[", "]") -- Allow comma (preferred) or colon as separator. local ending_specs = com.fetch_specs(iut, segments, "[,:]", desc, nil, parse_err)

-- FIXME, this should propagate the 'ss' property upwards local props = {} local function do_combine_stem_ending(stem, ending) return combine_stem_ending(props, stem, ending) end

local function process(stem, ending) iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending) end

process_spec(ending_specs, nil, default, literal_default, desc, process) end end

local function show_forms(alternant_multiword_spec) local lemmas = export.get_lemmas(alternant_multiword_spec) local props = { lang = lang, lemmas = lemmas, slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles or noun_slot_list_with_linked_and_articles, }	iut.show_forms(alternant_multiword_spec.forms, props) end

local noun_template_both = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! style="background:#AAB8C0;width:15%" | ! colspan="3" style="background:#AAB8C0;width:46%" | singular ! colspan="2" style="background:#AAB8C0;width:39%" | plural ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:7%" | indef. ! style="background:#BBC9D0;width:7%" | def. ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0;width:7%" | def. ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_ind_nom_s}
 * style="background:#EEEEEE" | {art_def_nom_s}
 * {nom_s}
 * style="background:#EEEEEE" | {art_def_nom_p}
 * {nom_p}
 * style="background:#EEEEEE" | {art_ind_gen_s}
 * style="background:#EEEEEE" | {art_def_gen_s}
 * {gen_s}
 * style="background:#EEEEEE" | {art_def_gen_p}
 * {gen_p}
 * style="background:#EEEEEE" | {art_ind_dat_s}
 * style="background:#EEEEEE" | {art_def_dat_s}
 * {dat_s}
 * style="background:#EEEEEE" | {art_def_dat_p}
 * {dat_p}
 * style="background:#EEEEEE" | {art_ind_acc_s}
 * style="background:#EEEEEE" | {art_def_acc_s}
 * {acc_s}
 * style="background:#EEEEEE" | {art_def_acc_p}
 * {acc_p}
 * {\cl}{notes_clause} ]=]

local noun_template_both_no_indef = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! style="background:#AAB8C0;width:15%" | ! colspan="2" style="background:#AAB8C0;width:39%" | singular ! colspan="2" style="background:#AAB8C0;width:39%" | plural ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:7%" | def. ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0;width:7%" | def. ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_def_nom_s}
 * {nom_s}
 * style="background:#EEEEEE" | {art_def_nom_p}
 * {nom_p}
 * style="background:#EEEEEE" | {art_def_gen_s}
 * {gen_s}
 * style="background:#EEEEEE" | {art_def_gen_p}
 * {gen_p}
 * style="background:#EEEEEE" | {art_def_dat_s}
 * {dat_s}
 * style="background:#EEEEEE" | {art_def_dat_p}
 * {dat_p}
 * style="background:#EEEEEE" | {art_def_acc_s}
 * {acc_s}
 * style="background:#EEEEEE" | {art_def_acc_p}
 * {acc_p}
 * {\cl}{notes_clause} ]=]

local noun_template_abl_voc = [=[

! style="background:#BBC9D0" | ablative ! style="background:#BBC9D0" | vocative
 * style="background:#EEEEEE" | {art_ind_abl_s}
 * style="background:#EEEEEE" | {art_def_abl_s}
 * {abl_s}
 * style="background:#EEEEEE" | {art_ind_voc_s}
 * style="background:#EEEEEE" | {art_def_voc_s}
 * {voc_s}]=]

local noun_template_sg = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! style="background:#AAB8C0;width:24.6%" | ! colspan="3" style="background:#AAB8C0;" | singular ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:11.5%" | indef. ! style="background:#BBC9D0;width:11.5%" | def. ! style="background:#BBC9D0;width:52.5%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_ind_nom_s}
 * style="background:#EEEEEE" | {art_def_nom_s}
 * {nom_s}
 * style="background:#EEEEEE" | {art_ind_gen_s}
 * style="background:#EEEEEE" | {art_def_gen_s}
 * {gen_s}
 * style="background:#EEEEEE" | {art_ind_dat_s}
 * style="background:#EEEEEE" | {art_def_dat_s}
 * {dat_s}
 * style="background:#EEEEEE" | {art_ind_acc_s}
 * style="background:#EEEEEE" | {art_def_acc_s}
 * {acc_s}{abl_voc_clause}
 * {\cl}{notes_clause} ]=]

local noun_template_sg_no_indef = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! style="background:#AAB8C0;width:24.6%" | ! colspan="2" style="background:#AAB8C0;" | singular ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:11.5%" | def. ! style="background:#BBC9D0;width:52.5%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_def_nom_s}
 * {nom_s}
 * style="background:#EEEEEE" | {art_def_gen_s}
 * {gen_s}
 * style="background:#EEEEEE" | {art_def_dat_s}
 * {dat_s}
 * style="background:#EEEEEE" | {art_def_acc_s}
 * {acc_s}{abl_voc_clause}
 * {\cl}{notes_clause} ]=]

local noun_template_pl = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! style="background:#AAB8C0;width:24.6%" | ! colspan="2" style="background:#AAB8C0;" | plural ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:11.5%" | def. ! style="background:#BBC9D0;width:52.5%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_def_nom_p}
 * {nom_p}
 * style="background:#EEEEEE" | {art_def_gen_p}
 * {gen_p}
 * style="background:#EEEEEE" | {art_def_dat_p}
 * {dat_p}
 * style="background:#EEEEEE" | {art_def_acc_p}
 * {acc_p}
 * {\cl}{notes_clause} ]=]

local noun_template_surname = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}" ! rowspan="2" style="background:#AAB8C0;width:11%" | ! colspan="6" style="background:#AAB8C0" | singular ! colspan="2" rowspan="2" style="background:#AAB8C0" | plural ! colspan="3" style="background:#AAB8C0" | masculine ! colspan="3" style="background:#AAB8C0" | feminine ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:4%" | indef. ! style="background:#BBC9D0;width:4%" | def. ! style="background:#BBC9D0;width:23%" | noun ! style="background:#BBC9D0;width:4%" | indef. ! style="background:#BBC9D0;width:4%" | def. ! style="background:#BBC9D0;width:23%" | noun ! style="background:#BBC9D0;width:4%" | def. ! style="background:#BBC9D0;width:23%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | {art_ind_nom_m_s}
 * style="background:#EEEEEE" | {art_def_nom_m_s}
 * {nom_m_s}
 * style="background:#EEEEEE" | {art_ind_nom_f_s}
 * style="background:#EEEEEE" | {art_def_nom_f_s}
 * {nom_f_s}
 * style="background:#EEEEEE" | {art_def_nom_p}
 * {nom_p}
 * style="background:#EEEEEE" | {art_ind_gen_m_s}
 * style="background:#EEEEEE" | {art_def_gen_m_s}
 * {gen_m_s}
 * style="background:#EEEEEE" | {art_ind_gen_f_s}
 * style="background:#EEEEEE" | {art_def_gen_f_s}
 * {gen_f_s}
 * style="background:#EEEEEE" | {art_def_gen_p}
 * {gen_p}
 * style="background:#EEEEEE" | {art_ind_dat_m_s}
 * style="background:#EEEEEE" | {art_def_dat_m_s}
 * {dat_m_s}
 * style="background:#EEEEEE" | {art_ind_dat_f_s}
 * style="background:#EEEEEE" | {art_def_dat_f_s}
 * {dat_f_s}
 * style="background:#EEEEEE" | {art_def_dat_p}
 * {dat_p}
 * style="background:#EEEEEE" | {art_ind_acc_m_s}
 * style="background:#EEEEEE" | {art_def_acc_m_s}
 * {acc_m_s}
 * style="background:#EEEEEE" | {art_ind_acc_f_s}
 * style="background:#EEEEEE" | {art_def_acc_f_s}
 * {acc_f_s}
 * style="background:#EEEEEE" | {art_def_acc_p}
 * {acc_p}
 * {\cl}{notes_clause} ]=]

local noun_template_langname = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname" ! style="background:#AAB8C0;width:15%" | ! colspan="5" style="background:#AAB8C0;width:85%" | singular  (explanation of the use and meaning of the forms) ! style="background:#BBC9D0" | ! style="background:#BBC9D0;width:14%" | (usually without article) ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0;width:7%" | def. ! style="background:#BBC9D0;width:32%" | noun ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * style="background:#EEEEEE" | ({art_def_nom_s})
 * {nom_s}
 * style="background:#EEEEEE" | {art_def_nom_s}
 * {nom_s_alt}
 * style="background:#EEEEEE" | ({art_def_gen_s})
 * {gen_s}
 * style="background:#EEEEEE" | {art_def_gen_s}
 * {gen_s_alt}
 * style="background:#EEEEEE" | ({art_def_dat_s})
 * {dat_s}
 * style="background:#EEEEEE" | {art_def_dat_s}
 * {dat_s_alt}
 * style="background:#EEEEEE" | ({art_def_acc_s})
 * {acc_s}
 * style="background:#EEEEEE" | {art_def_acc_s}
 * {acc_s_alt}
 * {\cl}{notes_clause} ]=]

local adjectival_template_both = [=[ {title}{annotation} {\op}| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table" ! style="background:#BBC9D0;width:15%" | ! colspan="2" style="background:#BBC9D0" | singular ! colspan="2" style="background:#BBC9D0" | plural ! style="background:#AAB8C0" | {gender} ! colspan="4" style="background:#AAB8C0" | strong declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative ! style="background:#AAB8C0" | ! colspan="4" style="background:#AAB8C0" | weak declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative ! style="background:#AAB8C0" | ! colspan="4" style="background:#AAB8C0" | mixed declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * colspan="2" | {str_nom_s}
 * colspan="2" | {str_nom_p}
 * colspan="2" | {str_gen_s}
 * colspan="2" | {str_gen_p}
 * colspan="2" | {str_dat_s}
 * colspan="2" | {str_dat_p}
 * colspan="2" | {str_acc_s}
 * colspan="2" | {str_acc_p}
 * style="background:#EEEEEE;width:5em" | {art_def_nom_s}
 * {wk_nom_s}
 * style="background:#EEEEEE;width:5em" | {art_def_nom_p}
 * {wk_nom_p}
 * style="background:#EEEEEE;width:5em" | {art_def_gen_s}
 * {wk_gen_s}
 * style="background:#EEEEEE;width:5em" | {art_def_gen_p}
 * {wk_gen_p}
 * style="background:#EEEEEE;width:5em" | {art_def_dat_s}
 * {wk_dat_s}
 * style="background:#EEEEEE;width:5em" | {art_def_dat_p}
 * {wk_dat_p}
 * style="background:#EEEEEE;width:5em" | {art_def_acc_s}
 * {wk_acc_s}
 * style="background:#EEEEEE;width:5em" | {art_def_acc_p}
 * {wk_acc_p}
 * style="background:#EEEEEE;width:5em" | {art_ind_nom_s}
 * {mix_nom_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_nom_p}
 * {mix_nom_p}
 * style="background:#EEEEEE;width:5em" | {art_ind_gen_s}
 * {mix_gen_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_gen_p}
 * {mix_gen_p}
 * style="background:#EEEEEE;width:5em" | {art_ind_dat_s}
 * {mix_dat_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_dat_p}
 * {mix_dat_p}
 * style="background:#EEEEEE;width:5em" | {art_ind_acc_s}
 * {mix_acc_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_acc_p}
 * {mix_acc_p}
 * {\cl}{notes_clause} ]=]

local adjectival_template_sg = [=[ {title}{annotation} {| border="1px solid #505050" style="border-collapse:collapse; background:#FAFAFA; text-align:center; width:100%" class="inflection-table" ! style="background:#BBC9D0;width:15%" | ! colspan="2" style="background:#BBC9D0" | singular ! style="background:#AAB8C0" | {gender} ! colspan="2" style="background:#AAB8C0" | strong declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative ! style="background:#AAB8C0" | ! colspan="2" style="background:#AAB8C0" | weak declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative ! style="background:#AAB8C0" | ! colspan="2" style="background:#AAB8C0" | mixed declension ! style="background:#BBC9D0" | nominative ! style="background:#BBC9D0" | genitive ! style="background:#BBC9D0" | dative ! style="background:#BBC9D0" | accusative
 * colspan="2" | {str_nom_s}
 * colspan="2" | {str_gen_s}
 * colspan="2" | {str_dat_s}
 * colspan="2" | {str_acc_s}
 * style="background:#EEEEEE;width:5em" | {art_def_nom_s}
 * {wk_nom_s}
 * style="background:#EEEEEE;width:5em" | {art_def_gen_s}
 * {wk_gen_s}
 * style="background:#EEEEEE;width:5em" | {art_def_dat_s}
 * {wk_dat_s}
 * style="background:#EEEEEE;width:5em" | {art_def_acc_s}
 * {wk_acc_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_nom_s}
 * {mix_nom_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_gen_s}
 * {mix_gen_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_dat_s}
 * {mix_dat_s}
 * style="background:#EEEEEE;width:5em" | {art_ind_acc_s}
 * {mix_acc_s}
 * {\cl}{notes_clause} ]=]

local notes_template = [===[ {footnote} ]===]

local function make_table(alternant_multiword_spec) local forms = alternant_multiword_spec.forms

if alternant_multiword_spec.title then forms.title = alternant_multiword_spec.title else forms.title = 'Declension of ' .. forms.lemma .. '' end

local annotation = alternant_multiword_spec.annotation if annotation == "" then forms.annotation = "" else forms.annotation = " [" .. annotation .. " ]"	end

local table_spec if alternant_multiword_spec.props.surname then table_spec = noun_template_surname elseif alternant_multiword_spec.props.langname then table_spec = noun_template_langname elseif alternant_multiword_spec.props.overall_adj then table_spec = alternant_multiword_spec.number == "sg" and adjectival_template_sg or			alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or			adjectival_template_both if alternant_multiword_spec.number == "pl" then forms.gender = "" else local genderdesc_parts = {} for _, gender in ipairs(alternant_multiword_spec.genders) do				table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec]) end forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''" end else local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article table_spec = alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or			alternant_multiword_spec.number == "pl" and noun_template_pl or			(no_indef and noun_template_both_no_indef or noun_template_both) if forms.abl_s ~= "—" or forms.voc_s ~= "—" then forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms) else forms.abl_voc_clause = "" end end forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or "" return m_string_utilities.format(table_spec, forms) end

-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is -- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot. -- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects -- {form=FORM, footnotes=FOOTNOTES}. function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def) local params = { [1] = {required = true, default = "Haus"}, pagename = {}, }

if from_headword or pretend_from_headword then params["head"] = {list = true} params["f"] = {list = true} params["m"] = {list = true} params["n"] = {list = true} params["dim"] = {list = true} params["sg"] = {list = true} params["id"] = {} params["sort"] = {} params["splithyph"] = {type = "boolean"} params["nolinkhead"] = {type = "boolean"} end

local args = require("Module:parameters").process(parent_args, params)

local arg1 = args[1] local need_surrounding_angle_brackets = true -- Check whether we need to add <...> around the argument. If the -- argument has no < in it, we definitely do. Otherwise, we need to	-- parse the balanced [...] and <...> and add <...> only if there isn't	-- a top-level <...>. We check for [...] because there might be angle -- brackets inside of them (HTML tags in qualifiers or <> and	-- such in references). if arg1:find("<") then local segments = iut.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}}) for i = 2, #segments, 2 do			if segments[i]:find("^<.*>$") then need_surrounding_angle_brackets = false break end end end if need_surrounding_angle_brackets then arg1 = "<" .. arg1 .. ">"	end

local pagename = args.pagename or mw.title.getCurrentTitle.text

local function do_parse_indicator_spec(angle_bracket_spec, lemma) return parse_indicator_spec(angle_bracket_spec, lemma, pagename) end

local parse_props = { parse_indicator_spec = do_parse_indicator_spec, allow_default_indicator = true, allow_blank_lemma = true, }	local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props) alternant_multiword_spec.args = args alternant_multiword_spec.props = {} alternant_multiword_spec.props.is_proper = is_proper detect_all_indicator_specs(alternant_multiword_spec) local default_number = (alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both" propagate_properties(alternant_multiword_spec, "number", default_number, "both") -- FIXME, maybe should check that noun genders match adjective genders determine_adjectival_genders(alternant_multiword_spec) determine_noun_status(alternant_multiword_spec) local inflect_props = { skip_slot = function(slot) return skip_slot(alternant_multiword_spec.number, slot) end, slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked or alternant_multiword_spec.props.langname and langname_slot_list_with_linked or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or noun_slot_list_with_linked, inflect_word_spec = decline_noun_or_adjective, }	iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) compute_articles(alternant_multiword_spec) compute_headword_genders(alternant_multiword_spec) if not pos then -- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen		-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen, -- it's a suffix, else a noun (proper nouns get categorized like nouns). local lemmas = export.get_lemmas(alternant_multiword_spec) local first_lemma = #lemmas > 0 and lemmas[1].form or pagename pos = rfind(first_lemma, "^%-") and "suffixes" or "nouns" end alternant_multiword_spec.pos = pos compute_categories_and_annotation(alternant_multiword_spec) if from_headword or pretend_from_headword then process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive") process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,			"literal default", "f", "feminine equivalent") process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,			"literal default", "m", "masculine equivalent") process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,			"literal default", "n", "neuter equivalent") process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular") end return alternant_multiword_spec end

-- Entry point for. Template-callable function to parse and decline a noun given -- user-specified arguments and generate a displayable table of the declined forms. function export.show(frame) local parent_args = frame:getParent.args local alternant_multiword_spec = export.do_generate_forms(parent_args) show_forms(alternant_multiword_spec) -- FIXME! alternant_multiword_spec.forms.decl_type = "foo" return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(		alternant_multiword_spec.categories, lang, nil, nil, force_cat) end

-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...". -- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also -- include additional properties (currently, g= for headword genders). This is for use by bots. local function concat_forms(alternant_multiword_spec, include_props) local ins_text = {} for _, slotaccel in ipairs(		alternant_multiword_spec.props.surname and surname_slot_list_with_linked or		alternant_multiword_spec.props.langname and langname_slot_list_with_linked or		alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or		noun_slot_list_with_linked	) do		local slot, accel = unpack(slotaccel) local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot]) if formtext then table.insert(ins_text, slot .. "=" .. formtext) end end if include_props then table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ",")) end return table.concat(ins_text, "|") end

-- Template-callable function to parse and decline a noun given user-specified arguments and return -- the forms as a string of the same form as documented in concat_forms above. function export.generate_forms(frame) local include_props = frame.args["include_props"] local parent_args = frame:getParent.args local alternant_multiword_spec = export.do_generate_forms(parent_args) return concat_forms(alternant_multiword_spec, include_props) end

return export

title: Module:de-noun


text: Template:de-ndecl

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: Template:de-ndecl


text: feels like oneself

title: feels like oneself


text:
Template:de-ndecl/documentation

Introduction
This template should be used to decline all German nouns and proper noun, in preference to any other, older template that may still exist. (Eventually these will all be eliminated.)

Masculine and neuter nouns
Generally, a single argument is supplied to the template, which specifies the gender and optionally the genitive singular and/or plural. For example, for the noun, use:

which produces

Here,  specifies the gender,   the genitive singular ending, and   the plural ending. Note that the module is smart enough to add -n onto the dative plural automatically.

Sensible defaults are provided for the genitive singular and plural. In this case, the default genitive singular for most nouns, including, adds an -s, and the default plural adds an -e, so both the genitive singular and plural could be omitted:

which has the same result as above.

If there is more than one possibility for a given ending, separate the possibilities with a colon, as with :

which produces

Because genitive singulars in either -es or -s are so common, a shortcut  is provided. Along with the default plural, the above could be equivalently written:

Other such shortcuts are  (either -s or no ending) and   (either -es or no ending).

Use  to specify a null ending, e.g. for, plural Mädchen:

which produces

Feminine nouns
Feminine nouns normally have a null ending in the genitive singular. As a result, the syntax for feminine nouns omits the genitive singular and specifies only the plural, as for, plural Ordnungen:

which produces

Feminine nouns default to the plural -en (or just -n after e), so this could equivalently be written:

Umlaut
To include umlaut, precede the ending with. For example, for, with plural Häuser, use the following:

which produces

The module knows the correct rules for umlaut, e.g. umlauts in the plural as Äpfel:

which produces

Since -s is the default genitive ending in most cases, this could equivalently be written:

Weak nouns
Additional modifiers beyond the gender, genitive singular and plural are known as indicators. These are specified following a period. One common indicator is, indicating a weak noun, e.g. :

an which produces

The code will automatically add -n in place of -en if the noun ends in -e. However, if the noun has -n in place of -en after a consonant, as with, , and their compounds, use. For example, one of the declensions of could be indicated as follows:

which produces

If the noun has -n in the singular but -en in the plural, as is typical for and its compounds, specify the plural explicitly, as follows:

which produces

For nouns with multiple possible declensions, e.g. weak or strong, use the alternant notation, as described below. For example,, which can be declined either strong or weak, might be indicated as follows:

which produces

The general syntax here is to surround each declension with angle brackets, separate them with commas and put double parens around the whole thing. More than two alternants are possible; e.g. for, which can be either strong, weak with genitive in -n or weak with genitive in -en, use the following:

which produces

In this case, the plural is always in -n, so the alternants that would by default produce other plurals must have the plural given explicitly.

Additional indicators
Besides  and , other supported indicators are as follows:
 * : singular-only
 * : indicate that the term is normally used with the definite article
 * : don't add -n onto the dative plural when it normally would be added
 * : change -ß to -ss before an ending beginning with a vowel (as is common in pre-1996 spellings)
 * : include dative variant in -e with footnote even if no genitive with -e- exists; see below

Examples:

1.  for singular-only, e.g. :

which produces

2.  for nouns normally used with the definite article, e.g. :

which produces

This indicator is especially useful in the headword template, e.g.:

which produces

3.  to suppress the final -n in the dative plural after a final -e, -er or -el, e.g. :

which produces

4.  to indicate that a final -ß changes to -ss before an ending beginning with a vowel (for pre-1996 spellings), e.g.  (superseded spelling):

which produces

5.  to explicitly include the dative variant in -e with footnote even if no genitive with -e- exists, e.g. for :

which produces

Note that by default the variant in -e with associated footnote appears whenever a genitive form includes an -e- in it (genitive is specified as,   or  ). To suppress its appearance, as in recently-coined words, use the override  (see Overrides below).

Irregular genitives and plurals
If the genitive or plural are sufficiently irregular, they cannot be specified using an ending and/or the use of  to indicate umlaut. In those cases, specify the full form, e.g. for with plural Vakua or Vakuen:

which produces

Note that the default plural of neuter nouns in -um changes the -um to -en (see below), so the following would equivalently work:

Here,  explicitly requests the default.

A full form is recognized as such by beginning with a capital letter. In the rare case where a full form must be given and begins with a lowercase letter, precede the full form with. For example, for (alternative letter-case form of ), use:

which produces

Angle-bracket notation
An alternative notation is available, which specifies the lemma explicitly along with the declension. E.g. for, the following could be used:

Since the lemma here is the same as lemma attached to the angle brackets, it can be omitted:

Both notations are equivalent to the following:

For single-word terms, angle brackets aren't usually needed, but they become necessary with multiword expressions and alternants; see below.

Default genitive and plural algorithms
The following algorithm produces the default genitive singular:
 * 1) If the noun is feminine, use a null ending.
 * 2) Otherwise, if the noun is weak, use -n after -e, -nen after consonant + -in, and otherwise -en.
 * 3) Otherwise, if the noun ends in -nis (neuter like, , etc. or occasional masculine like ), use -ses.
 * 4) Otherwise, if the noun ends in a consonant + -us, use a null ending, as in, , , etc.
 * 5) Otherwise, if the noun ends in s/ß/x/z, use -es.
 * 6) Otherwise, use -s.

The following algorithm produces the default plural:
 * 1) If the noun ends in -nis (neuter like  or, feminine like  or , or occasional masculine like ), use -se.
 * 2) Otherwise, if the noun is feminine or weak, use -n after -e, -nen after consonant + -in, and otherwise -en.
 * 3) Otherwise, if the noun ends in -e, use -n.
 * 4) Otherwise, if the noun is neuter and ends in -lein, use a null ending.
 * 5) Otherwise, if the noun is neuter and ends in -um (e.g.  or ), replace the -um with -en.
 * 6) Otherwise, if the noun ends in -mus (e.g.  or ), replace the -mus with -men.
 * 7) Otherwise, if the noun ends in a consonant + -us (e.g., , ), use -se.
 * 8) Otherwise, if the noun ends in -el, -em, -en or -er (e.g., , ), use a null ending. (But this does not apply to nouns in a consonant + -eer/-ier, -eel/-iel, etc., as in , , , which default to -e as below.)
 * 9) Otherwise, use -e.

Nouns with multiple genders
If a noun has more than one possible gender, separate the genders with a colon, e.g. :

which produces

You can also place a footnote/qualifier in brackets after a given gender. For example, is neuter mainly in Austria; to note this, use the following:

Gender qualifiers do not appear in the declension table, but they do appear in the headword, which is specified like this:

which produces

Plural-only nouns
To specify a plural-only noun, use  in place of the gender, e.g. for :

which produces

With plural-only nouns, you cannot specify a genitive or plural form, and if you do so, an error will result.

Overrides
You can override a particular case/number combination using the form, where   specifies the particular slot to override, e.g.   for accusative singular,   for dative plural. For example, for the noun, whose plural is Häusle and whose dative plural can be either Häuslen or Häusle, use the following:

which produces

Another use of overrides is specifying a distinct genitive for feminine nouns. An example is, which has an alternative Latinate genitive singular Quinquagesimä, used mostly when no article is present. Specify as follows:

which produces

Here, we specify a footnote in brackets, as described in the Footnotes section above. For another example of using a footnote with an override, see the declension of below.

Recognized slot names are as follows:

The ablative and vocative cases are used only in certain terms with special Latinate declensions, e.g..

Defective forms
If a given form is missing entirely, use  to indicate this. An example is, which is missing the genitive singular. Indicate as follows:

which produces

When used in the headword, it displays as follows:

However, for nouns without a plural form,  should be used instead of.

Embedded commas and periods
If you need to include a form that contains an embedded comma or period, precede the comma or period with a backslash. For example, for (abbreviation of ), with plural either Vf. or Vff., use the following:

which produces

Multiword expressions
To decline a multiword expression, include the text of the expression in 1 and put the spec for each word after the word, surrounded by angle brackets. For example, for :

which produces

Another example, for :

which produces

It is not necessary to surround each word with brackets, but when used in it ensures that the words are individually linked in the headword.

Arbitrary specs can be included inside of angle brackets, e.g. for :

which produces

For singular-only nouns, include the indicator  inside the angle brackets, as for :

which produces

Any number of declined components can be included, and will be handled correctly. An example with three is :

which produces

Adjectival nouns and adjective-noun combinations
Some nouns are declined like adjectives. An example is (definite nominative der Erwachsene, indefinite nominative ein Erwachsener, definitive genitive des Erwachsenen, bare plural Erwachsene, definite plural die Erwachsenen, etc.). To indicate this, put a  in place of the declension:

which produces

The headword appears as follows:

Note how the declension table includes strong (i.e. bare), weak (i.e. definite) and mixed (i.e. indefinite) forms, and the headword includes both bare and definite versions of the nominative singular, genitive singular and nominative plural. For masculine and neuter nouns like this, the bare and definite genitive have the same ending and so the headword inflection combines the two, but for feminine nouns, they will be split. An example is :

which produces

The headword appears as follows:

You can likewise decline adjective-noun combinations using, e.g. :

which produces

The headword appears as follows:

Here, the alternative notation using angle brackets must be used to indicate the declensions of the individual words. Links must be included in order for there to be links to individual words in the headword.

Note that the gender does not need to be specified in conjunction with, because it can automatically be inferred from the ending. When used in conjunction with a noun, the plural status of the adjective does not need to be given either, as with :

which produces

The headword appears as follows:

However, this won't work for a plural-only adjectival noun, because the -e ending will be inferred as feminine singular. If for some reason you need to specify such a noun, use  or , e.g. for :

which produces

The headword appears as follows:

Alternants
Sometimes a given expression has multiple possible declensions, in a way that can't easily be specified using the available possibilities for specifying multiple genders or alternative genitive or plural endings. For example, some nouns can be declined either strong or weak, and in some multiword expressions, one word may or may not be declined. An example is, normally strong but sometimes weak (especially in Southern Germany and Austria). To indicate this, use a syntax like this:  where each alternant must have angle brackets in it:

which produces

Here the first alternant is strong while the second is weak and includes an entire-declension footnote (see Footnotes above). The headword appears as follows:

Another example is, where lüttje (a Low German word) may or may not be inflected as a normal adjective:

which produces

The headword appears as follows:

Note that both the declension and headword use the adjectival form even though only one of the two alternants has an adjective in it. This is also an example where we purposely avoid linking one of the components, since lüttje by itself is not a German word.

title: Template:de-ndecl/documentation


text: feeling like oneself

title: feeling like oneself


text: felt like oneself

title: felt like oneself


text:
vulgarisme

Noun

 * 1) vulgarism

title: vulgarisme


text:
cathétérisme

Noun

 * 1) catheterism

title: cathétérisme


text:
catégoricité

Noun

 * 1) categoricity

title: catégoricité


text:
Talk:사포

RFV discussion: January 2022
Jeju "사포", apparently of French origin, but I'm not seeing it in 우리말샘, 제주어 사전, Jejueo.com, run by the Jeju Preservation Society, or in any of the Jeju resources that I'm familiar with. AG202 (talk) 04:38, 5 January 2022 (UTC)
 * —Fish bowl (talk) 07:02, 6 January 2022 (UTC)

Nevermind it's cited in the 제주 방언 사전 which I completely forgot to check, so I'm closing this RFV, though I'd still like to see if it's in any other resources. AG202 (talk) 21:09, 19 January 2022 (UTC)

title: Talk:사포


text:
catégorème

Noun

 * 1) categorem

title: catégorème


text:
mesmérisme

Noun

 * 1) mesmerism

title: mesmérisme


text:
mésocéphale

Etymology
From.

Adjective

 * 1) mesocephalous

title: mésocéphale


text:
mésozoïque

Adjective

 * 1) Mesozoic

title: mésozoïque


text: kupumbaza

title: kupumbaza


text:
fakirisme

Noun

 * 1) fakirism

title: fakirisme


text: kupumbaa

title: kupumbaa


text:
contre-terrorisme

Noun

 * 1) counter-terrorism

title: contre-terrorisme


text:
contre-terroriste

Noun

 * 1) counter-terrorist

title: contre-terroriste


text:
gongorisme

Noun

 * 1) gongorism

title: gongorisme


text:
historisme

Noun

 * 1) historism

title: historisme


text:
humorisme

Noun

 * 1) humorism

title: humorisme


text: 步樣

title: 步樣


text: Category:sei:Ducks

title: Category:sei:Ducks


text: Category:sei:Poultry

title: Category:sei:Poultry


text: Category:sei:Anatids

title: Category:sei:Anatids


text: assythement

title: assythement


text: Category:sei:Freshwater birds

title: Category:sei:Freshwater birds


text: Category:sei:Livestock

title: Category:sei:Livestock


text:
lettrisme

Noun

 * 1) Letterism

title: lettrisme


text: Category:sei:Agriculture

title: Category:sei:Agriculture


text:
phallocentrisme

Noun

 * 1) phallocentrism

title: phallocentrisme


text: Category:sei:Applied sciences

title: Category:sei:Applied sciences


text:
tantrisme

Noun

 * 1) tantrism

title: tantrisme


text:
théocentrisme

Etymology
From.

Noun

 * 1) theocentricism

title: théocentrisme


text: assythements

title: assythements


text: assithments

title: assithments


text:
Reconstruction:Proto-Mongolic/ebkere-

Etymology
From 🇨🇬.

Verb

 * 1) to roll

Descendants

 * Khalkha:
 * Khalkha:

title: Reconstruction:Proto-Mongolic/ebkere-


text:
tellurisme

Noun

 * 1) tellurism

title: tellurisme


text:
molinosisme

Noun

 * 1) Molinosism

title: molinosisme


text:
moliéresque

Etymology
From.

Adjective

 * 1) Molieresque

title: moliéresque


text:
거래소

Etymology
.

Noun

 * 1) exchange

title: 거래소


text:
parsisme

Noun

 * 1) Parsism

title: parsisme


text:
partageable

Adjective

 * 1) sharable

title: partageable


text:
pilocarpe

Noun

 * 1) pilocarp

title: pilocarpe


text:
tagnokto

Etymology
🇰🇲.

Noun

 * 1) nychthemeron, one day and one night, 24 hours

title: tagnokto


text:
ololufẹ

Etymology
From.

Noun

 * 1) lover, loved one
 * 2) fan

title: ololufẹ


text:
euphuisme

Noun

 * 1) euphuism

title: euphuisme


text:
médiévisme

Noun

 * 1) medievialsm

title: médiévisme


text:
trezorejo

Etymology
.

Noun

 * 1) treasury vault, treasury chamber

title: trezorejo


text:
nativisme

Noun

 * 1) nativism

title: nativisme


text:
national-socialiste

Noun

 * 1) National Socialist

title: national-socialiste


text:
néopositivisme

Noun

 * 1) neopositivism

title: néopositivisme


text:
néopositiviste

Noun

 * 1) neopositivist

title: néopositiviste


text:
néo-positivisme

Noun

 * 1) neopositivism

title: néo-positivisme


text:
néo-positiviste

Noun

 * 1) neopositivist

title: néo-positiviste


text:
néo-réalisme

Noun

 * 1) neorealism

title: néo-réalisme


text: Citations:tube site

title: Citations:tube site


text:
néo-réaliste

Noun

 * 1) neorealist

title: néo-réaliste


text:
objectivisme

Noun

 * 1) objectivism

Noun

 * 1) objectivism

title: objectivisme


text:
médico-social

Adjective

 * 1) medicosocial

title: médico-social


text:
médico-légal

Adjective

 * 1) medicolegal

title: médico-légal


text:
ayanfẹ

Etymology
From

Noun

 * 1)  lover, chosen one

title: ayanfẹ


text:
ἀροτρίασις

Etymology
From.

Noun

 * 1) ploughing

title: ἀροτρίασις


text: אָבלאַסטן

title: אָבלאַסטן


text:
tự lập

Etymology
.

title: tự lập


text:
aridunnu

Etymology
From.

Noun

 * 1)  lover

title: aridunnu


text: Streets

title: Streets


text:
φορεῖον

Etymology
.

Noun

 * 1) sedan chair
 * 2) sack

title: φορεῖον


text:
ẹni ti ọkan mi yan

Etymology
From.

Noun

 * 1)  lover, sweetheart

title: ẹni ti ọkan mi yan


text:
studentenjob

Etymology
🇰🇲

Noun

 * 1) student job

title: studentenjob


text:
memodifikasi

Etymology
Affixed.

Verb

 * 1) to modify

title: memodifikasi


text: عَِنِ تِ وَْكَن مِ يَن

title: عَِنِ تِ وَْكَن مِ يَن


text: وْلوْلُفعَِ

title: وْلوْلُفعَِ


text: ايَنفعَِ

title: ايَنفعَِ


text: ぬるま湯

title: ぬるま湯


text:
ぬるまゆ

Noun

 * 1) lukewarm water
 * 2)  dull life

title: ぬるまゆ


text:
থালা

Etymology
Related to and ; all of them are from, from ,. Cognate of 🇨🇬,, 🇨🇬, , 🇨🇬 / ,  / ,  / , 🇨🇬 / ,  / , 🇨🇬 / ,  / , 🇨🇬, , 🇨🇬 / ,  /.

Noun

 * 1) plate

title: থালা


text:
lode oni

Etymology
From.

Adverb

 * 1) nowadays

title: lode oni


text:
BI-EE

Etymology
.

Noun

 * 1) Bachelor of Arts (B.A.) degree

title: BI-EE


text: tàiyángxué

title: tàiyángxué


text: tàiyángxuè

title: tàiyángxuè


text: Category:yo:Academic degrees

title: Category:yo:Academic degrees


text:
BI-ẸẸDI

Etymology
.

Noun

 * 1) Bachelor of Education (B.Ed.) degree

title: BI-ẸẸDI


text:
妝娘

Noun

 * 1)  girl who does someone else's makeup

title: 妝娘


title: 800


text:
porta-rolos

Etymology
From.

Noun

 * 1) toilet roll holder
 * 2)  paper towel holder,  kitchen roll holder
 * 1)  paper towel holder,  kitchen roll holder

title: porta-rolos


text:
浪費家

Etymology
From.

Noun

 * 1) squanderer

title: 浪費家


text:
いせまいり

Etymology
From.

Noun

 * 1) visiting

title: いせまいり


text:
người quen

Etymology
.

Noun

 * 1) an acquaintance

title: người quen


text:
年始

Noun

 * 1) beginning of a new year

title: 年始


text: 嘘くさい

title: 嘘くさい


text:
うそくさい

Etymology
From.

Adjective

 * 1) suspicious-sounding

title: うそくさい


text: Template:R:moh:MSD

title: Template:R:moh:MSD


text: 嘘臭い

title: 嘘臭い


text: 伊勢参り

title: 伊勢参り


text:
ブザービーター

Etymology
From.

Noun

 * 1)  buzzer beater

title: ブザービーター


text:
スリーポイントシュート

Etymology
, derived from.

Noun

 * 1)  three-point shot

title: スリーポイントシュート