<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=Module%3Acategory_tree%2Futilities</id>
	<title>Module:category tree/utilities - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=Module%3Acategory_tree%2Futilities"/>
	<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:category_tree/utilities&amp;action=history"/>
	<updated>2026-04-22T00:14:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://linguifex.com/w/index.php?title=Module:category_tree/utilities&amp;diff=494690&amp;oldid=prev</id>
		<title>Sware: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:category_tree/utilities&amp;diff=494690&amp;oldid=prev"/>
		<updated>2026-04-21T11:22:26Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 11:22, 21 April 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
	<entry>
		<id>https://linguifex.com/w/index.php?title=Module:category_tree/utilities&amp;diff=494689&amp;oldid=prev</id>
		<title>wikt&gt;WingerBot: WingerBot moved page Module:category tree/poscatboiler/utilities to Module:category tree/utilities: rename category tree subpage per Wiktionary:Grease_pit/2025/February#cleaning_up_and_renaming_the_category_tree_modules</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:category_tree/utilities&amp;diff=494689&amp;oldid=prev"/>
		<updated>2025-04-28T05:01:57Z</updated>

		<summary type="html">&lt;p&gt;WingerBot moved page &lt;a href=&quot;/w/index.php?title=Module:category_tree/poscatboiler/utilities&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Module:category tree/poscatboiler/utilities (page does not exist)&quot;&gt;Module:category tree/poscatboiler/utilities&lt;/a&gt; to &lt;a href=&quot;/wiki/Module:category_tree/utilities&quot; title=&quot;Module:category tree/utilities&quot;&gt;Module:category tree/utilities&lt;/a&gt;: rename category tree subpage per &lt;a href=&quot;http://en.wiktionary.org/wiki/Grease_pit/2025/February#cleaning_up_and_renaming_the_category_tree_modules&quot; class=&quot;extiw&quot; title=&quot;wiktionary:Grease pit/2025/February&quot;&gt;Wiktionary:Grease_pit/2025/February#cleaning_up_and_renaming_the_category_tree_modules&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local export = {}&lt;br /&gt;
&lt;br /&gt;
local en_utilities_module = &amp;quot;Module:en-utilities&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local unpack = unpack or table.unpack -- Lua 5.2 compatibility&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Generate labels for inflection classes. `data` is a table with the following fields:&lt;br /&gt;
* `labels`: The table into which the labels are written.&lt;br /&gt;
* `pos`: The singular part of speech, e.g. &amp;quot;noun&amp;quot;.&lt;br /&gt;
* `stem_classes`: Table of possible stem classes and associated properties. See below.&lt;br /&gt;
* `principal_parts`: List of the principal part fields and descriptions. Each list element is a two-element list&lt;br /&gt;
  consisting of {&amp;quot;FIELD&amp;quot;, &amp;quot;DESCRIPTION&amp;quot;} where FIELD is the field in the element in `stem_classes` (e.g. &amp;quot;nom_sg&amp;quot;,&lt;br /&gt;
  &amp;quot;gen_sg&amp;quot;, &amp;quot;pl&amp;quot;, &amp;quot;sup&amp;quot;) containing the detailed description of what this principal part looks like, and DESCRIPTION&lt;br /&gt;
  is the corresponding English description of the principal part (e.g. &amp;quot;nominative singular&amp;quot;).&lt;br /&gt;
* `mark_up_spec`: Optional function to add markup to a spec. Takes two arguments, the spec and a flag `nolink`; if the&lt;br /&gt;
  flag is true, links should not be present in the resulting markup. The default just converts literal text enclosed&lt;br /&gt;
  in &amp;lt;...&amp;gt; into italics.&lt;br /&gt;
* `make_spec_bare`: Optional function to make a spec (stem class or sortkey) free of markup. The default just converts&lt;br /&gt;
  literal text enclosed in &amp;lt;...&amp;gt; into bare text.&lt;br /&gt;
* `addl`: Optional additional text to be displayed in the footer of each category page.&lt;br /&gt;
&lt;br /&gt;
`stem_classes` is a table describing the various stem classes and how to format the category description of each. It is&lt;br /&gt;
a table with keys specifying the stem classes and values consisting of an object containing properties of the stem&lt;br /&gt;
class. If the stem class contains the word &amp;#039;GENDER&amp;#039; in it, it expands into labels both for a parent category that&lt;br /&gt;
subsumes several genders (obtained by removing the word &amp;#039;GENDER&amp;#039; and following whitespace) as well as gender-specific&lt;br /&gt;
children categories (obtained by replacing the word &amp;#039;GENDER&amp;#039; with the genders specified in the `possible_genders`&lt;br /&gt;
field). The stem class can contain literal text (e.g. suffixes), which will be marked up appropriately (e.g. italicized)&lt;br /&gt;
in breadcrumbs and titles. The fields of the property object for a given stem class are as follows:&lt;br /&gt;
* `gender`: The description of the gender(s) of the stem class. If preceded by ~, the description is preceded by&lt;br /&gt;
  &amp;quot;most commonly&amp;quot;. This appears in the `additional` field of the label properties. It is not used in gender-specific&lt;br /&gt;
  children categories; instead the gender of that category is used.&lt;br /&gt;
* `possible_genders`: The possible genders this class occurs in. If this is specified, the word &amp;#039;GENDER&amp;#039; must occur in&lt;br /&gt;
  the stem class, and gender-specific variants of the stem class (with GENDER replaced by the possible genders) are&lt;br /&gt;
  handled along with a parent category subsuming all genders. &lt;br /&gt;
* `PRINCIPAL_PART`: The ending for the specified principal part. Use &amp;lt;...&amp;gt; to enclose literal Latin-script text (e.g.&lt;br /&gt;
  suffixes), which will be italicized. There will be one field for each principal part listed in the `principal_parts`&lt;br /&gt;
  table described above.&lt;br /&gt;
* `GENDER_PRINCIPAL_PART`: The ending for the GENDER variant of the specified principal part. If not specified, the&lt;br /&gt;
  value of `PRINCIPAL_PART` is used.&lt;br /&gt;
* `breadcrumb`: The breadcrumb for the category, appearing in the trail of breadcrumbs at the top of the page. If this&lt;br /&gt;
  stem has gender-specific variants, the breadcrumb specified here is used only for the parent category, while the&lt;br /&gt;
  gender-specific child categories use the gender as the breadcrumb. If not specified, it defaults to `sortkey`. If that&lt;br /&gt;
  is also not specified, or if the breadcrumb has the value &amp;quot;+&amp;quot;, the stem class (without the word &amp;#039;GENDER&amp;#039;) is used.&lt;br /&gt;
  (Use &amp;quot;+&amp;quot; when a sortkey is specified but the stem class should be used as the breadcrumb.)&lt;br /&gt;
* `parent`: The parent category or categories. If specified, the actual category label is formed by appending the part&lt;br /&gt;
  of speech (e.g. &amp;quot;nouns&amp;quot;). Defaults to &amp;quot;POS by inflection type&amp;quot; where POS is the part of speech. Note that&lt;br /&gt;
  gender-specific child categories do not use this, but always have the gender-subsuming parent stem class category as&lt;br /&gt;
  their parent.&lt;br /&gt;
* `sortkey`: The sort key used for sorting this category among its parent&amp;#039;s children. Defaults to the stem class&lt;br /&gt;
  (without the word &amp;#039;GENDER&amp;#039;). Note that gender-specific child categories do nto use this, but always use the gender&lt;br /&gt;
  as the sort key.&lt;br /&gt;
* `addl`: Optional additional text to be displayed in the footer of the category page.&lt;br /&gt;
* `GENDER_addl`: Optional additional text to be displayed in the footer of a gender-specific category page, defaulting&lt;br /&gt;
  to `addl`. Use the value `false` to cancel out a non-gender-specific value.&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
function export.add_inflection_labels(data)&lt;br /&gt;
	for _, reqfield_spec in ipairs {&lt;br /&gt;
		{&amp;quot;labels&amp;quot;, &amp;quot;table of labels&amp;quot;},&lt;br /&gt;
		{&amp;quot;pos&amp;quot;, &amp;quot;singular part of speech&amp;quot;},&lt;br /&gt;
		{&amp;quot;stem_classes&amp;quot;, &amp;quot;table of possible stem classes and associated properties&amp;quot;},&lt;br /&gt;
		{&amp;quot;principal_parts&amp;quot;, &amp;quot;list of principal part fields and names&amp;quot;},&lt;br /&gt;
	} do&lt;br /&gt;
		local reqfield, gloss = unpack(reqfield_spec)&lt;br /&gt;
		if not data[reqfield] then&lt;br /&gt;
			error((&amp;quot;Internal error: Missing field &amp;#039;%s&amp;#039;, which should containing the %s&amp;quot;):format(reqfield, gloss))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function default_mark_up_spec(spec, nolink)&lt;br /&gt;
		return (spec:gsub(&amp;quot;&amp;lt;(.-)&amp;gt;&amp;quot;, &amp;quot;&amp;#039;&amp;#039;%1&amp;#039;&amp;#039;&amp;quot;))&lt;br /&gt;
	end&lt;br /&gt;
	local function default_make_spec_bare(spec)&lt;br /&gt;
		return (spec:gsub(&amp;quot;&amp;lt;(.-)&amp;gt;&amp;quot;, &amp;quot;%1&amp;quot;))&lt;br /&gt;
	end&lt;br /&gt;
	local function mark_up_spec(spec, nolink)&lt;br /&gt;
		return (data.mark_up_spec or default_mark_up_spec)(spec, nolink)&lt;br /&gt;
	end&lt;br /&gt;
	local function make_spec_bare(spec)&lt;br /&gt;
		return (data.make_spec_bare or default_make_spec_bare)(spec)&lt;br /&gt;
	end&lt;br /&gt;
	local plpos = require(en_utilities_module).pluralize(data.pos)&lt;br /&gt;
	for full_infl, spec in pairs(data.stem_classes) do&lt;br /&gt;
		local subgenders = spec.possible_genders&lt;br /&gt;
&lt;br /&gt;
		-- Get the stem type.&lt;br /&gt;
		local infl&lt;br /&gt;
		if subgenders then&lt;br /&gt;
			if not full_infl:find(&amp;quot;GENDER&amp;quot;) then&lt;br /&gt;
				error((&amp;quot;Internal error: Declension spec &amp;#039;%s&amp;#039; needs to have the word &amp;#039;GENDER&amp;#039; in it, in all caps&amp;quot;):format(full_infl))&lt;br /&gt;
			end&lt;br /&gt;
			infl = full_infl:gsub(&amp;quot;GENDER &amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
		else&lt;br /&gt;
			infl = full_infl&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Get the breadcrumb.&lt;br /&gt;
		local breadcrumb = spec.breadcrumb or spec.sortkey or &amp;quot;+&amp;quot;&lt;br /&gt;
		if breadcrumb == &amp;quot;+&amp;quot; then&lt;br /&gt;
			breadcrumb = infl&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Generate the parents.&lt;br /&gt;
		local parents = {}&lt;br /&gt;
		local spec_parents = spec.parent&lt;br /&gt;
		if type(spec_parents) == &amp;quot;string&amp;quot; then&lt;br /&gt;
			spec_parents = {spec_parents}&lt;br /&gt;
		end&lt;br /&gt;
		local parent_sort = make_spec_bare(spec.sortkey or infl)&lt;br /&gt;
		if spec_parents then&lt;br /&gt;
			for _, parent in ipairs(spec_parents) do&lt;br /&gt;
				table.insert(parents, {name = make_spec_bare(parent) .. &amp;quot; &amp;quot; .. plpos, sort = parent_sort})&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			table.insert(parents, {name = plpos .. &amp;quot; by inflection type&amp;quot;, sort = parent_sort})&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- Generate the additional text, including principal part descriptions and footer.&lt;br /&gt;
		local function create_addl(gender_spec, subgender_prefix)&lt;br /&gt;
			local addl_parts = {}&lt;br /&gt;
			local function ins(txt)&lt;br /&gt;
				table.insert(addl_parts, txt)&lt;br /&gt;
			end&lt;br /&gt;
			local function insert_header(gender_spec)&lt;br /&gt;
				if gender_spec then&lt;br /&gt;
					local most_commonly, gender = gender_spec:match(&amp;quot;^(~)(.*)$&amp;quot;)&lt;br /&gt;
					most_commonly = most_commonly and &amp;quot;most commonly &amp;quot; or &amp;quot;&amp;quot;&lt;br /&gt;
					gender = gender or gender_spec&lt;br /&gt;
					ins((&amp;quot;These %s are %s%s, typically with the following endings:\n&amp;quot;):format(plpos, most_commonly,&lt;br /&gt;
						mark_up_spec(gender)))&lt;br /&gt;
				else&lt;br /&gt;
					ins((&amp;quot;These %s typically have the following endings:\n&amp;quot;):format(plpos))&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			local function process_ending(field, desc, is_last)&lt;br /&gt;
				local ending_spec = spec[subgender_prefix .. field] or spec[field]&lt;br /&gt;
				if not ending_spec then&lt;br /&gt;
					error((&amp;quot;Internal error: for inflection &amp;#039;%s&amp;#039;, field &amp;#039;%s&amp;#039; for principal part &amp;#039;%s&amp;#039; is missing&amp;quot;):format(&lt;br /&gt;
						full_infl, field, desc))&lt;br /&gt;
				end&lt;br /&gt;
				return (&amp;quot;* in the %s: %s%s&amp;quot;):format(desc, mark_up_spec(ending_spec), is_last and &amp;quot;.&amp;quot; or &amp;quot;;\n&amp;quot;)&lt;br /&gt;
			end&lt;br /&gt;
			local function insert_principal_part_info(subgender_prefix)&lt;br /&gt;
				for i, ppart_spec in ipairs(data.principal_parts) do&lt;br /&gt;
					local ppart_field, ppart_desc = unpack(ppart_spec)&lt;br /&gt;
					ins(process_ending(ppart_field, ppart_desc, i == #data.principal_parts))&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			insert_header(gender_spec)&lt;br /&gt;
			insert_principal_part_info(&amp;quot;&amp;quot;)&lt;br /&gt;
			local spec_addl = spec[subgender_prefix .. &amp;quot;addl&amp;quot;]&lt;br /&gt;
			if spec_addl == nil then&lt;br /&gt;
				spec_addl = spec.addl&lt;br /&gt;
			end&lt;br /&gt;
			if data.addl or spec_addl then&lt;br /&gt;
				local footer_parts = {}&lt;br /&gt;
				if data.addl then&lt;br /&gt;
					table.insert(footer_parts, mark_up_spec(data.addl))&lt;br /&gt;
				end&lt;br /&gt;
				if spec_addl then&lt;br /&gt;
					table.insert(footer_parts, mark_up_spec(spec_addl))&lt;br /&gt;
				end&lt;br /&gt;
				ins(&amp;quot;\n&amp;quot; .. table.concat(footer_parts, &amp;quot; &amp;quot;))&lt;br /&gt;
			end&lt;br /&gt;
			return table.concat(addl_parts)&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		data.labels[make_spec_bare(infl) .. &amp;quot; &amp;quot; .. plpos] = {&lt;br /&gt;
			description = &amp;quot;{{{langname}}} &amp;quot; .. mark_up_spec(infl) .. &amp;quot; &amp;quot; .. plpos .. &amp;quot;.&amp;quot;,&lt;br /&gt;
			displaytitle = &amp;quot;{{{langname}}} &amp;quot; .. mark_up_spec(infl, &amp;quot;nolink&amp;quot;) .. &amp;quot; &amp;quot; .. plpos,&lt;br /&gt;
			additional = create_addl(spec.gender, &amp;quot;&amp;quot;),&lt;br /&gt;
			breadcrumb = mark_up_spec(breadcrumb, &amp;quot;nolink&amp;quot;),&lt;br /&gt;
			parents = parents,&lt;br /&gt;
		}&lt;br /&gt;
		if subgenders then&lt;br /&gt;
			for _, subgender in ipairs(subgenders) do&lt;br /&gt;
				local gender_infl = full_infl:gsub(&amp;quot;GENDER&amp;quot;, subgender)&lt;br /&gt;
				data.labels[make_spec_bare(gender_infl) .. &amp;quot; &amp;quot; .. plpos] = {&lt;br /&gt;
					description = &amp;quot;{{{langname}}} &amp;quot; .. mark_up_spec(gender_infl) .. &amp;quot; &amp;quot; .. plpos .. &amp;quot;.&amp;quot;,&lt;br /&gt;
					displaytitle = &amp;quot;{{{langname}}} &amp;quot; .. mark_up_spec(gender_infl, &amp;quot;nolink&amp;quot;) .. &amp;quot; &amp;quot; .. plpos,&lt;br /&gt;
					additional = create_addl(subgender, subgender .. &amp;quot;_&amp;quot;),&lt;br /&gt;
					breadcrumb = subgender,&lt;br /&gt;
					parents = {{&lt;br /&gt;
						name = make_spec_bare(infl) .. &amp;quot; &amp;quot; .. plpos,&lt;br /&gt;
						sort = subgender,&lt;br /&gt;
					}},&lt;br /&gt;
				}&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return export&lt;/div&gt;</summary>
		<author><name>wikt&gt;WingerBot</name></author>
	</entry>
</feed>