<?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%2Fcharacters</id>
	<title>Module:category tree/characters - 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%2Fcharacters"/>
	<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:category_tree/characters&amp;action=history"/>
	<updated>2026-04-22T05:48:49Z</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/characters&amp;diff=494670&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/characters&amp;diff=494670&amp;oldid=prev"/>
		<updated>2026-04-21T11:22:23Z</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/characters&amp;diff=494669&amp;oldid=prev</id>
		<title>wikt&gt;Surjection: Changed protection settings for &quot;Module:category tree/characters&quot;: Highly visible template/module ([Edit=Allow only autopatrollers] (indefinite) [Move=Allow only autopatrollers] (indefinite))</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:category_tree/characters&amp;diff=494669&amp;oldid=prev"/>
		<updated>2026-04-15T09:16:36Z</updated>

		<summary type="html">&lt;p&gt;Changed protection settings for &amp;quot;&lt;a href=&quot;/wiki/Module:category_tree/characters&quot; title=&quot;Module:category tree/characters&quot;&gt;Module:category tree/characters&lt;/a&gt;&amp;quot;: Highly visible template/module ([Edit=Allow only autopatrollers] (indefinite) [Move=Allow only autopatrollers] (indefinite))&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local raw_categories = {}&lt;br /&gt;
local handlers = {} &lt;br /&gt;
local raw_handlers = {}&lt;br /&gt;
&lt;br /&gt;
local m_str_utils = require(&amp;quot;Module:string utilities&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
local insert = table.insert&lt;br /&gt;
local ulen = m_str_utils.len&lt;br /&gt;
local ulower = m_str_utils.lower&lt;br /&gt;
local umatch = m_str_utils.match&lt;br /&gt;
local toNFC = mw.ustring.toNFC&lt;br /&gt;
local toNFD = mw.ustring.toNFD&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function track(page)&lt;br /&gt;
	require(&amp;quot;Module:debug/track&amp;quot;)(&amp;quot;category tree/characters/&amp;quot; .. page)&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
--                                                                         --&lt;br /&gt;
--                              RAW CATEGORIES                             --&lt;br /&gt;
--                                                                         --&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
raw_categories[&amp;quot;Terms by their individual characters subcategories by language&amp;quot;] = {&lt;br /&gt;
	description = &amp;quot;Umbrella categories covering terms categorized by unusual characters contained in them.&amp;quot;,&lt;br /&gt;
	additional = &amp;quot;{{{umbrella_meta_msg}}}&amp;quot;,&lt;br /&gt;
	parents = {&lt;br /&gt;
		&amp;quot;Umbrella metacategories&amp;quot;,&lt;br /&gt;
		{name = &amp;quot;terms by their individual characters&amp;quot;, is_label = true, sort = &amp;quot; &amp;quot;},&lt;br /&gt;
	},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- FIXME! This should probably be deleted.&lt;br /&gt;
raw_categories[&amp;quot;Letters&amp;quot;] = {&lt;br /&gt;
	description = &amp;quot;Categories specifying individual letters, containing the languages that use those letters.&amp;quot;,&lt;br /&gt;
	additional = &amp;quot;{{{umbrella_meta}}}&amp;quot;,&lt;br /&gt;
	parents = {&lt;br /&gt;
		&amp;quot;Fundamental&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
--                                                                         --&lt;br /&gt;
--                                 HANDLERS                                --&lt;br /&gt;
--                                                                         --&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- 	If char is a combining character, returns a version with a dotted circle before it.&lt;br /&gt;
local function add_dotted_circle(char, combining)&lt;br /&gt;
	return combining and &amp;quot;◌&amp;quot; .. char or char&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
insert(handlers, function(data)&lt;br /&gt;
	-- NOTE: The &amp;quot;character&amp;quot; in the title may actually be a description such as&lt;br /&gt;
	-- &amp;quot;gershayim&amp;quot;. In that case, char= is specified as a parameter indicating the&lt;br /&gt;
	-- actual character.&lt;br /&gt;
	local titlechar = data.label:match(&amp;quot;^terms spelled with (.+)$&amp;quot;)&lt;br /&gt;
	if not titlechar then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local args = require(&amp;quot;Module:parameters&amp;quot;).process(data.args, {&lt;br /&gt;
		[&amp;quot;char&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;sort&amp;quot;] = true,&lt;br /&gt;
		-- Not sure what used to be done with the following parameters.&lt;br /&gt;
		[&amp;quot;context&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;context2&amp;quot;] = true,&lt;br /&gt;
	})&lt;br /&gt;
	if args.context or args.context2 then&lt;br /&gt;
		track(&amp;quot;terms-spelled-with-context&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local special_cases = {&lt;br /&gt;
		numbers = {&lt;br /&gt;
			sort = &amp;quot;#&amp;quot;,&lt;br /&gt;
			desc = &amp;quot;numeric digits&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		emoji = {&lt;br /&gt;
			sort = &amp;quot;⌚&amp;quot;, -- the first emoji in our list in [[Module:headword/data]]&lt;br /&gt;
		},&lt;br /&gt;
		parentheses = {&lt;br /&gt;
			sort = &amp;quot;(&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		[&amp;quot;square brackets&amp;quot;] = {&lt;br /&gt;
			sort = &amp;quot;[&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		[&amp;quot;angle brackets&amp;quot;] = {&lt;br /&gt;
			sort = &amp;quot;&amp;lt;&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		braces = {&lt;br /&gt;
			sort = &amp;quot;{&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
	if special_cases[titlechar] then&lt;br /&gt;
		local sortkey = args.sort or special_cases[titlechar].sort&lt;br /&gt;
		return {&lt;br /&gt;
			description = &amp;quot;{{{langname}}} terms spelled with one or more &amp;quot; .. (special_cases[titlechar].desc or titlechar) .. &amp;quot;.&amp;quot;,&lt;br /&gt;
			parents = {{name = &amp;quot;terms by their individual characters&amp;quot;, sort = sortkey }},&lt;br /&gt;
			breadcrumb = titlechar,&lt;br /&gt;
			umbrella = {&lt;br /&gt;
				breadcrumb = titlechar,&lt;br /&gt;
				parents = {{name = &amp;quot;Terms by their individual characters subcategories by language&amp;quot;, sort = &amp;quot; &amp;quot; .. sortkey }}&lt;br /&gt;
			},&lt;br /&gt;
		}, true&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local char = args.char or titlechar&lt;br /&gt;
	local titlechar_is_desc = args.char and args.char ~= titlechar&lt;br /&gt;
	if titlechar_is_desc then&lt;br /&gt;
		track(&amp;quot;titlechar_is_desc&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local lang = data.lang or require(&amp;quot;Module:languages&amp;quot;).getByCode(&amp;quot;mul&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	local combining = ulen(char) == 1 and require(&amp;quot;Module:Unicode_data&amp;quot;).is_combining(char)&lt;br /&gt;
	&lt;br /&gt;
	local specials = {[&amp;quot;ß&amp;quot;] = &amp;quot;ẞ&amp;quot;, [&amp;quot;ͅ&amp;quot;] = &amp;quot;ͅ&amp;quot;}&lt;br /&gt;
	local upper = toNFD(char)&lt;br /&gt;
		:gsub(&amp;quot;[%z\1-\127\194-\244][\128-\191]*&amp;quot;, function(m)&lt;br /&gt;
			return specials[m] or m:uupper()&lt;br /&gt;
		end)&lt;br /&gt;
	upper = toNFC(upper)&lt;br /&gt;
	&lt;br /&gt;
	local standard_chars = lang:getStandardCharacters()&lt;br /&gt;
	-- FIXME: This should be able to handle non-atomic single characters (e.g. &amp;quot;Q̓&amp;quot;).&lt;br /&gt;
	if char ~= upper and ulen(char) == 1 then&lt;br /&gt;
		-- We want uppercase characters; but unless we&amp;#039;re careful, we run into an issue with&lt;br /&gt;
		-- [[Category:English terms spelled with ı]] due to the weird behavior of this character,&lt;br /&gt;
		-- which has standard &amp;quot;I&amp;quot; as its uppercase equivalent.&lt;br /&gt;
		if standard_chars then&lt;br /&gt;
			local function err()&lt;br /&gt;
				error(&amp;quot;Category titles should use uppercase characters: &amp;#039;&amp;quot; .. data.label .. &amp;quot;&amp;#039;&amp;quot;, 2)&lt;br /&gt;
			end&lt;br /&gt;
			if lang:getCode() ~= &amp;quot;hi&amp;quot; and lang:getCode() ~= &amp;quot;lo&amp;quot; then&lt;br /&gt;
				if not umatch(standard_chars, upper) then&lt;br /&gt;
					err()&lt;br /&gt;
				end&lt;br /&gt;
			elseif not umatch(upper, &amp;quot;[&amp;quot; .. standard_chars .. &amp;quot;]&amp;quot;) then&lt;br /&gt;
				err()&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Compute description.&lt;br /&gt;
	&lt;br /&gt;
	local is_reconstructed = lang:hasType(&amp;quot;reconstructed&amp;quot;)&lt;br /&gt;
	local character = require(&amp;quot;Module:links&amp;quot;).full_link(&lt;br /&gt;
		{&lt;br /&gt;
			term = is_reconstructed and &amp;quot;&amp;quot; or char,&lt;br /&gt;
			alt = combining and add_dotted_circle(char, true) or is_reconstructed and &amp;quot;*&amp;quot; .. char or nil,&lt;br /&gt;
			lang = lang,&lt;br /&gt;
			tr = combining and &amp;quot;-&amp;quot; or nil,&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;term&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
	&lt;br /&gt;
	-- If the letter has a lowercase form that&amp;#039;s also not in the standard characters,&lt;br /&gt;
	-- show it. This time, it&amp;#039;s [[Category:English terms spelled with İ]] that causes&lt;br /&gt;
	-- issues, because the lowercase equivalent is standard &amp;quot;i&amp;quot;.&lt;br /&gt;
	-- Note that ulower(&amp;quot;İ&amp;quot;) has a bug where it outputs &amp;quot;i&amp;quot; with a combining dot, instead&lt;br /&gt;
	-- of plain &amp;quot;i&amp;quot;, so this has to be accounted for.&lt;br /&gt;
	local lower = ulower(char:gsub(&amp;quot;İ&amp;quot;, &amp;quot;I&amp;quot;))&lt;br /&gt;
	if lower ~= char and not (standard_chars and umatch(lower, &amp;quot;[&amp;quot; .. standard_chars .. &amp;quot;]&amp;quot;)) then&lt;br /&gt;
		character = &amp;quot;upper case &amp;quot; .. character .. &amp;quot; or lower case &amp;quot; ..&lt;br /&gt;
			require(&amp;quot;Module:links&amp;quot;).full_link(&lt;br /&gt;
				{&lt;br /&gt;
					term = is_reconstructed and &amp;quot;&amp;quot; or lower,&lt;br /&gt;
					alt = is_reconstructed and &amp;quot;*&amp;quot; .. lower or nil,&lt;br /&gt;
					lang = lang&lt;br /&gt;
				},&lt;br /&gt;
				&amp;quot;term&amp;quot;&lt;br /&gt;
			)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if titlechar_is_desc then&lt;br /&gt;
		character = character .. &amp;quot; (&amp;quot; .. titlechar .. &amp;quot;)&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local description = &amp;quot;{{{langname}}} terms spelled with &amp;quot; .. character .. &amp;quot;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	-- Set tagged character for displaytitle and breadcrumb.&lt;br /&gt;
	local tagged_titlechar = not titlechar_is_desc and&lt;br /&gt;
		require(&amp;quot;Module:script utilities&amp;quot;).tag_text(titlechar, lang, nil, &amp;quot;term&amp;quot;) or nil&lt;br /&gt;
	local tagged_char = titlechar_is_desc and titlechar or&lt;br /&gt;
		require(&amp;quot;Module:script utilities&amp;quot;).tag_text(add_dotted_circle(char, combining), lang, nil, &amp;quot;term&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	local han = umatch(char, &amp;quot;^[&amp;quot; .. require(&amp;quot;Module:scripts&amp;quot;).getByCode(&amp;quot;Hani&amp;quot;).characters .. &amp;quot;]+$&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- Make the sortkey. Always use Hani-sortkey for Han characters, as this circumvents any reading-based sortkey methods.&lt;br /&gt;
	local sortkey = args.sort or han and require(&amp;quot;Module:Hani-sortkey&amp;quot;).makeSortKey(char) or lang:makeSortKey(char)&lt;br /&gt;
	-- Use the char as a fallback.&lt;br /&gt;
	if sortkey == &amp;quot;&amp;quot; then&lt;br /&gt;
		sortkey = char&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return {&lt;br /&gt;
		description = description,&lt;br /&gt;
		-- The following doesn&amp;#039;t apply to Sinitic or Japonic, where we categorize all characters.&lt;br /&gt;
		additional = not lang:inFamily(&amp;quot;zhx&amp;quot;, &amp;quot;jpx&amp;quot;) and&lt;br /&gt;
			&amp;quot;Note that categories of the form &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;LANG terms spelled with CHAR&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; are intended for characters not &amp;quot;&lt;br /&gt;
			.. &amp;quot;part of the standard repertoire of a language (e.g. Cyrillic characters in English or Latin characters in Russian).&amp;quot; or nil,&lt;br /&gt;
		displaytitle = not titlechar_is_desc and &amp;quot;{{{langname}}} terms spelled with &amp;quot; .. tagged_titlechar or nil,&lt;br /&gt;
		parents = {{name = &amp;quot;terms by their individual characters&amp;quot;, sort = sortkey }},&lt;br /&gt;
		breadcrumb = tagged_char,&lt;br /&gt;
		umbrella = {&lt;br /&gt;
			displaytitle = not titlechar_is_desc and &amp;quot;Terms spelled with &amp;quot; .. tagged_titlechar .. &amp;quot; by language&amp;quot; or nil,&lt;br /&gt;
			breadcrumb = tagged_char,&lt;br /&gt;
			parents = {{name = &amp;quot;Terms by their individual characters subcategories by language&amp;quot;, sort = &amp;quot; &amp;quot; .. sortkey }}&lt;br /&gt;
		},&lt;br /&gt;
	}, true&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
--                                                                         --&lt;br /&gt;
--                               RAW HANDLERS                              --&lt;br /&gt;
--                                                                         --&lt;br /&gt;
-----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Special-cased categories that we allow, for Turkish letters.&lt;br /&gt;
local letter_cat_allow_list = require(&amp;quot;Module:table&amp;quot;).listToSet {&lt;br /&gt;
	&amp;quot;İi&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
insert(raw_handlers, function(data)&lt;br /&gt;
	-- Only recognize cases consisting of an uppercase letter followed by the&lt;br /&gt;
	-- corresponding lowercase letter, either as the entire category name or&lt;br /&gt;
	-- followed by a colon (for cases like [[Category:Gg: ⠛]]). Cases that&lt;br /&gt;
	-- don&amp;#039;t fit this profile (e.g. for Turkish [[Category:İi]] and&lt;br /&gt;
	-- [[Category:Iı]]) need to call {{letter cat}} directly. Formerly this&lt;br /&gt;
	-- handler was much less restrictive and would fire on categories named&lt;br /&gt;
	-- [[Category:zh:]], [[Category:RFQ]], etc.&lt;br /&gt;
	local upper, lower = umatch(data.category, &amp;quot;^(%u)(%l)%f[:%z]&amp;quot;)&lt;br /&gt;
	if not upper or not letter_cat_allow_list[data.category] and lower:uupper() ~= upper then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return {&lt;br /&gt;
		description = (&amp;#039;Languages that use the uppercase letter &amp;quot;%s&amp;quot; (lowercase equivalent &amp;quot;%s&amp;quot;).&amp;#039;):format(upper, lower),&lt;br /&gt;
		parents = {&amp;quot;Letters&amp;quot;},&lt;br /&gt;
	}&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
return {RAW_CATEGORIES = raw_categories, HANDLERS = handlers, RAW_HANDLERS = raw_handlers}&lt;/div&gt;</summary>
		<author><name>wikt&gt;Surjection</name></author>
	</entry>
</feed>