Module:User:Benwing2/category tree/poscatboiler/data/terms by etymology

local labels = {} local raw_categories = {} local handlers = {} local raw_handlers = {}

- --                                                                        -- --                                  LABELS                                 -- --                                                                        -- -

labels["terms by etymology"] = { description = " terms categorized by their etymologies.", umbrella_parents = "Fundamental", parents = , }

labels["AABB-type reduplications"] = { description = " terms that underwent reduplication in an AABB pattern.", parents = {"reduplications"}, }

labels["alliterative compounds"] = { description = " noun phrases composed of two or more stems that alliterate.", umbrella_parents = "Types of compound words by language", parents = {"compound words", "alliterative phrases"}, }

labels["antonymous compounds"] = { description = " compounds in which one part is an antonym of the other.", umbrella_parents = "Types of compound words by language", parents = {"dvandva compounds", sort = "antonym"}, }

labels["back-formations"] = { description = " words formed by reversing a supposed regular formation, removing part of an older term.", parents = {"terms by etymology"}, }

labels["bahuvrihi compounds"] = { description = " compounds in which the first part (A) modifies the second (B), and whose meaning follows a metonymic pattern: “ having a B that is A.”", umbrella_parents = "Types of compound words by language", parents = {"compound words", "exocentric compounds"}, }

labels["blends"] = { description = " words formed by combinations of other words.", parents = {"terms by etymology"}, }

labels["borrowed terms"] = { description = " terms that are loanwords, i.e. words that were directly incorporated from another language.", parents = {"terms by etymology"}, }

labels["calques"] = { description = " calques, i.e. terms formed by piece-by-piece translations of terms from other languages.", parents = {"terms by etymology"}, }

labels["catachreses"] = { description = " terms derived from misuses or misapplications of other terms.", parents = {"terms by etymology"}, }

labels["coinages"] = { description = " terms coined by an identifiable person, organization or other such entity.", parents = {"terms attributed to a specific source"}, umbrella_parents = {name = "terms attributed to a specific source", is_label = true, sort = " "}, }

-- Add "compound POS" categories for various parts of speech.

local compound_poses = { "adjectives", "adverbs", "conjunctions", "determiners", "interjections", "nouns", "numerals", "particles", "postpositions", "prefixes", "prepositions", "pronouns", "proper nouns", "suffixes", "verbs", }

for _, pos in ipairs(compound_poses) do labels["compound " .. pos] = { description = " " .. pos .. " composed of two or more stems.", umbrella_parents = "Types of compound words by language", parents = {{name = "compound words", sort = " "}, pos}, } end

labels["compound determinatives"] = { description = " determinatives composed of two or more stems.", parents = {"compound words", "determiners"}, }

labels["compound words"] = { description = " words composed of two or more stems.", parents = {"terms by etymology"}, }

labels["coordinated pairs"] = { description = "Terms in consisting of a pair of terms joined by a coordinating conjunction.", parents = {"terms by etymology"}, }

labels["coordinated triples"] = { -- Avoid saying "a coordinating conjunction" or "coordinating conjunctions" -- because there can be either one or two conjunctions. description = "Terms in consisting of three terms joined by coordinating conjunction.", parents = {"terms by etymology"}, }

labels["denominals"] = { description = " terms derived from a noun.", parents = {"terms by etymology"}, }

labels["deverbals"] = { description = " terms derived from a verb.", parents = {"terms by etymology"}, }

labels["doublets"] = { description = " terms that trace their etymology from ultimately the same source as other terms in the same language, but by different routes, and often with subtly or substantially different meanings.", parents = {"terms by etymology"}, }

labels["dvandva compounds"] = { description = " words composed of two or more stems whose stems could be connected by an 'and'.", umbrella_parents = "Types of compound words by language", parents = {"compound words"}, }

labels["elongated forms"] = { description = " terms where one or more letters or sounds is repeated for emphasis or effect.", parents = {"terms by etymology"}, }

labels["endocentric compounds"] = { description = " words composed of two or more stems, one of which is the head of that compound.", umbrella_parents = "Types of compound words by language", parents = {"compound words"}, }

labels["endocentric noun-noun compounds"] = { description = " words composed of two or more stems, one of which is the head of that compound.", umbrella_parents = "Types of compound words by language", parents = {"endocentric compounds", "compound words"}, }

labels["endocentric verb-noun compounds"] = { description = " compounds in which the first element is a verbal stem, the second a nominal stem and the head of the compound.", umbrella_parents = "Types of compound words by language", parents = {"endocentric compounds", "verb-noun compounds"}, }

labels["eponyms"] = { description = " terms derived from names of real or fictitious people.", parents = {"terms by etymology"}, }

labels["exocentric compounds"] = { description = " words composed of two or more stems, none of which is the head of that compound.", umbrella_parents = "Types of compound words by language", parents = {"compound words"}, }

labels["exocentric verb-noun compounds"] = { description = " compounds in which the first element is a transitive verb, the second a noun functioning as its direct object, and whose referent is the person or thing doing the action.", umbrella_parents = "Types of compound words by language", parents = {"exocentric compounds", "verb-noun compounds"}, }

labels["genericized trademarks"] = { description = " terms that originate from trademarks, brands and company names which have become genericized; that is, fallen into common usage in the target market's vernacular, even when referring to other competing brands.", parents = {"terms by etymology"}, }

labels["ghost words"] = { description = " terms that were originally erroneous or fictitious, published in a reference work as if they were genuine as a result of typographical error, misreading, misinterpretation or another process.", parents = {"terms by etymology"}, }

labels["karmadharaya compounds"] = { description = " words composed of two or more stems in which the main stem determines the case endings.", umbrella_parents = "Types of compound words by language", parents = {"tatpurusa compounds"}, }

labels["haplological forms"] = { description = " terms that underwent haplology: thus, their origin involved a loss or omission of a repeated sequence of sounds.", parents = {"terms by etymology"}, }

labels["homophonic translations"] = { description = " terms that were borrowed by matching the etymon phonetically, without regard for the sense; compare phono-semantic matching and Hobson-Jobson.", parents = {"terms by etymology"} }

labels["hybridisms"] = { description = " words formed by elements of different linguistic origins.", parents = {"terms by etymology"}, }

labels["inherited terms"] = { description = " terms that were inherited from an earlier stage of the language.", parents = {"terms by etymology"}, }

labels["itaretara dvandva compounds"] = { description = " words composed of two or more stems whose stems could be connected by an 'and'.", umbrella_parents = "Types of compound words by language", parents = {"dvandva compounds"}, }

labels["learned borrowings"] = { description = " terms that are learned loanwords, that is, words that were directly incorporated from another language instead of through normal language contact.", parents = {"borrowed terms"}, }

labels["legal doublets"] = { description = " legal doublets – a legal doublet is a standardized phrase commonly use in legal documents, proceedings etc which includes two words that are near synonyms.", parents = {"coordinated pairs"}, }

labels["merisms"] = { description = " merisms – terms that are coordinates that, combined, are a synonym for a totality.", parents = {"coordinated pairs"}, }

labels["metonyms"] = { description = " terms whose origin involves calling a thing or concept not by its own name, but by the name of something intimately associated with that thing or concept.", parents = {"terms by etymology"}, }

labels["neologisms"] = { description = " terms that have been only recently acknowledged.", parents = {"terms by etymology"}, }

labels["nonce terms"] = { description = " terms that have been invented for a single occasion.", parents = {"terms by etymology"}, }

labels["onomatopoeias"] = { description = " words that were coined to sound like what they represent.", parents = {"terms by etymology"}, }

labels["orthographic borrowings"] = { description = " orthographic loans, i.e. terms that were borrowed in their script forms, not their pronunciations.", parents = {"borrowed terms"}, }

labels["partial calques"] = { description = " partial calques, i.e. terms formed partly by piece-by-piece translations of terms from other languages and partly by direct borrowing.", parents = {"terms by etymology"}, }

labels["phono-semantic matchings"] = { description = " terms that were borrowed by matching the etymon phonetically and semantically.", parents = {"borrowed terms"}, }

labels["piecewise doublets"] = { description = " terms that are piecewise doublets.", parents = {"terms by etymology"}, }

labels["pseudo-loans"] = { description = " terms that are pseudo-loans.", parents = {"terms by etymology"}, }

for _, ism_and_langname in ipairs({	{"anglicisms", "English"},	{"Gallicisms", "French"},	{"Germanisms", "German"},	{"Hispanisms", "Spanish"},	{"Italianisms", "Italian"},	{"Latinisms", "Latin"}, }) do	local ism, langname = unpack(ism_and_langname) labels["pseudo-" .. ism] = { description = " terms that appear to be " .. langname .. ", but are not used or have a different meaning in " .. langname .. " itself.", parents = {"pseudo-loans"}, umbrella_parents = {name = "pseudo-loans", is_label = true, sort = " "}, } end

labels["rebracketings"] = { description = " terms that have interacted with another word in such a way that the boundary between the words has been modified.", parents = {"terms by etymology"} }

labels["reconstructed terms"] = { description = " terms that are not directly attested, but have been reconstructed through other evidence.", parents = {"terms by etymology"} }

labels["reduplicated coordinated pairs"] = { description = " reduplicated coordinated pairs.", parents = {"coordinated pairs", "reduplications"}, }

labels["reduplicated coordinated triples"] = { description = " reduplicated coordinated triples.", parents = {"coordinated triples", "reduplications"}, }

labels["reduplications"] = { description = " terms that underwent reduplication, so their origin involved a repetition of roots or stems.", parents = {"terms by etymology"}, }

labels["retronyms"] = { description = " terms that serve as new unique names for older objects or concepts whose previous names became ambiguous.", parents = {"terms by etymology"}, }

labels["rhyming compounds"] = { description = " noun phrases composed of two or more stems that rhyme.", umbrella_parents = "Types of compound words by language", parents = {"compound words", "rhyming phrases"}, }

labels["roots"] = { description = "Basic morphemes from which words are formed.", parents = {"morphemes"}, }

labels["roots by shape"] = { description = " roots categorized by their shape.", parents = , }

labels["samahara dvandva compounds"] = { description = " words composed of two or more stems whose stems could be connected by an 'and'.", umbrella_parents = "Types of compound words by language", parents = {"dvandva compounds"}, }

labels["semantic loans"] = { description = " terms one or more of whose definitions was borrowed from a term in another language.", parents = {"terms by etymology"}, }

labels["semi-learned borrowings"] = { description = " terms that are semi-learned loanwords, that is, words borrowed from a classical language into a modern language and partly reshaped based on later sound changes or by analogy with inherited words in the language.", parents = {"borrowed terms"}, }

labels["spelled-out initialisms"] = { description = " initialisms in which the letter names are spelled out.", parents = {"terms by etymology"}, }

labels["spelling pronunciations"] = { description = " terms whose pronunciation was historically or presently affected by their spelling.", parents = {"terms by etymology"}, }

labels["spoonerisms"] = { description = " terms in which the initial sounds of component parts have been exchanged, as in \"crook and nanny\" for \"nook and cranny\".", parents = {"terms by etymology"}, }

labels["synonymous compounds"] = { description = " compounds in which one part is a synonym of the other.", umbrella_parents = "Types of compound words by language", parents = {"dvandva compounds", sort = "synonym"}, }

labels["tatpurusa compounds"] = { description = " words composed of two or more stems", umbrella_parents = "Types of compound words by language", parents = {"compound words"}, }

labels["terms attributed to a specific source"] = { description = " terms coined by an identifiable person or deriving from a known work.", parents = {"terms by etymology"}, }

labels["terms derived from area codes"] = { description = " terms derived from area codes.", parents = {"terms by etymology"}, }

labels["terms derived from the shape of letters"] = { description = " terms derived from the shape of letters. This can include terms derived from the shape of any letter in any alphabet.", parents = {"terms by etymology"}, }

labels["terms by Proto-Indo-European word"] = { description = " terms categorized by the Proto-Indo-European word they originate from.", parents = {"terms by etymology", "terms derived from Proto-Indo-European"}, }

labels["terms by root"] = { description = " terms categorized by the root they originate from.", parents = {"terms by etymology", {name = "roots", sort = " "}}, }

labels["terms derived from fiction"] = { description = " terms that originate from works of fiction.", parents = {"terms attributed to a specific source"}, }

for _, source_and_desc in ipairs({	{"DC Comics", "DC Comics"},	{"Duckburg and Mouseton", "Disney's Duckburg and Mouseton universe"},	{"Harry Potter", "the Harry Potter series"},	{"Nineteen Eighty-Four", "George Orwell's Nineteen Eighty-Four"},	{"Star Trek", "Star Trek"},	{"Star Wars", "Star Wars"},	{"The Simpsons", "The Simpsons"},	{"Tolkien's legendarium", "the legendarium of J. R. R. Tolkien"}, }) do	local source, desc = unpack(source_and_desc) labels["terms derived from " .. source] = { description = " terms that originate from " .. desc .. ".",		parents = {"terms derived from fiction"}, } end

labels["terms derived from occupations"] = { description = " terms derived from names of occupations.", parents = {"terms by etymology"}, }

labels["terms derived from other languages"] = { description = " terms that originate from other languages.", parents = {"terms by etymology"}, }

labels["terms derived from the Bible"] = { description = " terms that originate from the Bible.", parents = {"terms attributed to a specific source"}, }

labels["terms derived from toponyms"] = { description = " terms derived from names of real or fictitious places.", parents = {"terms by etymology"}, }

labels["terms making reference to character shapes"] = { description = " terms making reference to character shapes.", parents = {"terms by etymology"}, }

labels["terms with Indo-Aryan extensions"] = { description = " terms extended with particular Indo-Aryan pleonastic affixes.", parents = {"terms by etymology"}, }

labels["terms with lemma and non-lemma form etymologies"] = { description = " terms consisting of both a lemma and non-lemma form, of different origins.", breadcrumb = "lemma and non-lemma form", parents = {"terms with multiple etymologies"}, }

labels["terms with multiple etymologies"] = { description = " terms that are derived from multiple origins.", parents = {"terms by etymology"}, }

labels["terms with multiple lemma etymologies"] = { description = " lemmas that are derived from multiple origins.", breadcrumb = "multiple lemmas", parents = {"terms with multiple etymologies"}, }

labels["terms with multiple non-lemma form etymologies"] = { description = " non-lemma forms that are derived from multiple origins.", breadcrumb = "multiple non-lemma forms", parents = {"terms with multiple etymologies"}, }

labels["terms with unknown etymologies"] = { description = " terms whose etymologies have not yet been established.", parents = , }

labels["twice-borrowed terms"] = { description = " terms that were borrowed from another language that originally borrowed the term from .", parents = {"terms by etymology", "borrowed terms"}, }

labels["unadapted borrowings"] = { description = " loanwords that have not been conformed to the morpho-syntactic, phonological and/or phonotactical rules of the target language.", parents = {"borrowed terms"}, }

labels["univerbations"] = { description = " terms that result from the agglutination of two or more words.", parents = {"terms by etymology"}, }

labels["verb-noun compounds"] = { description = " compounds in which the first element is a transitive verb, the second a noun functioning as its direct object, and whose referent is the person or thing doing the action.", umbrella_parents = "Types of compound words by language", parents = {"compound nouns"}, }

labels["vyadhikarana compounds"] = { description = " words composed of two or more stems in which the non-main stem determines the case endings.", umbrella_parents = "Types of compound words by language", parents = {"tatpurusa compounds"}, }

labels["words derived through metathesis"] = { description = " words that were created through metathesis from another word.", parents = , }

for _, fixtype in ipairs({"circumfix", "infix", "interfix", "prefix", "suffix",}) do labels["words by " .. fixtype] = { description = " words categorized by their " .. fixtype .. "es.", parents = {{name = "terms by etymology", sort = fixtype}, fixtype .. "es"}, } end

-- Add 'umbrella_parents' key if not already present. for key, data in pairs(labels) do	if not data.umbrella_parents then data.umbrella_parents = "Terms by etymology subcategories by language" end end

- --                                                                        -- --                              RAW CATEGORIES                             -- --                                                                        -- -

raw_categories["Terms by etymology subcategories by language"] = { description = "Umbrella categories covering topics related to terms categorized by their etymologies, such as types of compounds or borrowings.", additional = "", parents = { "Umbrella metacategories", {name = "terms by etymology", is_label = true, sort = " "}, }, }

raw_categories["Borrowed terms subcategories by language"] = { description = "Umbrella categories covering topics related to borrowed terms.", additional = "", parents = { "Umbrella metacategories", {name = "borrowed terms", is_label = true, sort = " "}, {name = "Terms by etymology subcategories by language", sort = " "}, }, }

raw_categories["Inherited terms subcategories by language"] = { description = "Umbrella categories covering topics related to inherited terms.", additional = "", parents = { "Umbrella metacategories", {name = "inherited terms", is_label = true, sort = " "}, {name = "Terms by etymology subcategories by language", sort = " "}, }, }

raw_categories["Indo-Aryan extensions"] = { description = "Umbrella categories covering terms extended with particular Indo-Aryan pleonastic affixes.", additional = "", parents = { "Umbrella metacategories", {name = "Terms by etymology subcategories by language", sort = " "}, }, }

raw_categories["Multiple etymology subcategories by language"] = { description = "Umbrella categories covering topics related to terms with multiple etymologies.", additional = "", parents = { "Umbrella metacategories", {name = "Terms by etymology subcategories by language", sort = " "}, }, }

raw_categories["Types of compound words by language"] = { description = "Umbrella categories covering topics related to types of compound words.", additional = "", parents = { "Umbrella metacategories", {name = "compound words", is_label = true, sort = " "}, {name = "Terms by etymology subcategories by language", sort = " "}, }, }

- --                                                                        -- --                                 HANDLERS                                -- --                                                                        -- -

- --- Root handlers --- -

-- Handlers for 'terms derived from the SOURCE root ROOT' must go *BEFORE* the -- more general 'terms derived from SOURCE' handler.

local function get_source_and_type_desc(source, term_type) if source:getCode == "ine-pro" and term_type:find("^roots?$") then return "Proto-Indo-European " .. term_type .. "" else return "" .. source:getCanonicalName .. " " .. term_type end end

-- Handler for e.g. Category:Yola terms derived from the Proto-Indo-European root *h₂el- (grow) and -- Category:Russian terms derived from the Proto-Indo-European word *swé, and corresponding umbrella -- categories Category:Terms derived from the Proto-Indo-European root *h₂el- (grow) and -- Category:Terms derived from the Proto-Indo-European word *swé. Replaces the former -- Module:category tree/PIE root cat, Module:category tree/root cat and Template:PIE word cat. table.insert(handlers, function(data)	local source_name, term_type, term_and_id = data.label:match("^terms derived from the (.+) (root) (.+)$")	if not source_name then		source_name, term_type, term_and_id = data.label:match("^terms derived from the (.+) (word) (.+)$")	end	if not source_name then		source_name, term_type, term_and_id = data.label:match("^terms derived from the (.+) (term) (.+)$")	end

if source_name then local term, id = term_and_id:match("^(.+) %((.-)%)$") term = term or term_and_id local source = require("Module:languages").getByCanonicalName(source_name, true, "allow etym langs")

local parents = { { name = "terms by " .. source_name .. " " .. term_type, sort = source:makeSortKey(term) } }		local umbrella_parents = { { name = "Terms derived from " .. source_name .. " " .. term_type .. "s", sort = source:makeSortKey(term) } }		if id then table.insert(parents, { name = "terms derived from the " .. source_name .. " " .. term_type .. " " .. term, sort = " "}) table.insert(umbrella_parents, { name = "terms derived from the " .. source_name .. " " .. term_type .. " " .. term, is_label = true, sort = " "}) end -- Italicize the root/word in the title. local function displaytitle(title, lang) return require("Module:string").plain_gsub(title, term, require("Module:script utilities").tag_text(term, source, nil, "term")) end local breadcrumb = require("Module:script utilities").tag_text(term, source, nil, "term") .. (id and " (" .. id .. ")" or "") return { description = " terms that originate ultimately from the " .. get_source_and_type_desc(source, term_type) .. " " ..				require("Module:links").full_link({ term = term, lang = source, gloss = id, id = id }, "term") .. ".",			displaytitle = displaytitle, breadcrumb = breadcrumb, parents = parents, umbrella = { no_by_language = true, displaytitle = displaytitle, breadcrumb = breadcrumb, parents = umbrella_parents, }		}	end end)

table.insert(handlers, function(data)	local root_and_id = data.label:match("^terms belonging to the root (.+)$")	if root_and_id then		local root, id = root_and_id:match("^(.+) %((.-)%)$")		root = root or root_and_id

-- See if the language is Semitic. local fam = data.lang local is_semitic = false while true do			if not fam then break end if fam:getCode == "qfa-not" then -- qfa-not is "not a family" and is its own parent break end if fam:getCode == "sem" then is_semitic = true break end fam = fam:getFamily end local root_desc = is_semitic and "root" or "root" local parents = local separators = "־ %-" local separator_c = "[" .. separators .. "]"		local not_separator_c = "[^" .. separators .. "]"		-- remove any leading or trailing separators (e.g. in PIE-style roots) local root_no_prefix_suffix = mw.ustring.gsub(mw.ustring.gsub(root, separator_c .. "$", ""), "^" .. separator_c, "") local num_sep = mw.ustring.len(mw.ustring.gsub(root_no_prefix_suffix, not_separator_c, "")) local linked_root = data.lang and require("Module:links").full_link({ term = root, lang = data.lang, gloss = id, id = id }, "term") or root if num_sep > 0 then table.insert(parents, {name = "" .. (num_sep + 1) .. "-letter roots", sort = root_and_id}) end -- Italicize the root/word in the title. local function displaytitle(title, lang) return require("Module:string").plain_gsub(title, root, require("Module:script utilities").tag_text(root, lang, nil, "term")) end local breadcrumb = require("Module:script utilities").tag_text(root, data.lang, nil, "term") .. (id and " (" .. id .. ")" or "") return { description = " terms that belong to the " .. root_desc .. " " .. linked_root .. ".",			displaytitle = displaytitle, breadcrumb = breadcrumb, parents = parents, umbrella = false, }	end end)

table.insert(handlers, function(data)	local num_letters = data.label:match("^([0-9]+)-letter roots$")	if num_letters then		return {			description = " roots with " .. num_letters .. " letters in them.",			parents = ,			umbrella_parents = "Terms by etymology subcategories by language",		}	end end)

table.insert(handlers, function(data)	local source_name = data.label:match("^terms by (.+) root$")	if source_name then		local source = require("Module:languages").getByCanonicalName(source_name, true, "allow etym langs")		local parents = {"terms by etymology"}		-- In Category:Proto-Indo-Iranian terms by Proto-Indo-Iranian root,		-- don't add parent Category:Proto-Indo-Iranian terms derived from Proto-Indo-Iranian.		if not data.lang or data.lang:getCode ~= source:getCode then			table.insert(parents, "terms derived from " .. source_name)		end		return {			description = " terms categorized by the " .. get_source_and_type_desc(source, "root") .. " they originate from.",			parents = parents,			umbrella_parents = "Terms by etymology subcategories by language",		}	end end)

table.insert(handlers, function(data)	local root_shape = data.label:match("^(.+)-shape roots$")	if root_shape then		local description = " roots with the shape " .. root_shape .. "."		local additional		if data.lang and data.lang:getCode == "ine-pro" then			additional = [=[		end		return {			description = description,			additional = additional,			breadcrumb = root_shape,			parents = ,			umbrella = false,		}	end end)
 * e stands for the vowel of the root.
 * C stands for any stop or s.
 * R stands for any resonant.
 * H stands for any laryngeal.
 * M stands for m or w, when followed by a resonant.
 * s stands for s, when next to a stop.]=]

- Derived/inherited/borrowed handlers -

-- Handler for categories of the form "LANG terms derived from SOURCE", where SOURCE is a language, etymology language -- or family (e.g. "Indo-European languages"), along with corresponding umbrella categories of the form -- "Terms derived from SOURCE". table.insert(handlers, function(data)	local source_name = data.label:match("^terms derived from (.+)$")	if source_name then		-- FIXME, should we allow 'terms derived from taxonomic names' when mul-tax has canonical name		-- 'taxonomic name'? This is equivalent to what Module:category tree/derived cat did.		-- Maybe fix mul-tax instead.		local source = require("Module:languages").getByCanonicalName(source_name, true, "allow etym langs", "allow families")		local source_desc = source:makeCategoryLink

-- Compute description. local desc = " terms that originate from " .. source_desc .. "."		local additional if source:getType == "family" then additional = "This category should, ideally, contain only other categories. Entries can be categorized here, too, when the proper subcategory is unclear. " .. "If you know the exact language from which an entry categorized here is derived, please edit its respective entry." end -- Compute parents. local derived_from_subvariety_of_self = false local parent local sortkey = source:getDisplayForm if source:getType == "etymology language" then local parcode = source:getParentCode if parcode and parcode ~= "qfa-iso" and parcode ~= "qfa-not" and parcode ~= "qfa-und" then if data.lang and parcode == data.lang:getCode then derived_from_subvariety_of_self = true parent = data.lang:getFamily:getDisplayForm else -- Etymology language parent may be regular language, etymology language, -- or family parent = require("Module:languages").getByCode(parcode, true,						"allow etym langs", "allow families"):getDisplayForm end end else -- regular language or family local fam = source:getFamily if fam and fam:getCode ~= "qfa-iso" and fam:getCode ~= "qfa-not" then parent = fam:getDisplayForm end end parent = parent and "terms derived from " .. parent or "terms derived from other languages" local parents = if derived_from_subvariety_of_self then table.insert(parents, "Category:Categories for terms in a language derived from a term in a subvariety of that language") end

-- Compute umbrella parents. local umbrella_parents = { source:getType == "family" and {name = source:getCategoryName, raw = true, sort = " "} or source:getType == "etymology language" and {name = "Category:" .. mw.getContentLanguage:ucfirst(source:getCategoryName), sort = "terms derived from"} or			{name = source:getCategoryName, raw = true, sort = "terms derived from"} }

return { description = desc, additional = additional, breadcrumb = source_name, parents = parents, umbrella = { no_by_language = true, description = "Categories with terms that originate from " .. source_desc .. ".",				parents = umbrella_parents, },		}	end end)

local function get_source_and_source_desc(source_name) local source = require("Module:languages").getByCanonicalName(source_name, true, "allow etym langs", "allow families") local source_desc = source:makeCategoryLink if source:getType == "family" then source_desc = "unknown " .. source_desc end return source, source_desc end

-- Handler for categories of the form "LANG terms inherited/borrowed from SOURCE", where SOURCE is a language, -- etymology language or family (e.g. "Indo-European languages"). Also handles umbrella categories of the form -- "Terms inherited/borrowed from SOURCE". local function inherited_borrowed_handler(etymtype) return function(data) local source_name = data.label:match("^terms " .. etymtype .. " from (.+)$") if source_name then local source, source_desc = get_source_and_source_desc(source_name) return { description = " terms " .. etymtype .. " from " .. source_desc .. ".",				breadcrumb = source_name, parents = { { name = etymtype .. " terms", sort = source_name }, { name = "terms derived from " .. source_name, sort = " "}, },				umbrella = { no_by_language = true, parents = { { name = "terms derived from " .. source_name, is_label = true, sort = " " }, etymtype == "inherited" and { name = "Inherited terms subcategories by language", sort = source_name } -- There are several types of borrowings mixed into the following holding category, -- so keep these ones sorted under 'Terms borrowed from SOURCE_NAME' instead of just -- 'SOURCE_NAME'. or "Borrowed terms subcategories by language", }				},			}		end end end

table.insert(handlers, inherited_borrowed_handler("borrowed")) table.insert(handlers, inherited_borrowed_handler("inherited"))

- Borrowing subtype handlers - -

local function borrowing_subtype_handler(source_name, parent_cat, desc, no_by_language) local source, source_desc = get_source_and_source_desc(source_name) return { description = " " .. desc:gsub("SOURCE", source_desc), breadcrumb = source_name, parents = { { name = parent_cat, sort = source_name }, { name = "terms borrowed from " .. source_name, sort = " " }, },		umbrella = { no_by_language = no_by_language, parents = { { name = "terms borrowed from " .. source_name, is_label = true, sort = " " }, "Borrowed terms subcategories by language", }		},	} end

local borrowing_descriptions = { ["learned borrowings"] = "terms that are learned loanwords from SOURCE, that is, words that were directly incorporated from SOURCE instead of through normal language contact.", ["semi-learned borrowings"] = "terms that are semi-learned loanwords from SOURCE, that is, words borrowed from SOURCE (a classical language) into the target language (a modern language) and partly reshaped based on later sound changes or by analogy with inherited words in the language.", ["orthographic borrowings"]	= "terms that are orthographic loans from SOURCE, i.e. words that were borrowed from SOURCE in their script forms, not their pronunciations.", ["unadapted borrowings"] = "loanwords from SOURCE that have not been conformed to the morpho-syntactic, phonological and/or phonotactical rules of the target language.", }

table.insert(handlers, function(data)	local borrowing_type, source_name = data.label:match("^(.+ borrowings) from (.+)$")	if borrowing_type then		return borrowing_subtype_handler(source_name, borrowing_type, borrowing_descriptions[borrowing_type])	end end)

table.insert(handlers, function(data)	local source_name = data.label:match("^semantic loans from (.+)$")	if source_name then		return borrowing_subtype_handler(source_name, "semantic loans", "terms that are semantic loans from SOURCE.", "no by language")	end end)

table.insert(handlers, function(data)	local source_name = data.label:match("^terms partially calqued from (.+)$")	if source_name then		return borrowing_subtype_handler(source_name, "partial calques", "terms that were partially calqued from SOURCE.", "no by language")	end end)

table.insert(handlers, function(data)	local source_name = data.label:match("^terms calqued from (.+)$")	if source_name then		return borrowing_subtype_handler(source_name, "calques", "terms that were calqued from SOURCE.", "no by language")	end end)

table.insert(handlers, function(data)	local source_name = data.label:match("^phono%-semantic matchings from (.+)$")	if source_name then		return borrowing_subtype_handler(source_name, "phono-semantic matchings", "terms that are phono-semantic matchings from SOURCE.", "no by language")	end end)

- -- Affix handlers --- -

table.insert(handlers, function(data)	local labelpref, pos, affixtype, term_and_id = data.label:match("^(([a-z -]+) ([a-z]+fix)ed with )(.+)$")	if affixtype then		local term, id = term_and_id:match("^(.+) %(([^]+)%)$")		term = term or term_and_id

-- Convert term/alt into affixes if needed local desc = { ["prefix"]		= "beginning with the prefix", ["suffix"]		= "ending with the suffix", ["circumfix"]	= "bookended with the circumfix", ["infix"]		= "spliced with the infix", ["interfix"]	= "joined with the interfix", ["transfix"]	= "patterned with the transfix", }		if not desc[affixtype] then return nil end

local params = { ["alt"] = {}, ["sc"] = {}, ["sort"] = {}, ["tr"] = {}, }		local args = require("Module:parameters").process(data.args, params) local sc = data.sc or args.sc and require("Module:scripts").getByCode(args.sc, "sc") or nil local m_compound = require("Module:compound") term = m_compound.make_affix(term, data.lang, sc, affixtype) alt = m_compound.make_affix(args.alt, data.lang, sc, affixtype) local tr = m_compound.make_affix(args.tr, data.lang, require("Module:scripts").getByCode("Latn"), affixtype) local m_script_utilities = require("Module:script utilities") local id_text = id and " (" .. id .. ")" or ""

-- Compute parents. local parents = {} if id then if pos == "words" then table.insert(parents, {name = labelpref .. term, sort = id, args = args}) else table.insert(parents, {name = "words " .. affixtype .. "ed with " .. term_and_id, sort = id .. ", " .. pos, args = args}) table.insert(parents, {name = labelpref .. term, sort = id, args = args}) end elseif pos ~= "words" then table.insert(parents, {name = "words " .. affixtype .. "ed with " .. term, sort = pos, args = args}) end table.insert(parents, {name = "words by " .. affixtype, sort = data.lang:makeSortKey(data.lang:makeEntryName(args.sort or term))})

return { description = " " .. pos .. " " .. desc[affixtype] .. " " .. require("Module:links").full_link({				lang = data.lang, term = term, alt = alt, sc = sc, id = id, tr = tr}, "term") .. ".",			breadcrumb = pos == "words" and m_script_utilities.tag_text(alt or term, data.lang, sc, "term") .. id_text or pos, displaytitle = " " .. labelpref .. m_script_utilities.tag_text(term, data.lang, sc, "term") .. id_text, parents = parents, umbrella = false, }, true -- true = args handled end end)

- -- Indo-Aryan extension handlers -

table.insert(handlers, function(data)	local labelpref, extension = data.label:match("^(terms extended with Indo%-Aryan )(.+)$")	if extension then		local lang_inc_ash = require("Module:languages").getByCode("inc-ash")		local linked_term = require("Module:links").full_link({lang = lang_inc_ash, term = extension}, "term")		local tagged_term = require("Module:script utilities").tag_text(extension, lang_inc_ash, nil, "term")		return {			description = " terms extended with the Indo-Aryan pleonastic affix " .. linked_term .. ".",			displaytitle = " " .. labelpref .. tagged_term,			breadcrumb = tagged_term,			parents = ,			umbrella = {				no_by_language = true,				parents = "Indo-Aryan extensions",				displaytitle = "Terms extended with Indo-Aryan " .. tagged_term,			}		}	end end)

- Coined-by handlers - -

table.insert(handlers, function(data)	local coiner = data.label:match("^terms coined by (.+)$")	if coiner then		-- Sort by last name per request from User:Metaknowledge		local last_name = coiner:match(".* ([^ ]+)$")		return {			description = " terms coined by " .. coiner .. ".",			breadcrumb = coiner,			parents = ,			umbrella = false,		}	end end)

- Multiple etymology handlers -

table.insert(handlers, function(data)	local pos = data.label:match("^terms with multiple (.+) etymologies$")	if pos and pos ~= "lemma" and pos ~= "non-lemma form" then		local plpos = require("Module:string utilities").pluralize(pos)		local postype = require("Module:headword").pos_lemma_or_nonlemma(plpos, "guess")		return {			description = " " .. plpos .. " that are derived from multiple origins.",			umbrella_parents = "Multiple etymology subcategories by language",			breadcrumb = "multiple " .. plpos,			parents = ,		}	end end)

table.insert(handlers, function(data)	local pos1, pos2 = data.label:match("^terms with (.+) and (.+) etymologies$")	if pos1 and pos1 ~= "lemma" and pos2 ~= "non-lemma form" then		local m_strutil = require("Module:string utilities")		local m_headword = require("Module:headword")		local plpos1 = m_strutil.pluralize(pos1)		local plpos2 = m_strutil.pluralize(pos2)		local pos1type = m_headword.pos_lemma_or_nonlemma(plpos1, "guess")		local pos2type = m_headword.pos_lemma_or_nonlemma(plpos2, "guess")		local a_pos1 = m_strutil.add_indefinite_article(pos1)		local a_pos2 = m_strutil.add_indefinite_article(pos2)		return {			description = " terms consisting of " .. a_pos1 .." of one origin and " ..				a_pos2 .. " of a different origin.",			umbrella_parents = "Multiple etymology subcategories by language",			breadcrumb = pos1 .. " and " .. pos2,			parents = ,		}	end end)

- --                                                                        -- --                                RAW HANDLERS                             -- --                                                                        -- -

-- Handler for umbrella metacategories of the form e.g. Category:Terms derived from Proto-Indo-Iranian roots -- and Category:Terms derived from Proto-Indo-European words. Replaces the former -- Module:category tree/PIE root cat, Module:category tree/root cat and Template:PIE word cat. table.insert(raw_handlers, function(data)	local source_name, terms_type = data.category:match("^Terms derived from (.+) (roots)$")	if not source_name then		source_name, terms_type = data.category:match("^Terms derived from (.+) (words)$")	end	if not source_name then		source_name, terms_type = data.category:match("^Terms derived from (.+) (terms)$")	end	if source_name then		local source = require("Module:languages").getByCanonicalName(source_name, true, "allow etym langs")

return { description = "Umbrella categories covering terms derived from particular " .. get_source_and_type_desc(source, terms_type) .. ".",			additional = "", parents = { "Umbrella metacategories", { name = terms_type == "roots" and "roots" or "lemmas", is_label = true, lang = source:getCode, sort = " " }, { name = "terms derived from " .. source_name, is_label = true, sort = " " .. terms_type }, },		}	end end)

return {LABELS = labels, RAW_CATEGORIES = raw_categories, HANDLERS = handlers, RAW_HANDLERS = raw_handlers}