text:
Module:de-noun/sandbox

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. 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. ]=]

local lang = require("Module:languages").getByCode("de") 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 = true -- may be set during debugging local force_cat = false -- may be set during debugging

local u = mw.ustring.char local rsplit = mw.text.split local rfind = mw.ustring.find local rmatch = mw.ustring.match local rgmatch = mw.ustring.gmatch local rsubn = mw.ustring.gsub local ulen = mw.ustring.len local usub = mw.ustring.sub local uupper = mw.ustring.upper local ulower = mw.ustring.lower

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

local archaic_dative_note = "[now uncommon, 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

-- version of rsubn that returns a 2nd argument boolean indicating whether -- a substitution was made. local function rsubb(term, foo, bar) local retval, nsubs = rsubn(term, foo, bar) return retval, nsubs > 0 end

local noun_slots = { nom_s = "nom|s", gen_s = "gen|s", dat_s = "dat|s", acc_s = "acc|s", abl_s = "abl|s", voc_s = "voc|s", nom_p = "nom|p", gen_p = "gen|p", dat_p = "dat|p", acc_p = "acc|p", }

local noun_slots_with_linked = m_table.shallowcopy(noun_slots) noun_slots_with_linked["nom_s_linked"] = "nom|s" noun_slots_with_linked["nom_p_linked"] = "nom|p"

local cases = { nom = true, gen = true, dat = true, acc = true, abl = true, voc = true, }

local noun_slots_with_linked_and_articles = m_table.shallowcopy(noun_slots_with_linked) for case, _ in pairs(cases) do noun_slots_with_linked_and_articles["art_ind_" .. case .. "_s"] = "-" noun_slots_with_linked_and_articles["art_def_" .. case .. "_s"] = "-" noun_slots_with_linked_and_articles["art_def_" .. case .. "_p"] = "-" 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

local function add(base, slot, stem, ending, 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 return retval end

footnotes = iut.combine_footnotes(base.footnotes, footnotes) local ending_obj = iut.combine_form_and_footnotes(ending, footnotes) iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending) end

local function process_spec(endings, default, footnotes, 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. error("Form '+' found for " .. desc .. " but no default is available") end process_spec(iut.convert_to_general_list_form(default, ending.footnotes), nil, footnotes, desc, process) else local full_eform if 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

local function add_spec(base, slot, endings, default, footnotes, process_combined_stem_ending) local function do_add(stem, ending) add(base, slot, stem, ending, footnotes, process_combined_stem_ending) end process_spec(endings, default, footnotes, "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 add_spec(base, slot, overrides, origforms) end end

local function add_dative_plural(base, specs, def_pl) local function process_combined_stem_ending(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, "dat_p", specs, def_pl, nil, process_combined_stem_ending) end

local function add_archaic_dative_singular(base, 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" end if dat_ending then add(base, "dat_s", nil, dat_ending, iut.combine_footnotes(ending.footnotes, {archaic_dative_note})) end end end

local function get_n_ending(stem) if rfind(stem, "e$") or 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 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.lemma) 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 or rfind(base.lemma, "e$") then return get_n_ending(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_plural(base, def_pl) add_spec(base, "nom_p", base.pls, def_pl) add_spec(base, "gen_p", base.pls, def_pl) add_dative_plural(base, base.pls, def_pl) add_spec(base, "acc_p", base.pls, def_pl) end

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

local function decline(base) if base.number == "pl" then decline_plural(base, "") else for _, genderspec in ipairs(base.genders) do			local gender = genderspec.form decline_singular_and_plural(base, gender, get_default_gen(base, gender), get_default_pl(base, gender)) end end 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({"nom_s", "nom_p"}) 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

--[=[ decls["adj"] = function(base, stress) local adj_alternant_spec = require("Module:de-adjective").do_generate_forms(		{base.lemma}	) local function copy(from_slot, to_slot) base.forms[to_slot] = adj_alternant_spec.forms[from_slot] end if base.number ~= "pl" then copy("dir_m_s", "dir_s") copy("obl_m_s", "obl_s") copy("voc_m_s", "voc_s") end if base.number ~= "sg" then copy("dir_m_p", "dir_p") copy("obl_m_p", "obl_p") copy("voc_m_p", "voc_p") 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 cases[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_slots[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_mn = false for _, genderspec in ipairs(base.genders) do					local g = genderspec.form if g == "m" or g == "n" then saw_mn = true saw_sg = true elseif g == "f" then saw_sg = true elseif g == "p" then saw_pl = true 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 local pl_index = saw_mn and 3 or saw_pl and 1 or 2 if #comma_separated_groups > 1 and saw_mn then base.gens = com.fetch_specs(iut, comma_separated_groups[2], ":", "genitive", "allow blank", parse_err) end if #comma_separated_groups >= pl_index and not saw_pl then base.pls = com.fetch_specs(iut, comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err) end if #comma_separated_groups > pl_index then if saw_pl then parse_err("Can't specify plurals with plural-only nouns") elseif saw_mn then parse_err("Can specify at most three comma-separated specs when the gender is masculine or "							.. "neuter (gender, genitive, plural)") else parse_err("Can specify at most two comma-separated specs when then gender is feminine "							.. "(gender, plural)") end end if saw_pl then if #base.genders > 1 then parse_err("Internal error: More than one gender spec when gender spec is plural") elseif base.genders[1].footnotes then parse_err("Can't specify footnotes with 'pl' gender spec") else base.genders = {} base.number = "pl" end end 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 local case_prefix = usub(part, 1, 3) if cases[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 parse_err("Footnotes only allowed with slot overrides or by themselves: '" .. 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 part == "+" then if base.props.adj then parse_err("Can't specify '+' twice") end base.props.adj = true elseif part == "weak" or part == "ss" or part == "nodatpln" 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

local function detect_indicator_spec(alternant_multiword_spec, base) -- Set default values. if not base.props.adj then base.number = base.number or base.pls and "both" or alternant_multiword_spec.is_proper and "sg" or "both" end 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 base.gens = base.gens or 	base.pls = base.pls or 	if base.props.adj then synthesize_adj_lemma(base) 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) 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 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` ("gender" 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 set_defaults_and_check_bad_indicators. 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 (to handle e.g. пустальга звычайная "common kestrel", where  the adjective польовий should inherit the 'animal' animacy of лунь). 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" for animacy  and 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

-- 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(base) decline(base) 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_articles(alternant_multiword_spec) iut.map_word_specs(alternant_multiword_spec, function(base)		for _, genderspec in ipairs(base.genders) do			for case, _ in pairs(cases) do				iut.insert_form(alternant_multiword_spec.forms, "art_ind_" .. case .. "_s", {form = com.articles[genderspec.form]["ind_" .. case]})				iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_s", {form = com.articles[genderspec.form]["def_" .. case]})			end		end	end) for case, _ in pairs(cases) do iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",			{form = com.articles.p["def_" .. case]}) 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.props = {}

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.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 = {} local function do_word_spec(base) local saw_m_or_n = false for _, gender in ipairs(base.genders) do			if gender.form == "m" then m_table.insertIfNot(genderdescs, "masc") saw_m_or_n = true elseif gender.form == "f" then m_table.insertIfNot(genderdescs, "fem") elseif gender.form == "n" then m_table.insertIfNot(genderdescs, "neut") saw_m_or_n = true else error("Internal error: Unrecognized gender '" .. gender.form .. "'") end end if saw_m_or_n then if base.props.weak then insert("weak ~") m_table.insertIfNot(decldescs, "weak") else m_table.insertIfNot(decldescs, "strong") end -- Compute overall weakness for use in headword. if alternant_multiword_spec.props.weak == nil then alternant_multiword_spec.props.weak = base.props.weak elseif alternant_multiword_spec.props.weak ~= base.props.weak then alternant_multiword_spec.props.weak = "both" end end end 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 do_word_spec(multiword_spec.word_specs[key_entry]) end end else do_word_spec(alternant_or_word_spec) end end if alternant_multiword_spec.number ~= "both" then table.insert(annparts, alternant_multiword_spec.number == "sg" and "sg-only" or "pl-only") end 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 alternant_multiword_spec.annotation = table.concat(annparts, " ") end

local function process_dim_m_f(alternant_multiword_spec, arg_specs, default, slot, desc) local lemmas = alternant_multiword_spec.forms.nom_s or alternant_multiword_spec.forms.nom_p or {} 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, "[", "]") 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, default, nil, desc, process) end end

local function show_forms(alternant_multiword_spec) local lemmas = alternant_multiword_spec.forms.nom_s or alternant_multiword_spec.forms.nom_p or {} local props = { lang = lang, lemmas = lemmas, slot_table = noun_slots_with_linked_and_articles, }	iut.show_forms(alternant_multiword_spec.forms, props) end

local table_spec_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 table_spec_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 table_spec_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 table_spec_pl = [=[ {title}{annotation} {| 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 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 = alternant_multiword_spec.number == "sg" and table_spec_sg or		alternant_multiword_spec.number == "pl" and table_spec_pl or		table_spec_both if forms.abl_s ~= "—" or forms.voc_s ~= "—" then forms.abl_voc_clause = m_string_utilities.format(table_spec_abl_voc, forms) else forms.abl_voc_clause = "" end forms.notes_clause = forms.footnote ~= "" and m_string_utilities.format(notes_template, forms) or "" return m_string_utilities.format(table_spec, forms) end

local function compute_headword_genders(alternant_multiword_spec) local genders = {} if alternant_multiword_spec.number == "pl" then return {spec = "p"} end iut.map_word_specs(alternant_multiword_spec, function(base)		for _, genderspec in ipairs(base.genders) do			-- Create the new spec to insert.			local spec = {spec = genderspec.form}			if genderspec.footnotes then				local qualifiers = {}				for _, footnote in ipairs(genderspec.footnotes) do					m_table.insertIfNot(qualifiers, iut.expand_footnote_or_references(footnote, "return raw", "no parse refs"))				end				spec.qualifiers = qualifiers			end			-- See if the gender of the spec is already present; if so, combine qualifiers.			local saw_existing = false			for _, existing_spec in ipairs(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(genders, spec)			end		end	end) return genders end

-- Externally callable function to parse and decline a noun given user-specified arguments. -- Return value is WORD_SPEC, an object where the declined forms are in `WORD_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["dim"] = {list = true} params["id"] = {} params["sort"] = {} params["name"] = {} 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 function do_parse_indicator_spec(angle_bracket_spec, lemma) local pagename = args.pagename or parent_args["name"] or mw.title.getCurrentTitle.text 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.pos = pos or "nouns" alternant_multiword_spec.args = args alternant_multiword_spec.is_proper = is_proper detect_all_indicator_specs(alternant_multiword_spec) propagate_properties(alternant_multiword_spec, "number", "both", "both") -- The default of "M" should apply only to plural adjectives, where it doesn't matter. -- FIXME: This may be wrong for German. -- propagate_properties(alternant_multiword_spec, "gender", "M", "mixed") determine_noun_status(alternant_multiword_spec) local inflect_props = { skip_slot = function(slot) return skip_slot(alternant_multiword_spec.number, slot) end, slot_table = noun_slots_with_linked, inflect_word_spec = decline_noun, }	iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) compute_articles(alternant_multiword_spec) compute_categories_and_annotation(alternant_multiword_spec) alternant_multiword_spec.genders = compute_headword_genders(alternant_multiword_spec) process_dim_m_f(alternant_multiword_spec, args.dim, nil, "dim", "diminutive") process_dim_m_f(alternant_multiword_spec, args.f, nil, "f", "feminine equivalent") process_dim_m_f(alternant_multiword_spec, args.m, nil, "m", "masculine equivalent") 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_spec, include_props) local ins_text = {} for slot, _ in pairs(noun_slots_with_linked) do		local formtext = iut.concat_forms_in_slot(alternant_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_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_spec = export.do_generate_forms(parent_args) return concat_forms(alternant_spec, include_props) end

return export

title: Module:de-noun/sandbox


text:
Talk:unacceptable

Canadian usage
Put a pin in this one. It's emerging as the Canadian version of. WordyAndNerdy (talk) 02:09, 12 February 2022 (UTC)

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

title: Talk:unacceptable


text:
ਸਾਫ਼

Etymology
, from. Compare 🇨🇬.

Adjective

 * 1) clean
 * 2) clear
 * 3) legible, intelligible
 * 4) smooth
 * 1) legible, intelligible
 * 2) smooth

title: ਸਾਫ਼


text: Category:Rhymes:Punjabi/ɑːf

title: Category:Rhymes:Punjabi/ɑːf


text: Category:et:Hotels

title: Category:et:Hotels


text: Category:et:Tourism

title: Category:et:Tourism


text: Category:et:Travel

title: Category:et:Travel


text: Category:Estonian terms derived from Irish


text: aggek

title: aggek


text: aagig

title: aagig


text: Category:Rhymes:English/ɛlmɪt

title: Category:Rhymes:English/ɛlmɪt


text:
Talk:girlboss

Verb
This has been verbified, though it may be hard to find durably archived quotations. 70.172.194.25 02:29, 12 February 2022 (UTC)

title: Talk:girlboss


text:
akromatopsi

Etymology
From.

title: akromatopsi


text: Category:et:Carpentry

title: Category:et:Carpentry


text: Category:et:Construction

title: Category:et:Construction


text: Category:et:Woodworking

title: Category:et:Woodworking


text: Category:et:Hydrology

title: Category:et:Hydrology


text:
akromatik

Etymology
From.

Adjective

 * 1) achromatic

title: akromatik


text: Category:et:Thinking

title: Category:et:Thinking


text:
akromatin

Etymology
From.

title: akromatin


text:
ਤਿਆਰੀ

Noun

 * 1) preparation,  to prepare for
 * 2) completion
 * 3) physical fitness
 * 4) willingness
 * 1) willingness

title: ਤਿਆਰੀ


text: aggerous

title: aggerous


text:
a-gildroo

Adverb

 * 1)  Into confusion, to wreck and ruin.

title: a-gildroo


text:
agrip

Adverb

 * 1) In one's grip or grasp.

title: agrip


text: agyaen

title: agyaen


text:
Éliot

Etymology
.

title: Éliot


text: Éliott

title: Éliott


text: Élliot

title: Élliot


text: Élliott

title: Élliott


text: ageen

title: ageen


text:
Talk:身體健康

Taishanese
Can you add the Taishanese reading from this voice sample: ? The dog2 (talk) 03:28, 12 February 2022 (UTC)
 * ✅ — justin(r)leung { (t...) 14:20, 12 February 2022 (UTC)

title: Talk:身體健康


text: ノゲシ

title: ノゲシ


text: Lob Lie-by-the-Fire

title: Lob Lie-by-the-Fire


text: Lob-lie-by-the-fire

title: Lob-lie-by-the-fire


text:
Template:ks-conj-pa/styles.css

tr > td > a, tr > th > a { font-size: 133%; font-style: normal; font-weight: normal; font-family: 'Noto Naskh Arabic',Amiri,Mirza,Scheherazade,'Geeza Pro',Tahoma,sans-serif; }

title: Template:ks-conj-pa/styles.css


text:
akrobatlık

Noun

 * 1) acrobatics

title: akrobatlık


text:
کَرٕنَے

Etymology
From.

Verb

 * 1) having not done;

title: کَرٕنَے


text: Category:Kashmiri terms suffixed with ـنَے


text:
کٔرؠ مٕتؠ

Etymology
From.

title: کٔرؠ مٕتؠ


text: ニガナ

title: ニガナ


text: D/s

title: D/s


text: Category:et:Physical chemistry

title: Category:et:Physical chemistry


text: Category:et:Ions

title: Category:et:Ions


text: Category:et:Laughter

title: Category:et:Laughter


text: 野罌粟

title: 野罌粟


text:
User:Rishabhbhat/common.js

// /* globals mw, $ */ // jshint maxerr:500

/* * The starting point of the whole script. * * This adds a hook to the page load event so that the script runs * adds the generated text to the edit window once the page is done loading. */

"use strict";

mw.loader.using(["mediawiki.util"]).done(function {	var pageName = mw.config.get("wgPageName");	// Don't do anything unless the current page is in the main namespace.	// Set window.accelEverywhere = true to test this gadget elsewhere.	if (window.accelEverywhere || (mw.config.get("wgAction") === "view" && (mw.config.get("wgNamespaceNumber") === 0 || pageName == "Wiktionary:Sandbox"))) {		// Stores all accelerated data, by language, by target pagename.		// Sub-arrays are in HTML order.		var accelParamsByPagename = {};		var getTargetPagename = function(link) {			var targetPagename = mw.util.getParamValue("title", link.href);			if (targetPagename === null) {				var match = link.href.match(/^(.*)\/wiki\/([^#]+)(?:#.+)?$/);				if (match) {					targetPagename = decodeURIComponent(match[2]);				}			}			return targetPagename;		};		var getLang = function (element) {			if (element.accelLang !== undefined) { return element.accelLang; }			var hasLang = $(element).closest("[lang]")[0]; var lang = hasLang ? hasLang.getAttribute("lang") : null; element.accelLang = lang; return lang; };		var getPartOfSpeech = function(link) { // Acceleration can be added to inflection tables too. // This tells the search script to skip headers with these names. var skipheaders = [ "alternative forms", "antonyms", "conjugation", "declension", "derived terms", "inflection", "mutation", "related terms", "synonyms", "translations", "usage notes" ];			for (var node = link; node !== null; node = node.previousSibling || node.parentNode) { if (node.nodeType == 1 && node.nodeName.match(/^H[3-6]$/)) { var header = $(node).find(".mw-headline").text.replace(/^[1-9.]* /, "").toLowerCase; if (skipheaders.indexOf(header) == -1) { return header; }				}			}			throw new Error("This entry seems to be formatted incorrectly. Does it have a language and part-of-speech header?"); };		var createAccelParam = function(link) { var classNames = Array.prototype.filter.call($(link).closest(".form-of")[0].classList,				function (className) {					return (/^(gender|origin|origin_transliteration|pos|target|transliteration|affix)-.+|.+-form-of$/.test(className));				}); var accelParam = classNames.join(" "); var targetPagename = getTargetPagename(link); var targetHead = (link.innerText || link.textContent).replace(/ /g, "_"); if (targetPagename != targetHead) { accelParam = "target-" + targetHead + " " + accelParam; }			console.log(accelParam); return "pos-" + getPartOfSpeech(link).replace(/ /g, "_") + " " + accelParam; };		var storeAccelParam = function(link) { // Extract the targeted pagename from the URL, // and language code from the nearest element with a lang attribute var lang = getLang(link); var targetPagename = getTargetPagename(link); // Add page name to the list if (accelParamsByPagename[lang] === undefined) { accelParamsByPagename[lang] = {}; }			if (accelParamsByPagename[lang][targetPagename] === undefined) { accelParamsByPagename[lang][targetPagename] = []; }			var accelParam = createAccelParam(link); if (accelParamsByPagename[lang][targetPagename].indexOf(accelParam) === -1) { accelParamsByPagename[lang][targetPagename].push(accelParam); }		};		var processLink = function(link) { // Extract the targeted pagename from the URL, // and language code from the nearest element with a lang attribute var lang = getLang(link); var targetPagename = getTargetPagename(link); // Fetch the acceleration parameters from the store var accelParam = accelParamsByPagename[lang][targetPagename].slice(0) .map(function (accel, i) {					return "accel" + (i + 1).toString + "=" + encodeURIComponent(accel);				}) .join("&"); // Convert an orange link into an edit link if ($(link).hasClass("partlynew")) { link.href = link.href.replace(/^(.*)\/wiki\/([^#]+)(?:#.+)?$/, "$1/w/index.php?title=$2&action=edit"); }			// Now build a new "green link" URL to replace the original red link with link.href += "&editintro=User:Conrad.Irwin/creation.js/intro" + "&accel_lang=" + encodeURIComponent(lang) + "&accel_lemma=" + encodeURIComponent(pageName.replace(/_/g, " ")) + "&" + accelParam; link.style.color = "#22CC00"; link.processedLink = true; };		// Mutation observer to respond when OrangeLinks modifies links var mutobs = new MutationObserver(function(mutations, observer) {			mutations.forEach(function(mutation) { if (mutation.attributeName != "class") { return; }				var link = mutation.target; // Don't process a link we've already been to				if (link.processedLink) { return; }				if (!$(link).hasClass("partlynew")) { return; }				// Process processLink(link); });		});		// First generate and store all the parameters var oldtable = null; // Were we previously inside a table? var columns = []; $(".form-of a").each(function {			// Are we currently inside a table?			var $this = $(this);			var table = $this.closest("table");			if (table.length > 0) {				table = table[0];			} else {				table = null;			}			// Was a column number specified on the current table cell?			// jQuery.fn.data automatically converts an integer-like string			// to a number.			var col = $this.closest("td[data-accel-col]").first.data("accel-col");			if (typeof col !== "number") {				col = null;			}			// If we were in a table, and we changed to another table or are no longer in one,			// or if there is no column number attribute, flush the column lists.			if (oldtable && (oldtable !== table || col === null)) {				for (var i = 0; i < columns.length; ++i) {					for (var j = 0; j < columns[i].length; ++j) {						storeAccelParam(columns[i][j]);					}				}				columns = [];			}			oldtable = table;			// The nostore parameter causes the link to not be stored, // but it is processed later. The effect is that this link has no // effect on the ordering of forms. if ($(this).closest(".form-of").first.hasClass("form-of-nostore")) { return; }			// If there is a column number attribute, defer storing the link, // put it in the columns array instead. if (col !== null) { --col; // Column attributes are 1-based, JS arrays are 0-based // Expand the columns list to fit the number of columns while (columns.length <= col) { columns.push([]); }				// Save the link in the columns list columns[col].push(this); } else { // Store the link directly storeAccelParam(this); }		});		// Flush column lists		for (var i = 0; i < columns.length; ++i) {			for (var j = 0; j < columns[i].length; ++j) {				storeAccelParam(columns[i][j]);			}		}		// Then add them onto the links, or add a mutation observer		$(".form-of a").each(function { var $this = $(this); if ($this.hasClass("new") || $this.hasClass("partlynew")) { processLink(this); } else { // FIXME: There's a small window for a race condition here. // If the "partlynew" class is added by OrangeLinks after the above if-statement is evaluated, // but before the observer is added, then the link won't be processed. mutobs.observe(this, {attributes : true}); }		});	} else if (mw.config.get("wgAction") === "edit") {		// Get the parameters from the URL		var getAccelParams = function {			var accelParams = [];			var i = 1;			while (true) {				var acceldata = mw.util.getParamValue("accel" + i.toString);				if (!acceldata) {					break;				}				// Default values				var params = {					pos: null,					form: null,					gender: null,					affix: mw.util.getParamValue("accel_affix"),					transliteration: null,					origin: mw.util.getParamValue("accel_lemma"),					origin_transliteration: null,					target: pageName,				};				// Go over each part and add it				var parts = acceldata.split(" ");				for (var j = 0; j < parts.length; ++j) {					var part = parts[j];					if (part.match(/^(gender|origin|origin_transliteration|pos|target|transliteration|affix)-(.+)$/)) {						params[RegExp.$1] = RegExp.$2.replace(/_/g, " ");					} else if (part.match(/^(.+)-form-of$/)) { params.form = RegExp.$1.replace(/_/g, " "); }				}				accelParams.push(params); ++i; }			console.log(accelParams); return accelParams; };		// Generates entries from the information var printArgs = function(accelParams) { var args = [ "lang=" + mw.util.getParamValue("accel_lang"), "origin_pagename=" + mw.util.getParamValue("accel_lemma"), "target_pagename=" + pageName, "num=" + accelParams.length, ];			for (var i = 0; i < accelParams.length; ++i) { for (var key in accelParams[i]) { if (accelParams[i][key] !== null) { args.push(key + (i + 1) + "=" + accelParams[i][key].replace(/\|/g, "|")); }				}			}			return args.join("|"); };		var showModuleError = function(errorText) { // Attempt to link to the line of the module in which the error occurred. errorText = errorText.replace(				/(Module:[^#<>\[\]|{}_]+)(?: at line |:)(\d+)/,				function (wholeMatch, moduleName, lineNumber) {					var link = document.createElement('a');					link.href = mw.util.getUrl(moduleName, {action: "edit"}) + "#mw-ce-l" + lineNumber;					link.innerHTML = moduleName + " at line " + lineNumber;					return "Lua error in " + link.outerHTML;				}); var errorBox = "" + " An error occurred while generating the entry: " + " " + errorText + " " + " ";			wikipreview.insertAdjacentHTML("beforebegin", errorBox); };		var receiveModuleResponse = function(response) { var newtext, result; try { result = JSON.parse(response.expandtemplates.wikitext); } catch (err) { // JSON parse error should not happen. mw.notify(err.msg); return; }			if (result.error) { // module error showModuleError(result.error); } else { // successfully generated entries newtext = result.entries; }			for (i = 0; i < result.messages.length; ++i) { mw.notify(result.messages[i]); }			if (!newtext) { return; }			var newValue; // Does the page already exist? if (textbox.value) { var langsection_regex = /^==([^=\n]+)==$/mg; var match = langsection_regex.exec(newtext); if (!match) { showModuleError("No language section was found in the returned text."); }				var langname = match[1]; // Reset position at which regex starts its search. // Otherwise, regex starts matching after the index where it // found the language header in newtext. langsection_regex.lastIndex = 0; // Go over language sections to find where to insert our new one while ((match = langsection_regex.exec(textbox.value)) !== null) { if (match[1] == langname) { // There already exists a section for our language, abort. return; } else if (match[1] == "Translingual" || match[1] == "English" || (langname != "English" && match[1] < langname)) { // Skip past English and Translingual, or if the language sorts higher continue; } else { // We found the first match that sorts lower than our language, great. break; }				}				var scrollIndex; newValue = textbox.value; if (match === null) { // We found no language that our section should go before, so insert it at the end. newValue = newValue.trimEnd + "\n\n\n\n"; scrollIndex = newValue.length; newValue = newValue + newtext; } else { // We found a language to insert before, so do that. newValue = newValue.substring(0, match.index) + newtext + "\n\n\n\n" + newValue.substring(match.index); scrollIndex = match.index; }				// Scroll the textbox to the newly added section. First scroll all the way down, // then set the cursor to the start of the new section, which scrolls back up // to the new section's language header. textbox.scrollTop = textbox.scrollHeight; textbox.selectionStart = scrollIndex; textbox.selectionEnd = scrollIndex; summary.value = "Adding forms of " + lemma + " (Accelerated)"; } else { newValue = newtext; summary.value = "Creating forms of " + lemma + " (Accelerated)"; }			// Set textbox text. Setting textbox.value is unreliable. $(textbox).val(newValue); };		var wikipreview = document.getElementById("wikiPreview"); var textbox = document.getElementById("wpTextbox1"); var summary = document.getElementById("wpSummary"); var lang = mw.util.getParamValue("accel_lang"); var lemma = mw.util.getParamValue("accel_lemma"); var affix = mw.util.getParamValue("accel_affix"); if (!(wikipreview && textbox && summary && lang && lemma)) { return; }		// Gather all the information that was given in the URL var accelParams = getAccelParams; if (!accelParams) { return; }		var module = "User:Rishabhbhat/accel", funcName = "generate_JSON"; mw.loader.using("mediawiki.api", function {			new mw.Api.get({ "action": "expandtemplates", "format": "json", "text": "", "prop": "wikitext" }).done(receiveModuleResponse);		}); } });

//

title: User:Rishabhbhat/common.js


text:
Module:User:Rishabhbhat/accel

local export = {}

local rsplit = mw.text.split local split_term_regex = "%*~!"

-- FIXME: Intentionally global, but think whether this is correct. Currently no messages are logged in any code. -- This potentially could be made non-global by moving inside of generate_JSON and passed into export.generate, -- so it can in turn be passed to language-specific accelerator code. messages = require("Module:array") -- intentionally global

function export.default_entry(params) local function make_head(pos, default_gender) local gender = params.gender or default_gender local genderspec = "" if gender then local genders = rsplit(gender, ",") for i, g in ipairs(genders) do				if i == 1 then genders[i] = "|g=" .. g				else genders[i] = "|g" .. i .. "=" .. g				end end genderspec = table.concat(genders) end local parts = {} table.insert(parts, "") return table.concat(parts) end

local function make_def(tempname, extra_params) local parts = {} table.insert(parts, "") return table.concat(parts) end

local function no_rule_error(params) -- FIXME, verify the 2 below (number of stack frames to pop off); may be wrong now that we moved this function -- underneath default_entry. return error(('No rule for "%s" in language "%s".')			:format(params.form, params.lang), 2) end

local entry = { pronunc = nil, affix = params.affix, pos_header = mw.getContentLanguage:ucfirst(params.pos), head = make_head(params.pos .. " form"), def = make_def("inflection of", "||" .. params.form), inflection = nil, declension = nil, conjugation = nil, mutation = nil, altforms = nil, -- also pass in functions make_head = make_head, make_def = make_def, no_rule_error = no_rule_error, }	-- Exceptions for some forms local templates = { ["p"] = "plural of", ["f"] = "feminine of", ["f|s"] = "feminine singular of", ["m|p"] = "masculine plural of", ["f|p"] = "feminine plural of", ["pejorative"] = "pejorative of", }	if params.form == "comparative" or params.form == "superlative" or params.form == "equative" then entry.head = make_head(params.form .. " " .. params.pos) entry.def = make_def(params.form .. " of", params.pos ~= "adjective" and "|POS=" .. params.pos or "") elseif params.form == "diminutive" or params.form == "augmentative" then entry.head = make_head(params.pos) entry.def = make_def(params.form .. " of", params.pos ~= "noun" and "|POS=" .. params.pos or "") elseif params.form == "f" and params.pos == "noun" then entry.head = make_head(params.pos, "f") entry.def = make_def("female equivalent of") elseif (params.form == "abstract noun" or params.form == "verbal noun") and params.pos == "noun" then entry.head = make_head(params.pos) entry.def = make_def(params.form .. " of") elseif templates[params.form] then entry.def = make_def(templates[params.form]) end return entry end

-- Given a list of tags, split into tag sets (separated by semicolons in -- the initial list of tags). local function split_tags_into_tag_sets(tags) local tag_set_group = {} local cur_tag_set = {} for _, tag in ipairs(tags) do		if tag == ";" then if #cur_tag_set > 0 then table.insert(tag_set_group, cur_tag_set) end cur_tag_set = {} else table.insert(cur_tag_set, tag) end end if #cur_tag_set > 0 then table.insert(tag_set_group, cur_tag_set) end return tag_set_group end

-- Canonicalize multipart shortcuts (e.g. "123" -> "1//2//3") and -- list shortcuts (e.g. "1s" -> {"1", "s"}); leave others alone. local function canonicalize_multipart_and_list_shortcuts(tags) local result = {} for _, tag in ipairs(tags) do		local expansion = require("Module:form of").lookup_shortcut(tag) if type(expansion) == "string" and not expansion:find("//", nil, true) then expansion = tag end if type(expansion) == "table" then for _, t in ipairs(expansion) do				table.insert(result, t)			end else table.insert(result, expansion) end end return result end

-- Split a multipart tag into component tags, normalize each component, and -- return the resulting list. If MAP_TO_CANONICAL_SHORTCUT is given, -- attempt to map each normalized component tag to its "canonical shortcut", -- i.e. the first shortcut listed among its shortcuts. -- -- If given a two-level multipart tag such as "1:sg//3:pl", the resulting -- return value will be {"first:singular", "third:plural"}, or {"1:s", "3:p"} -- if MAP_TO_CANONICAL_SHORTCUT is given. local function split_and_normalize_tag(tag, map_to_canonical_shortcut) local m_form_of = require("Module:form of") local normalized = m_form_of.normalize_tags({tag}, true) assert(#normalized == 1, "Something is wrong, encountered list tag " .. tag .. ", which should have been canonicalized earlier") tag = normalized[1] if tag:find("://") then -- HTML URL??? return {tag} else local tags = rsplit(tag, "//") if map_to_canonical_shortcut then for i=1,#tags do				if tags[i]:find(":") then local split_tags = rsplit(tags[i], ":") for j=1,#split_tags do						local tagobj = m_form_of.lookup_tag(split_tags[j]) split_tags[j] = tagobj and tagobj.shortcuts and tagobj.shortcuts[1] or split_tags[j] end tags[i] = table.concat(split_tags, ":") else local tagobj = m_form_of.lookup_tag(tags[i]) tags[i] = tagobj and tagobj.shortcuts and tagobj.shortcuts[1] or tags[i] end end end return tags end end

-- Given a normalized tag, return its tag type, or "unknown" if a tag type -- cannot be located (either the tag isn't recognized or for some reason -- it doesn't specify a tag type). local function get_normalized_tag_type(tag) local tagobj = require("Module:form of").lookup_tag(tag) return tagobj and tagobj.tag_type or "unknown" end

-- Combine multiple semicolon-separated tag sets into multipart tags if -- possible. We combine tag sets that differ in only one tag in a given -- dimension, and repeat this until no changes in case we can reduce along -- multiple dimensions, e.g. -- -- -- -- local function combine_tag_sets_into_multipart(tags) -- First, as an optimization, make sure there are multiple tag sets. -- Otherwise, do nothing. local found_semicolon = false for _, tag in ipairs(tags) do		if tag == ";" then found_semicolon = true break end end if not found_semicolon then return tags end

local m_table = require("Module:table")

-- Repeat until no changes can be made. while true do -- First, canonicalize 1s etc. into 1|s local canonicalized_tags = canonicalize_multipart_and_list_shortcuts(tags) local old_canonicalized_tags = canonicalized_tags

-- Then split into tag sets. local tag_set_group = split_tags_into_tag_sets(canonicalized_tags)

-- Try combining in two different styles ("adjacent-first" =		-- do two passes, where the first pass only combines adjacent		-- tag sets, while the second pass combines nonadjacent tag sets;		-- "all-first" = do one pass combining nonadjacent tag sets). -- Sometimes one is better, sometimes the other. --		-- An example where adjacent-first is better: --		-- 		--		-- all-first results in		-- -- 		--		-- which isn't ideal. --		-- If we do adjacent-first, we get --		-- 		--		-- which is much better. --		-- The opposite happens in		-- -- 		--		-- where all-first results in		-- -- 		--		-- which is better than the result from adjacent-first, which is		-- -- 		--		-- To handle this conundrum, we try both, and look to see which one -- results in fewer "combinations" (where a tag with // in it counts		-- as a combination). If both are different but have the same # of		-- combinations, we prefer adjacent-first, we seems generally a better -- approach.

local tag_set_group_by_style = {}

for _, combine_style in ipairs({"adjacent-first", "all-first"}) do -- Now, we do two passes. The first pass only combines adjacent -- tag sets, while the second pass combines nonadjacent tag sets. -- Copy tag_set_group, since we destructively modify the list. local tag_sets = m_table.shallowClone(tag_set_group) local combine_passes if combine_style == "adjacent-first" then combine_passes = {"adjacent", "all"} else combine_passes = {"all"} end for _, combine_pass in ipairs(combine_passes) do				local tag_ind = 1 while tag_ind <= #tag_sets do					local from, to					if combine_pass == "adjacent" then if tag_ind == 1 then from = 1 to = 0 else from = tag_ind - 1 to = tag_ind - 1 end else from = 1 to = tag_ind - 1 end local inner_broken = false for prev_tag_ind=from,to do						local cur_tag_set = tag_sets[prev_tag_ind] local tag_set = tag_sets[tag_ind] if #cur_tag_set == #tag_set then local mismatch_ind = nil local innermost_broken = false for i=1,#tag_set do								local tag1 = split_and_normalize_tag(cur_tag_set[i]) local tag2 = split_and_normalize_tag(tag_set[i]) if not m_table.deepEquals(m_table.listToSet(tag1),									m_table.listToSet(tag2)) then if mismatch_ind then innermost_broken = true break end local combined_dims = {} for _, tag in ipairs(tag1) do										combined_dims[get_normalized_tag_type(tag)] = true end for _, tag in ipairs(tag2) do										combined_dims[get_normalized_tag_type(tag)] = true end if m_table.size(combined_dims) == 1 and not combined_dims["unknown"] then mismatch_ind = i									else innermost_broken = true break end end end if not innermost_broken then -- No break, we either match perfectly or are combinable if not mismatch_ind then -- Two identical tag sets table.remove(tag_sets, tag_ind) inner_broken = true break else -- Combine tag sets at mismatch_ind, using the canonical shortcuts. tag1 = cur_tag_set[mismatch_ind] tag2 = tag_set[mismatch_ind] tag1 = split_and_normalize_tag(tag1, true) tag2 = split_and_normalize_tag(tag2, true) local combined_tag = table.concat(m_table.append(tag1, tag2), "//") local new_tag_set = {} for i=1,#cur_tag_set do										if i == mismatch_ind then table.insert(new_tag_set, combined_tag) else local cur_canon_tag = split_and_normalize_tag(cur_tag_set[i]) local canon_tag = split_and_normalize_tag(tag_set[i]) assert(m_table.deepEquals(m_table.listToSet(cur_canon_tag), m_table.listToSet(canon_tag))) table.insert(new_tag_set, cur_tag_set[i]) end end tag_sets[prev_tag_ind] = new_tag_set table.remove(tag_sets, tag_ind) inner_broken = true break end end end end if not inner_broken then -- No break from inner for-loop. Break from that loop indicates -- that we found that the current tag set can be combined with -- a preceding tag set, did the combination and deleted the -- current tag set. The next iteration then processes the same -- numbered tag set again (which is actually the following tag						-- set, because we deleted the tag set before it). No break -- indicates that we couldn't combine the current tag set with -- any preceding tag set, and need to advance to the next one. tag_ind = tag_ind + 1 end end end tag_set_group_by_style[combine_style] = tag_sets end

local tag_set_group if not m_table.deepEqualsList(tag_set_group_by_style["adjacent-first"], tag_set_group_by_style["all-first"]) then local function num_combinations(group) local num_combos = 0 for _, tag_set in ipairs(group) do					for _, tag in ipairs(tag_set) do						if tag:find("//") then num_combos = num_combos + 1 end end end return num_combos end

local num_adjacent_first_combos = num_combinations(tag_set_group_by_style["adjacent-first"]) local num_all_first_combos = num_combinations(tag_set_group_by_style["all-first"]) if num_adjacent_first_combos < num_all_first_combos then tag_set_group = tag_set_group_by_style["adjacent-first"] elseif num_all_first_combos < num_adjacent_first_combos then tag_set_group = tag_set_group_by_style["all-first"] else tag_set_group = tag_set_group_by_style["adjacent-first"] end else -- Both are the same, pick either one tag_set_group = tag_set_group_by_style["adjacent-first"] end

canonicalized_tags = {} for _, tag_set in ipairs(tag_set_group) do			if #canonicalized_tags > 0 then table.insert(canonicalized_tags, ";") end for _, tag in ipairs(tag_set) do				table.insert(canonicalized_tags, tag) end end if m_table.deepEqualsList(canonicalized_tags, old_canonicalized_tags) then break end -- FIXME, we should consider reversing the transformation 1s -> 1|s, -- but it's complicated to figure out when the transformation occurred; -- not really important as both are equivalent tags = canonicalized_tags end

return tags end

-- Test function, callable externally. function export.test_combine_tag_sets_into_multipart(frame) local combined_tags = combine_tag_sets_into_multipart(frame.args) return table.concat(combined_tags, "|") end

local function find_mergeable(entry, candidates) local function can_merge(candidate) for _, key in ipairs({"pronunc", "affix", "pos_header", "head", "inflection", "declension", "conjugation", "altforms"}) do			if entry[key] ~= candidate[key] then return false end end return true end for _, candidate in ipairs(candidates) do		if can_merge(candidate) then return candidate end end return nil end

-- Merge multiple entries into one if they differ only in the definition, with all other -- properties the same. The combined entry has multiple definition lines. We then do -- further frobbing of lines: -- -- 1. Convert lang= param to param 1 (there shouldn't be any remaining cases of accelerator --   modules generating  templates with lang=, but we do this just in case). -- 2. Combine adjacent lines that differ only in the tags, e.g.: -- --   # --    # --    # --    # -- --    becomes -- --   # -- -- 3. Further group  lines with multiple tag sets (as may be generated b y --    the previous step) using multipart tags, e.g. for the Latin entry bonum, -- --   # -- --    becomes -- --   # -- --    This grouping can group across multiple dimensions, e.g. for the Latin entry bonīs, -- --   # -- --    becomes -- --   # -- --    Another complex real-world example, for the Old English weak adjective form dēorenan: -- --   # -- --    becomes -- --   # -- --    Here, 17 separate tag sets are combined down into 3. local function merge_entries(entries) local entries_new = {}

-- First rewrite to 	for _, entry in ipairs(entries) do		local params = entry.def:match("^$") if params then params = rsplit(params, "|", true) local new_params = {} for _, param in ipairs(params) do				local lang = param:match("^lang=(.*)$") if lang then table.insert(new_params, 1, lang) else table.insert(new_params, param) end end entry.def = "" end end

-- Merge entries that match in all of the following properties: -- "pronunc", "pos_header", "head", "inflection", "declension", "conjugation", "altforms" -- This will merge any two mergeable entries even if non-consecutive. -- The definitions of the merged entries do not have to match, but any matching -- definitions will be deduped. for _, entry in ipairs(entries) do -- See if this entry can be merged with any previous entry. local merge_entry = find_mergeable(entry, entries_new)

if merge_entry then local duplicate_def = false -- If we can merge, check whether the definition of the new entry is -- the same as any previous definitions. for _, def in ipairs(merge_entry.defs) do				if def == entry.def then duplicate_def = true break end end

if not duplicate_def then table.insert(merge_entry.defs, entry.def) end else entry.defs = {entry.def} table.insert(entries_new, entry) end end

-- Combine the definitions for each entries, merging all calls -- into one such call with multiple tag sets. for _, entry in ipairs(entries_new) do		local existing_defs = {} for _, new_def in ipairs(entry.defs) do			local did_merge = false local new_params = new_def:match("^$") if new_params then -- The new definition is. See if there is an -- among the definitions seen so far. for i, existing_def in ipairs(existing_defs) do					local existing_params = existing_def:match("^$") if existing_params then -- Merge the existing and new calls. -- Find the last unnamed parameter of the first template. existing_params = rsplit(existing_params, "|", true) local last_numbered_index for j, param in ipairs(existing_params) do							if not param:find("=", nil, true) then last_numbered_index = j							end end -- Add grammar tags of the second template new_params = rsplit(new_params, "|") local tags = {} local n = 0 for k, param in ipairs(new_params) do							if not param:find("=", nil, true) then n = n + 1 -- Skip the first three unnamed parameters, -- which don't indicate grammar tags if n >= 4 then -- Now append the tags table.insert(tags, param) end end end -- Add the new parameters after the existing ones existing_params[last_numbered_index] = existing_params[last_numbered_index] .. "|;|" .. table.concat(tags, "|") existing_defs[i] = "" did_merge = true break end end end

if not did_merge then table.insert(existing_defs, new_def) end end

entry.def = table.concat(existing_defs, "\n# ") end -- Now combine tag sets inside a multiple-tag-set call for i, entry in ipairs(entries_new) do		local infl_of_params = entry.def:match("^$") if infl_of_params then infl_of_params = rsplit(infl_of_params, "|", true)

-- Find the last unnamed parameter local last_numbered_index for j, param in ipairs(infl_of_params) do				if not param:find("=", nil, true) then last_numbered_index = j				end end

-- Split the params in three: -- (1) Params before the inflection tags, and any named params mixed in with the tags -- (2) The tags themselves -- (3) Named params after the tags local pre_tag_params = {} local tags = {} local post_tag_params = {} local n = 0 for j, param in ipairs(infl_of_params) do				if not param:find("=", nil, true) then n = n + 1 -- Skip the first three unnamed parameters, which don't indicate grammar tags if n >= 4 then table.insert(tags, param) else table.insert(pre_tag_params, param) end elseif n >= last_numbered_index then table.insert(post_tag_params, param) else table.insert(pre_tag_params, param) end if not param:find("=", nil, true) then last_numbered_index = j				end end

-- Now combine tag sets. tags = combine_tag_sets_into_multipart(tags)

-- Put the template back together. local combined_params = {} for _, param in ipairs(pre_tag_params) do				table.insert(combined_params, param) end for _, param in ipairs(tags) do				table.insert(combined_params, param) end for _, param in ipairs(post_tag_params) do				table.insert(combined_params, param) end entry.def = "" end end

return entries_new end

local function entries_to_text(entries, lang) lang = require("Module:languages").getByCode(lang, "lang") for i, entry in ipairs(entries) do		entry = (entry.affix and "===Etymology===\n" .. "\n\n" or "") .. (entry.pronunc and "===Pronunciation===\n" .. entry.pronunc .. "\n\n" or "") .. "===" .. entry.pos_header .. "===\n" .. entry.head .. "\n\n" .. "# " .. entry.def .. (entry.inflection and "\n\n====Inflection====\n" .. entry.inflection or "") .. (entry.declension and "\n\n====Declension====\n" .. entry.declension or "") .. (entry.conjugation and "\n\n====Conjugation====\n" .. entry.conjugation or "") .. (entry.mutation and "\n\n===Mutation===\n" .. entry.mutation or "") .. (entry.altforms and "\n\n====Alternative forms====\n" .. entry.altforms or "") entries[i] = entry end return "==" .. lang:getCanonicalName .. "==\n\n" .. table.concat(entries, "\n\n TEST") end

local function split_term_and_translit(encoded_term, encoded_translit) local terms = rsplit(encoded_term, split_term_regex) local translits = encoded_translit and rsplit(encoded_translit, split_term_regex) or {} if #translits > #terms then error(("Saw %s translits, which is > the %s terms seen: encoded_term=%s, encoded_translit=%s"):			format(#translits, #terms, encoded_term, encoded_translit)) end local result = {} for i, term in ipairs(terms) do		local translit = translits[i] if translit == "" then translit = nil end table.insert(result, {term = term, translit = translit}) end return result end

function export.generate(frame) local fparams = { lang           = {required = true}, origin_pagename = {required = true}, target_pagename = {required = true}, num            = {required = true, type = "number"}, pos                   = {list = true, allow_holes = true}, affix                 = {list = true, allow_holes = true}, form                  = {list = true, allow_holes = true}, gender                = {list = true, allow_holes = true}, transliteration       = {list = true, allow_holes = true}, origin                = {list = true, allow_holes = true}, origin_transliteration = {list = true, allow_holes = true}, -- I'm pretty sure this is actually required and must have args.num entries in it. target                = {list = true, allow_holes = true}, }	local args = require("Module:parameters").process(frame.args, fparams) local entries = {} -- Generate each entry for i = 1, args.num do		local params = { lang = args.lang, origin_pagename = args.origin_pagename, target_pagename = args.target_pagename, pos = args.pos[i] or error("The argument \"pos\" is missing for entry " .. i), affix = args.affix[i]:gsub("|", "|") or args.affix[i], form = args.form[i] or error("The argument \"form\" is missing for entry " .. i), gender = args.gender[i], transliteration = args.transliteration[i], origin = args.origin[i] or error("The argument \"origin\" is missing for entry " .. i), origin_transliteration = args.origin_transliteration[i], target = args.target[i], }		params.form = params.form:gsub("|", "|") params.targets = split_term_and_translit(params.target, params.transliteration) params.origins = split_term_and_translit(params.origin, params.origin_transliteration) -- Make a default entry local entry = export.default_entry(params) -- Try to use a language-specific module, if one exists local success, lang_module = pcall(require, "Module:accel/" .. args.lang) if success then lang_module.generate(params, entry) end -- Add it to the list table.insert(entries, entry) end -- Merge entries if possible entries = merge_entries(entries) entries = entries_to_text(entries, args.lang) return entries end

function export.generate_JSON(frame) local success, entries = pcall(export.generate, frame) -- If success is false, entries is an error message. local ret = { [success and "entries" or "error"] = entries, messages = messages } return require("Module:JSON").toJSON(ret) end

return export

title: Module:User:Rishabhbhat/accel


text: Category:Estonian terms derived from Japanese


text: Category:Estonian terms derived from Japonic languages


text: Category:et:Conifers

title: Category:et:Conifers


text: Category:et:Gymnosperms

title: Category:et:Gymnosperms


text:
jatah

Etymology
From. From.

Noun

 * 1) ration: a portion of some limited resource allocated to a person or group.
 * 2) quota
 * 1) quota

title: jatah


text:
Wojnarowski

Etymology
Borrowed from.

Statistics

 * According to the 2010 United States Census, Wojnarowski is the 44270th most common surname in the United States, belonging to 486 individuals. Wojnarowski is most common among White (97.53%) individuals.

title: Wojnarowski


text: pōku

title: pōku


text: Template:ohi-noun

title: Template:ohi-noun


text:
udskiftning

Noun

 * 1) replacement

title: udskiftning


text:
рециклиране

Noun

 * 1) recycling

title: рециклиране


text:
jäätmekäitlus

Noun

 * 1) recycling

title: jäätmekäitlus


text: Citations:gospodin

title: Citations:gospodin


text:
marchmount

Etymology
🇰🇲; coined by to translate.

Noun

 * 1) A tall mountain, in particular one of the Five Great Mountains of China.

Usage notes

 * Now standard in the sinological literature.

title: marchmount


text:
angiangi

Etymology
.

Noun

 * 1) gentle breeze

Etymology
.

Adjective

 * 1) breezy, windy

Verb

 * 1)  to blow

title: angiangi


text: intuor

title: intuor


text:
원자필

Etymology
.

Noun

 * 1)  ballpoint pen

title: 원자필


text:
oroshärd

Etymology
🇰🇲

Noun

 * 1) trouble spot, hot spot

title: oroshärd


text: oroshärden

title: oroshärden


text: oroshärdar

title: oroshärdar


text: oroshärdarna

title: oroshärdarna


text: oroshärds

title: oroshärds


text: oroshärdens

title: oroshärdens


text: oroshärdars

title: oroshärdars


text: oroshärdarnas

title: oroshärdarnas


text:
encabrestar

Etymology
From.

Verb

 * 1) to dominate, to subjugate

title: encabrestar


text:
तूफ़ान के पहले की शांति

Noun

 * 1)  calm before the storm

title: तूफ़ान के पहले की शांति


text: तूफ़ान के पहले की शान्ति

title: तूफ़ान के पहले की शान्ति


text:
halvdussin

Etymology
🇰🇲

Noun

 * 1) half dozen, half a dozen

title: halvdussin


text: halvdussinet

title: halvdussinet


text: halvdussinen

title: halvdussinen


text: halvdussinets

title: halvdussinets


text: halvdussinens

title: halvdussinens


text: halvdussins

title: halvdussins


text:
lyssnare

Noun

 * 1) listener

Usage notes
Most often used to describe radio listeners.

title: lyssnare


text: lyssnaren

title: lyssnaren


text: lyssnarens

title: lyssnarens


text: lyssnarnas

title: lyssnarnas


text: lyssnares

title: lyssnares


text:
榜上有名

Idiom

 * 1) to have one's name on the list

title: 榜上有名


text: Ph.B.

title: Ph.B.


text:
coronoapical

Etymology
From.

Adjective

 * 1)  Of or pertaining to the  and  aspects of a tooth (the  and the root ); as  being on the longitudinal axis of the tooth, defined by those poles.

title: coronoapical


text: ζήλειας

title: ζήλειας


text: ζήλειες

title: ζήλειες


text: ζήλιας

title: ζήλιας


text: ζήλιες

title: ζήλιες


text:
play or pay

Phrase

 * 1)  Either continue with a gambling arrangement or forfeit the money.

title: play or pay


text: Philosophiae Doctor

title: Philosophiae Doctor


text:
Metacarcinus

Proper noun
†

title: Metacarcinus


text: Philosophiae Baccalaureus

title: Philosophiae Baccalaureus


text: ζήλου

title: ζήλου


text: ζήλο

title: ζήλο


text: ζήλε

title: ζήλε


text: ζητήματος

title: ζητήματος


text: ζητήματα

title: ζητήματα


text: ζητημάτων

title: ζητημάτων


text:
dolthead

Noun

 * 1) A dolt; a fool.

title: dolthead


text: doltheads

title: doltheads


text: ζήτησης

title: ζήτησης


text: ζητήσεως

title: ζητήσεως


text: ζητήσεις

title: ζητήσεις


text: ζητήσεων

title: ζητήσεων


text:
domicilement

Noun

 * 1) The state of being domiciled; residence in a certain place.

title: domicilement


text: Dombeya

title: Dombeya


text:
Dongolese

Adjective

 * 1) Of or relating to Dongolawi Nubian language.

title: Dongolese


text:
Dongolawi

Proper noun

 * 1) A Nubian language of northern Sudan.

Noun

 * 1) A member of various Nubian tribes and peoples in northern Sudan, primarily settling between the third Nile cataract and.

title: Dongolawi


text: reheatables

title: reheatables


text:
shower thought

Etymology
From.

Noun

 * 1)  An idea, often some minor epiphany, that occurs while showering or otherwise going about one’s everyday routine.

title: shower thought


text: marchmounts

title: marchmounts


text: shower thoughts

title: shower thoughts


text: donums

title: donums


text: täuschender

title: täuschender


text: täuschendsten

title: täuschendsten


text:
dooja

Etymology
From an Aboriginal language.

Noun

 * , the Australian lime.

title: dooja


text:
dookit

Noun

 * 1) dovecote
 * 2) alcove or cupboard without doors
 * 3) cubbyhole
 * 4) pigeonhole; small compartment

title: dookit


text: Category:sco:Animal dwellings

title: Category:sco:Animal dwellings


text:
rejimen

Etymology
.

Noun

 * : any regulation or remedy which is intended to produce beneficial effects by gradual operation.

Etymology 1
From.

Noun

 * 1)  regiment

Etymology 2
From, from.

Noun

 * 1)  regimen

title: rejimen


text:
doormaid

Etymology
🇰🇲

Noun

 * 1)  A doorwoman.

title: doormaid


text: doormaids

title: doormaids


text:
doorweed

Etymology
🇰🇲

title: doorweed


text: doorweeds

title: doorweeds


text: focari

title: focari


text: friști

title: friști


text:
heinähukka

Noun

 * 1) fox moth

title: heinähukka


text:
Doradidae

Hypernyms

 * ; - superorder;  - order

Hyponyms

 * ,, , , , , , , , , , , , , , , , , , , , , , , , , , , , , - genera

title: Doradidae


text:
talking catfish

Noun

 * 1) Any of the catfishes of the family, able to produce sound by moving their pectoral spine or vibrating their swim bladder.

title: talking catfish


text: talking catfishes

title: talking catfishes


text: frâne

title: frâne


text:
dorab

Noun

 * 1) The.

title: dorab


text: dorabs

title: dorabs


text:
चौकन्ना

Etymology
, from.

Adjective

 * 1) alert, vigilant, watchful, on guard

title: चौकन्ना


text: चौकन्नी

title: चौकन्नी


text: चौकन्ने

title: चौकन्ने


text:
nonparamyxovirus

Etymology
From.

Adjective

 * 1) Not : of another viral  than.

title: nonparamyxovirus


text:
dorcastry

Noun

 * 1)  A Dorcas society ladies' church association making clothes for the poor

title: dorcastry


text: dorcastries

title: dorcastries


text: Dorical

title: Dorical


text: dorje

title: dorje


text: osteochondroplasties

title: osteochondroplasties


text: dorjes

title: dorjes


text: Dorosoma

title: Dorosoma


text:
dorsospinal

Etymology
en

title: dorsospinal


text:
dorsocephalic

Etymology
en

Adjective

 * 1)  Relating to the back and the head.

title: dorsocephalic


text:
dorsonuchal

Adjective

 * 1)  Relating to the back and to the back of the neck.

title: dorsonuchal


text:
dorsosternal

Adjective

 * 1)  Relating to the back and the sternum.

title: dorsosternal


text:
dorsothoracic

Adjective

 * 1)  Relating to the back and the thorax.

title: dorsothoracic


text: Dorstenia

title: Dorstenia


text:
fat sleeper

Noun

 * 1) The fish.

title: fat sleeper


text: fat sleepers

title: fat sleepers


text:
dorsoscapular

Adjective

 * 1) Relating to the back and the scapula.

title: dorsoscapular


text:
catukkaṇṇa

Etymology
. Cognate with 🇨🇬.

Adjective

 * 1) secret

title: catukkaṇṇa


text: tšaave

title: tšaave


text:
tšau

Noun

 * 1) boy

title: tšau


text:
X̄

Letter

 * 1) The letter X with a macron.

Symbol

 * 1)   in statistics.

title: X̄


text:
dungeon monitor

Noun

 * 1)  A person charged with supervising BDSM activities at a play party or a BDSM club.

title: dungeon monitor


text: dungeon monitors

title: dungeon monitors


text:
Bauboom

Etymology
From.

Noun

 * 1) A period of increased construction activity.

title: Bauboom


text: Baubooms

title: Baubooms


text:
spöka

Etymology
. Sense 4 is a.

Verb

 * 1)  to haunt
 * 2)  to be haunted
 * 3)  to haunt; to cause recurring unease or discomfort
 * 4)  to ghost (to leave a romantic or sexual relationship with no prior announcement)
 * 1)  to haunt; to cause recurring unease or discomfort
 * 2)  to ghost (to leave a romantic or sexual relationship with no prior announcement)
 * 1)  to ghost (to leave a romantic or sexual relationship with no prior announcement)
 * 1)  to ghost (to leave a romantic or sexual relationship with no prior announcement)

title: spöka


text: spökade

title: spökade


text: spökat

title: spökat


text: spökas

title: spökas


text: spökats

title: spökats


text: spökades

title: spökades


text: barefaced liars

title: barefaced liars


text: åhöraren

title: åhöraren


text: harbenyowre

title: harbenyowre


text: åhörarna

title: åhörarna


text: åhörarens

title: åhörarens


text: åhörarnas

title: åhörarnas


text: åhörares

title: åhörares


text:
tšeer

Noun

 * 1) house
 * 2) home

title: tšeer


text:
Chronobiologie

Etymology
From.

Noun

 * 1) chronobiology

title: Chronobiologie


text: Category:German terms prefixed with chrono-


text:
Reconstruction:Proto-Georgian-Zan/ṭlap-

Etymology
Probably. Compare the synonymous.

Noun

 * 1) mud

Descendants

 * Zan:
 * Zan:

title: Reconstruction:Proto-Georgian-Zan/ṭlap-


text:
mommy wars

Noun

 * 1)  Disputes between mothers over parenting methods, especially those between working mothers and stay-at-home mothers.

title: mommy wars


text: lydstaten

title: lydstaten


text: lydstater

title: lydstater


text: lydstaterna

title: lydstaterna


text: lydstats

title: lydstats


text: lydstatens

title: lydstatens


text: lydstaters

title: lydstaters


text: lydstaternas

title: lydstaternas


text: klientstaten

title: klientstaten


text: klientstater

title: klientstater


text: klientstaterna

title: klientstaterna


text:
Reconstruction:Proto-Georgian-Zan/lap-

Noun

 * 1) mud

Descendants

 * Zan:
 * Zan:

Reconstruction notes
For the suffix, compare.

Descendants

 * Zan:
 * Zan:

title: Reconstruction:Proto-Georgian-Zan/lap-


text: klientstats

title: klientstats


text: klientstatens

title: klientstatens


text: klientstaters

title: klientstaters


text: klientstaternas

title: klientstaternas


text: DDBL

title: DDBL


text: mommy war

title: mommy war


text: DDBLs

title: DDBLs


text: mummy wars

title: mummy wars


text: mummy war

title: mummy war


text:
Blumenfield

Etymology
Probably a variant of.

Statistics

 * According to data collected by Forebears in 2014, Blumenfield is the 142122nd most common surname in the United States, belonging to 159 individuals.

title: Blumenfield


text:
ტლაპო

Etymology
From.

Noun

 * 1) mud

title: ტლაპო


text:
־אַק

Etymology
Ultimately from. Compare 🇨🇬, 🇨🇬, 🇨🇬.

title: ־אַק


text:
Reconstruction:Proto-Kartvelian/ṭq̇wal-

Noun

 * 1) mud

Descendants

 * Proto-Georgian-Zan:
 * Zan:

title: Reconstruction:Proto-Kartvelian/ṭq̇wal-


text:
eksotis

Etymology
From, from , from , from , from.

Adjective

 * 1) exotic:
 * 2) foreign, especially in an exciting way.
 * 3) non-native to the ecosystem

title: eksotis


text: anapleurosis

title: anapleurosis


text: precizii

title: precizii


text: clusterizations

title: clusterizations


text:
nondermatologist

Noun

 * 1) A person who is not a dermatologist

title: nondermatologist


text: nondermatologists

title: nondermatologists


text:
ტყუ̂ალ

Etymology
From.

Noun

 * 1) silt, mud

title: ტყუ̂ალ


text: ტყუ̂ა̈ლ

title: ტყუ̂ა̈ლ


text:
meja hijau

Etymology
Compound of 🇰🇲.

Noun

 * 1)  green desk, green table.
 * 2)  court

title: meja hijau


text:
splenogonadal

Adjective

 * 1) Relating to the spleen and the gonads

Derived terms

 * splenogonadal fusion

title: splenogonadal


text:
suprapure

Adjective

 * 1) Very pure

title: suprapure


text: 电㐫

title: 电㐫


text:
asfodelowy

Etymology
From.

Adjective

 * 1)  asphodel

title: asfodelowy


text:
werbalizować

Etymology
Likely from +, from , from.

Verb

 * 1)  to put into words, to verbalize

title: werbalizować


text:
zwerbalizować

Etymology
From.

Verb

 * 1)  to put into words, to verbalize

title: zwerbalizować


text:
Talk:çekmek

Please consider indo-european etymology...

çek sounds very similar to slavonic ciąg/ciągnąć and germanic Zug/ziehen. It may be a coincidence, but it does not have to.

83.19.57.219 09:19, 12 February 2022 (UTC)

title: Talk:çekmek


text:
tuwal

Adjective

 * 1) unbalanced; unsymmetrical; askew

title: tuwal


text:
дев'яносто сьомий

Adjective

 * 1)  ninety-seventh

title: дев'яносто сьомий


text:
askarys

Etymology
Ultimately from.

Noun

 * 1)  askari

title: askarys


text:
פֿאַרקנעכטן

Verb

 * 1) to enslave

title: פֿאַרקנעכטן


text:
askarioza

Etymology
From.

Noun

 * 1) ascariasis

title: askarioza


text:
העמערל

Noun

 * 1) gavel wooden mallet
 * 1) gavel wooden mallet

title: העמערל


text:
askarydoza

Etymology
From, from.

Noun

 * 1) ascariasis

title: askarydoza


text:
rombituon

Etymology
From.

Noun

 * 1) star

Etymology
From.

Noun

 * 1) star

Etymology
From.

Noun

 * 1) star

title: rombituon


text:
nyliberalism

Noun

 * 1) neoliberalism
 * 2) libertarianism

title: nyliberalism


text: nyliberalismens

title: nyliberalismens


text: nyliberalisms

title: nyliberalisms


text: Category:Tobilung language

title: Category:Tobilung language


text: Category:Tobilung lemmas

title: Category:Tobilung lemmas


text:
inkomstskatt

Etymology
🇰🇲

Noun

 * 1) income tax

title: inkomstskatt


text: inkomstskatten

title: inkomstskatten


text: inkomstskatter

title: inkomstskatter


text: inkomstskatterna

title: inkomstskatterna


text: inkomstskatts

title: inkomstskatts


text: inkomstskattens

title: inkomstskattens


text: inkomstskatters

title: inkomstskatters


text: inkomstskatternas

title: inkomstskatternas


text:
lydigt

Adverb

 * 1) obediently

title: lydigt


text: lydigaste

title: lydigaste


text: lydigast

title: lydigast


text: lydigare

title: lydigare


text: lydiga

title: lydiga


text:
askaryda

Etymology
.

Noun

 * 1) roundworm, nematode

title: askaryda


text:
旁枝末節

Idiom

 * 1) trivial things

title: 旁枝末節


text: 旁枝末节

title: 旁枝末节


text: Category:Coastal Kadazan terms with usage examples


text: Category:Tobilung nouns

title: Category:Tobilung nouns


text: Category:Tobilung terms derived from Proto-Malayo-Polynesian


text: Category:Tobilung terms inherited from Proto-Malayo-Polynesian


text: Category:Tobilung inherited terms

title: Category:Tobilung inherited terms


text: Category:Tobilung terms by etymology

title: Category:Tobilung terms by etymology


text: Category:Coastal Kadazan entry maintenance


text:
askeza

Etymology
Ultimately from.

title: askeza


text:
生辰八字

Noun

 * 1) eight characters that indicate the year, month, date and double-hour of one's birth, used in fortune-telling

title: 生辰八字


text:
askogon

Etymology

 * compare 🇨🇬, ultimately from +.

Noun

 * 1)  ascogonium

title: askogon


text: kunnigaste

title: kunnigaste


text:
時辰八字

Noun

 * 1) eight characters that indicate the year, month, date and double-hour of one's birth, used in fortune-telling
 * 2)  time

title: 時辰八字


text: 时辰八字

title: 时辰八字


text:
kunnigt

Adverb

 * 1) expertly, knowledgeably

title: kunnigt


text: Grossenbrode

title: Grossenbrode


text:
askorbinowy

Etymology
From either or. .

Adjective

 * 1)  ascorbic

title: askorbinowy


text:
harmistus

Noun

 * 1) annoyance, vexation, upsetness being annoyed, vexed or upset

title: harmistus


text:
havutus

Noun

 * 1) lining or decorating with sprigs of coniferous trees

title: havutus


text:
heinäys

Noun

 * 1) removing or killing grass around saplings

title: heinäys


text: hoosaus

title: hoosaus


text:
hyppyytys

Noun

 * 1) making something jump or bounce

title: hyppyytys


text: hönkäys

title: hönkäys


text:
kahnaus

Noun

 * 1) bickering, squabbling
 * 2) rubbing oneself against something

title: kahnaus


text:
kahvaus

Noun

 * 1)  impeding with the stick

title: kahvaus


text:
kakutus

Noun

 * 1) pieing

title: kakutus


text:
karhotus

Noun

 * 1) windrowing

title: karhotus


text:
kiinteytys

Noun

 * 1) solidifying making solid
 * 2) toning developing a physique with a large emphasis on musculature

title: kiinteytys


text:
kotoistus

Noun

 * 1) localizing, localization

title: kotoistus


text:
kotoutus

Noun

 * 1) integration of immigrants into a new society

title: kotoutus


text:
kukitus

Noun

 * 1) decorating with flowers

title: kukitus


text:
kurssitus

Noun

 * 1) providing or organizing courses for training

title: kurssitus


text:
kuumotus

Noun

 * 1) being barely visible, glimmering, looming

Noun

 * 1) feeling hot
 * 2)  feeling hot due to being nervous

title: kuumotus


text:
laidunnus

Noun

 * 1) grazing, pasturing

title: laidunnus


text:
loimitus

Noun

 * 1) rugging, covering a horse with a rug or blanket

title: loimitus


text:
maistatus

Noun

 * 1) organizing taste testing

title: maistatus


text:
muotitus

Noun

 * 1) casting into a mould/mold

title: muotitus


text:
mupellus

Noun

 * 1) munching on

title: mupellus


text:
mussutus

Noun

 * 1) eating loudly

title: mussutus


text:
möläytys

Noun

 * 1) blurting (out)

title: möläytys


text:
nillitys

Noun

 * 1) complaining, whining

title: nillitys


text:
nupoutus

Noun

 * 1) dehorning livestock

title: nupoutus


text:
näkyvöitys

Noun

 * 1) making (more) visible
 * 2)  targeting

title: näkyvöitys


text:
pirskotus

Noun

 * 1) spurting, spattering, sprinkling

title: pirskotus


text:
pisteitys

Noun

 * 1) marking with dots

title: pisteitys


text:
pisteytys

Noun

 * 1) scoring assigning score to

title: pisteytys


text: pitennys

title: pitennys


text:
Großenbrode

Proper noun

 * , Germany.

title: Großenbrode


text:
Citations:Kumtag

 * 2020, Anna Sherman, A Poetic Journey Through Western China, (11 May 2020);
 * The Kumtag is a little desert (9,000 square miles) between the Taklamakan Desert (130,000 square miles) and the great Gobi (500,000 square miles), which covers much of northern China and southern Mongolia.

title: Citations:Kumtag


text: Citations:Kumtag Desert

title: Citations:Kumtag Desert


text:
Citations:Taklamakan Desert

 * 2020, Anna Sherman, A Poetic Journey Through Western China, (11 May 2020);
 * The Kumtag is a little desert (9,000 square miles) between the Taklamakan Desert (130,000 square miles) and the great Gobi (500,000 square miles), which covers much of northern China and southern Mongolia.

title: Citations:Taklamakan Desert


text:
Citations:Gobi

 * 2020, Anna Sherman, A Poetic Journey Through Western China, (11 May 2020);
 * The Kumtag is a little desert (9,000 square miles) between the Taklamakan Desert (130,000 square miles) and the great Gobi (500,000 square miles), which covers much of northern China and southern Mongolia.
 * The Kumtag is a little desert (9,000 square miles) between the Taklamakan Desert (130,000 square miles) and the great Gobi (500,000 square miles), which covers much of northern China and southern Mongolia.

title: Citations:Gobi


text:
fodord

Etymology
From.

Noun

 * 1) muttering, murmuring, complaining
 * "sga"
 * "sga"

- Is peccad díabul lesom .i. fodord doïb di dommatu, ⁊ du·fúairthed ní leu fora sáith din main, ⁊ todlugud inna féulæ ɔ amairis nánda·tibérad Día doïb, ⁊ nach coimnacuir ⁊ issi dano insin ind frescissiu co fochaid.

title: fodord


text: mastography

title: mastography


text:
batalan

Etymology
From.

Noun

 * 1) roofless bamboo platform built at the rear of a nipa or cogon house

Etymology
From. Compare 🇨🇬, 🇨🇬, 🇨🇬, 🇨🇬, and 🇨🇬.

Noun

 * 1) roofless bamboo platform built at the rear of a nipa or cogon house

title: batalan


text:
Kumtag Desert

Translations

 * Chinese:
 * Mandarin:
 * Japanese:
 * Korean:

title: Kumtag Desert


text:
alipuros

Noun

 * 1) cyclone; tornado; whirlwind

title: alipuros


text: Braidwoods

title: Braidwoods


text:
дев'яносто восьмий

Adjective

 * 1)  ninety-eighth

title: дев'яносто восьмий


text: Kumtag

title: Kumtag


text:
дев'яносто дев'ятий

Adjective

 * 1)  ninety-ninth

title: дев'яносто дев'ятий