<?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%3Aen-utilities</id>
	<title>Module:en-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%3Aen-utilities"/>
	<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:en-utilities&amp;action=history"/>
	<updated>2026-04-06T02:00:06Z</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:en-utilities&amp;diff=460613&amp;oldid=prev</id>
		<title>Sware at 11:25, 30 June 2025</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:en-utilities&amp;diff=460613&amp;oldid=prev"/>
		<updated>2025-06-30T11:25:01Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://linguifex.com/w/index.php?title=Module:en-utilities&amp;amp;diff=460613&amp;amp;oldid=410291&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
	<entry>
		<id>https://linguifex.com/w/index.php?title=Module:en-utilities&amp;diff=410291&amp;oldid=prev</id>
		<title>Sware: Created page with &quot;local export = {}  local add_suffix -- Defined below. local find = string.find local match = string.match local reverse = string.reverse local sub = string.sub local toNFD = mw.ustring.toNFD local ugsub = mw.ustring.gsub local ulower = mw.ustring.lower local umatch = mw.ustring.match local usub = mw.ustring.sub  local vowels = &quot;aæᴀᴁɐɑɒ@eᴇǝⱻəɛɘɜɞɤiıɪɨᵻoøœᴏɶɔᴐɵuᴜʉᵾɯꟺʊʋʌyʏ&quot; local hyphens = &quot;%-‐‑‒–—&quot;  --[==[ Loaders for...&quot;</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:en-utilities&amp;diff=410291&amp;oldid=prev"/>
		<updated>2025-01-08T12:41:24Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local export = {}  local add_suffix -- Defined below. local find = string.find local match = string.match local reverse = string.reverse local sub = string.sub local toNFD = mw.ustring.toNFD local ugsub = mw.ustring.gsub local ulower = mw.ustring.lower local umatch = mw.ustring.match local usub = mw.ustring.sub  local vowels = &amp;quot;aæᴀᴁɐɑɒ@eᴇǝⱻəɛɘɜɞɤiıɪɨᵻoøœᴏɶɔᴐɵuᴜʉᵾɯꟺʊʋʌyʏ&amp;quot; local hyphens = &amp;quot;%-‐‑‒–—&amp;quot;  --[==[ Loaders for...&amp;quot;&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 add_suffix -- Defined below.&lt;br /&gt;
local find = string.find&lt;br /&gt;
local match = string.match&lt;br /&gt;
local reverse = string.reverse&lt;br /&gt;
local sub = string.sub&lt;br /&gt;
local toNFD = mw.ustring.toNFD&lt;br /&gt;
local ugsub = mw.ustring.gsub&lt;br /&gt;
local ulower = mw.ustring.lower&lt;br /&gt;
local umatch = mw.ustring.match&lt;br /&gt;
local usub = mw.ustring.sub&lt;br /&gt;
&lt;br /&gt;
local vowels = &amp;quot;aæᴀᴁɐɑɒ@eᴇǝⱻəɛɘɜɞɤiıɪɨᵻoøœᴏɶɔᴐɵuᴜʉᵾɯꟺʊʋʌyʏ&amp;quot;&lt;br /&gt;
local hyphens = &amp;quot;%-‐‑‒–—&amp;quot;&lt;br /&gt;
&lt;br /&gt;
--[==[&lt;br /&gt;
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as &amp;quot;foo or get_foo()&amp;quot;, where the function get_foo sets the object to &amp;quot;foo&amp;quot; and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once &amp;quot;foo&amp;quot; has been set, &amp;quot;get_foo&amp;quot; will not be called again.]==]&lt;br /&gt;
	local diacritics&lt;br /&gt;
	local function get_diacritics()&lt;br /&gt;
		diacritics, get_diacritics = mw.loadData(&amp;quot;Module:headword/data&amp;quot;).page.comb_chars.diacritics_all .. &amp;quot;+&amp;quot;, nil&lt;br /&gt;
		return diacritics&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
-- Normalize a string, so that case and diacritics are ignored. By default, &amp;quot;gu&amp;quot;&lt;br /&gt;
-- and &amp;quot;qu&amp;quot; are normalized to &amp;quot;g&amp;quot; and &amp;quot;q&amp;quot;, because they behave like consonants&lt;br /&gt;
-- under certain conditions (e.g. final &amp;quot;y&amp;quot; does not usually have the plural&lt;br /&gt;
-- &amp;quot;ies&amp;quot; after a vowel, but it&amp;#039;s regular for &amp;quot;quy&amp;quot; to become &amp;quot;quies&amp;quot;. The flag&lt;br /&gt;
-- `not_gu` prevents this happening to &amp;quot;gu&amp;quot;, and is needed because terms ending&lt;br /&gt;
-- &amp;quot;-guy&amp;quot; are almost always compounds of &amp;quot;guy&amp;quot; (→ &amp;quot;guys&amp;quot;).&lt;br /&gt;
local function normalize(str, followed_by, not_gu)&lt;br /&gt;
	if not followed_by then&lt;br /&gt;
		followed_by = &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	str = ugsub(toNFD(str) .. followed_by, &amp;quot;([&amp;quot; .. (not_gu and &amp;quot;&amp;quot; or &amp;quot;Gg&amp;quot;) .. &amp;quot;Qq])u([&amp;quot;.. vowels .. &amp;quot;])&amp;quot;, &amp;quot;%1%2&amp;quot;)&lt;br /&gt;
	return ulower(ugsub(sub(str, 1, #str - #followed_by), diacritics or get_diacritics(), &amp;quot;&amp;quot;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function epenthetic_e_default(stem)&lt;br /&gt;
	return sub(stem, -1) ~= &amp;quot;e&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function epenthetic_e_for_s(stem, term)&lt;br /&gt;
	-- If the stem is different, it must be from &amp;quot;y&amp;quot; → &amp;quot;i&amp;quot;.&lt;br /&gt;
	if stem ~= term then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	local final&lt;br /&gt;
	if match(stem, &amp;quot;^[^\128-\255]*$&amp;quot;) then&lt;br /&gt;
		final = sub(stem, -1)&lt;br /&gt;
	else&lt;br /&gt;
		stem = ugsub(toNFD(stem), diacritics or get_diacritics(), &amp;quot;&amp;quot;)&lt;br /&gt;
		final = usub(stem, -1)&lt;br /&gt;
	end&lt;br /&gt;
	-- Epenthetic &amp;quot;e&amp;quot; is added after a sibilant or sibilant-affricate. The vast&lt;br /&gt;
	-- majority of these are spelled &amp;quot;s&amp;quot;, &amp;quot;x&amp;quot;, &amp;quot;z&amp;quot;, &amp;quot;ch&amp;quot; and &amp;quot;sh&amp;quot;, but &amp;quot;dg&amp;quot;&lt;br /&gt;
	-- (→ &amp;quot;dge&amp;quot;) and &amp;quot;ß&amp;quot; (→ &amp;quot;ss&amp;quot;) can be found in obsolete spellings, &amp;quot;shh&amp;quot; in&lt;br /&gt;
	-- onomatopoeia, and &amp;quot;zh&amp;quot;, &amp;quot;dj&amp;quot;, &amp;quot;jj&amp;quot; (and more) in loanwords.&lt;br /&gt;
	return (&lt;br /&gt;
		final == &amp;quot;g&amp;quot; and sub(stem, -2, -2) == &amp;quot;d&amp;quot; or&lt;br /&gt;
		final == &amp;quot;h&amp;quot; and match(stem, &amp;quot;[csz]h+$&amp;quot;) or&lt;br /&gt;
		final == &amp;quot;j&amp;quot; and umatch(stem, &amp;quot;[^&amp;quot; .. vowels .. &amp;quot;]j$&amp;quot;) or&lt;br /&gt;
		final == &amp;quot;s&amp;quot; or&lt;br /&gt;
		final == &amp;quot;x&amp;quot; or&lt;br /&gt;
		final == &amp;quot;z&amp;quot; or&lt;br /&gt;
		final == &amp;quot;ß&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local suffixes = {}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;s.plural&amp;quot;] = {&lt;br /&gt;
	final_y_is_i = true,&lt;br /&gt;
	epenthetic_e = epenthetic_e_for_s&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;s.verb&amp;quot;] = {&lt;br /&gt;
	final_y_is_i = true,&lt;br /&gt;
	final_consonant_is_doubled = true,&lt;br /&gt;
	epenthetic_e = epenthetic_e_for_s&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;ing&amp;quot;] = {&lt;br /&gt;
	final_consonant_is_doubled = true,&lt;br /&gt;
	remove_silent_e = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;d&amp;quot;] = {&lt;br /&gt;
	final_y_is_i = true,&lt;br /&gt;
	final_consonant_is_doubled = true,&lt;br /&gt;
	epenthetic_e = epenthetic_e_default,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;dst&amp;quot;] = suffixes[&amp;quot;d&amp;quot;]&lt;br /&gt;
suffixes[&amp;quot;st.verb&amp;quot;] = suffixes[&amp;quot;d&amp;quot;]&lt;br /&gt;
suffixes[&amp;quot;th&amp;quot;] = suffixes[&amp;quot;d&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;n&amp;quot;] = {&lt;br /&gt;
	final_y_is_i = true,&lt;br /&gt;
	final_y_is_i_after_vowel = true,&lt;br /&gt;
	final_guy_is_gui = true,&lt;br /&gt;
	final_consonant_is_doubled = true,&lt;br /&gt;
	-- No epenthetic &amp;quot;e&amp;quot; after an &amp;quot;e&amp;quot;, or an &amp;quot;i&amp;quot;, &amp;quot;r&amp;quot; or &amp;quot;w&amp;quot; preceded by a vowel.&lt;br /&gt;
	epenthetic_e = function(stem)&lt;br /&gt;
		return not (&lt;br /&gt;
			sub(stem, -1) == &amp;quot;e&amp;quot; or&lt;br /&gt;
			umatch(normalize(stem), &amp;quot;[&amp;quot; .. vowels .. &amp;quot;][irw]$&amp;quot;)&lt;br /&gt;
		)&lt;br /&gt;
	end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;r&amp;quot;] = {&lt;br /&gt;
	final_y_is_i = true,&lt;br /&gt;
	final_ey_is_i = true,&lt;br /&gt;
	final_guy_is_gui = true,&lt;br /&gt;
	final_consonant_is_doubled = true,&lt;br /&gt;
	epenthetic_e = epenthetic_e_default&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
suffixes[&amp;quot;st.superlative&amp;quot;] = suffixes[&amp;quot;r&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
-- Returns the stem used for suffixes that sometimes convert final &amp;quot;y&amp;quot; into &amp;quot;i&amp;quot;,&lt;br /&gt;
-- such as &amp;quot;-es&amp;quot; (&amp;quot;-ies&amp;quot;), e.g. &amp;quot;penny&amp;quot; → &amp;quot;penni&amp;quot; (&amp;quot;pennies&amp;quot;). If&lt;br /&gt;
-- `final_ey_is_i` is true, final &amp;quot;ey&amp;quot; may also be converted, e.g. &amp;quot;plaguey&amp;quot; →&lt;br /&gt;
-- &amp;quot;plagui&amp;quot;; this is needed for &amp;quot;-er&amp;quot; (&amp;quot;-ier&amp;quot;) and &amp;quot;-est&amp;quot; (&amp;quot;-iest&amp;quot;). If `not_gu`&lt;br /&gt;
-- is true, then normalize() will be called with the `not_gu` flag (see there&lt;br /&gt;
-- for more info); this is true in most cases.&lt;br /&gt;
local function convert_final_y_to_i(str, not_gu, final_ey_is_i, final_y_is_i_after_vowel)&lt;br /&gt;
	local final3 = usub(str, -3)&lt;br /&gt;
	-- Special case: treat &amp;quot;eey&amp;quot; as &amp;quot;ee&amp;quot; + &amp;quot;y&amp;quot; (e.g. &amp;quot;treey&amp;quot; → &amp;quot;treeiest&amp;quot;).&lt;br /&gt;
	-- &amp;quot;oey&amp;quot; and &amp;quot;uey&amp;quot; are usually vowel + &amp;quot;ey&amp;quot;, but examples of &amp;quot;oe&amp;quot; + &amp;quot;y&amp;quot; and&lt;br /&gt;
	-- &amp;quot;ue&amp;quot; = &amp;quot;y&amp;quot; do also exist: compare &amp;quot;go&amp;quot; → &amp;quot;goey&amp;quot; → &amp;quot;goier&amp;quot; with &amp;quot;doe&amp;quot; →&lt;br /&gt;
	-- &amp;quot;doey&amp;quot; → &amp;quot;doeier&amp;quot;; &amp;quot;flu&amp;quot; → &amp;quot;fluey&amp;quot; → &amp;quot;fluiest&amp;quot; and &amp;quot;flue&amp;quot; → &amp;quot;fluey&amp;quot; →&lt;br /&gt;
	-- &amp;quot;flueiest&amp;quot; form a theoretically possible minimal pair.&lt;br /&gt;
	if final3 == &amp;quot;eey&amp;quot; then&lt;br /&gt;
		return sub(str, 1, -2) .. &amp;quot;i&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	local final2 = usub(str, -2)&lt;br /&gt;
	-- If `final_ey_is_i` is true, treat final &amp;quot;-ey&amp;quot; can also be reduced.&lt;br /&gt;
	if final_ey_is_i and final2 == &amp;quot;ey&amp;quot; then&lt;br /&gt;
		-- Remove &amp;quot;ey&amp;quot; to get the base stem.&lt;br /&gt;
		local base_stem = sub(str, 1, -3)&lt;br /&gt;
		-- Special case: allow final &amp;quot;-ey&amp;quot; (&amp;quot;potato-ey&amp;quot; → &amp;quot;potato-iest&amp;quot;).&lt;br /&gt;
		if umatch(final3, &amp;quot;[&amp;quot; .. hyphens .. &amp;quot;]ey&amp;quot;) then&lt;br /&gt;
			return base_stem .. &amp;quot;i&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		-- Final &amp;quot;ey&amp;quot; becomes &amp;quot;i&amp;quot; iff the term is polysyllabic (e.g. not&lt;br /&gt;
		-- &amp;quot;grey&amp;quot;). &amp;quot;ey&amp;quot; is common if the base stem ends in a vowel (&amp;quot;echo →&lt;br /&gt;
		-- &amp;quot;echoey&amp;quot;), so the presence of a vowel anywhere in the base stem is&lt;br /&gt;
		-- sufficient to deem it polysyllabic. (&amp;quot;echoey&amp;quot; → &amp;quot;echo&amp;quot; → &amp;quot;echoiest&amp;quot;,&lt;br /&gt;
		-- &amp;quot;beigey&amp;quot; → &amp;quot;beig&amp;quot; → &amp;quot;beigiest&amp;quot;, but &amp;quot;grey&amp;quot; → &amp;quot;gr&amp;quot; → &amp;quot;greyest&amp;quot;). The&lt;br /&gt;
		-- first &amp;quot;y&amp;quot; in &amp;quot;-yey&amp;quot; can be treated as a vowel as long as it&amp;#039;s&lt;br /&gt;
		-- preceded by something (&amp;quot;clayey&amp;quot; → &amp;quot;clay&amp;quot; → &amp;quot;clayiest&amp;quot;, &amp;quot;cryey&amp;quot; →&lt;br /&gt;
		-- &amp;quot;cry&amp;quot; → &amp;quot;cryiest&amp;quot;, but &amp;quot;*yey&amp;quot; → &amp;quot;*y&amp;quot; → &amp;quot;*yeyest&amp;quot;), so it needs to be&lt;br /&gt;
		-- treated as a special case.&lt;br /&gt;
		local normalized = normalize(base_stem, &amp;quot;ey&amp;quot;)&lt;br /&gt;
		if sub(normalized, -1) == &amp;quot;y&amp;quot; then&lt;br /&gt;
			if umatch(normalized, &amp;quot;[%w@][yY]$&amp;quot;) then&lt;br /&gt;
				return base_stem .. &amp;quot;i&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		elseif umatch(normalized, &amp;quot;[&amp;quot; .. vowels .. &amp;quot;%d]%w*$&amp;quot;) then&lt;br /&gt;
			return base_stem .. &amp;quot;i&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	-- Special cases:&lt;br /&gt;
	-- Final &amp;quot;quy&amp;quot; (&amp;quot;soliloquy&amp;quot; → &amp;quot;soliloquies&amp;quot;).&lt;br /&gt;
	-- Final &amp;quot;guy&amp;quot; iff `not_gu` is false (&amp;quot;roguy&amp;quot; → &amp;quot;roguiest&amp;quot;).&lt;br /&gt;
	-- Final &amp;quot;y&amp;quot; after a vowel iff `final_y_is_i_after_vowel` is true (&amp;quot;slay&amp;quot; →&lt;br /&gt;
	-- &amp;quot;slain&amp;quot;).&lt;br /&gt;
	-- Final &amp;quot;-y&amp;quot; (&amp;quot;bro-y&amp;quot; → &amp;quot;bro-iest&amp;quot;), accounting for hyphen variation.&lt;br /&gt;
	elseif umatch(final2, &amp;quot;[&amp;quot; .. hyphens .. &amp;quot;]y&amp;quot;) then&lt;br /&gt;
		-- Replace final &amp;quot;y&amp;quot; with &amp;quot;i&amp;quot;.&lt;br /&gt;
		return sub(str, 1, -2) .. &amp;quot;i&amp;quot;&lt;br /&gt;
	-- Otherwise, final &amp;quot;y&amp;quot; becomes &amp;quot;i&amp;quot; iff it&amp;#039;s not preceded by a vowel&lt;br /&gt;
	-- (&amp;quot;shy&amp;quot; → &amp;quot;shiest&amp;quot;, &amp;quot;horsy&amp;quot; → &amp;quot;horsies&amp;quot;, but &amp;quot;day&amp;quot; → &amp;quot;days&amp;quot;, &amp;quot;coy&amp;quot; →&lt;br /&gt;
	-- &amp;quot;coyest&amp;quot;).&lt;br /&gt;
	else&lt;br /&gt;
		-- Remove &amp;quot;y&amp;quot; to get the base stem.&lt;br /&gt;
		local base_stem = sub(str, 1, -2)&lt;br /&gt;
		if umatch(normalize(base_stem, &amp;quot;y&amp;quot;, not_gu), &amp;quot;[^%s%p&amp;quot; .. (final_y_is_i_after_vowel and &amp;quot;&amp;quot; or vowels) .. &amp;quot;]$&amp;quot;) then&lt;br /&gt;
			return base_stem .. &amp;quot;i&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function double_final_consonant(str, final)&lt;br /&gt;
	local initial = umatch(normalize(sub(str, 1, -2), final), &amp;quot;^.*%f[^%z%s&amp;quot; .. hyphens .. &amp;quot;…]([%l%p]*)[&amp;quot; .. vowels .. &amp;quot;]$&amp;quot;)&lt;br /&gt;
	return initial and (&lt;br /&gt;
		initial == &amp;quot;&amp;quot; or&lt;br /&gt;
		initial == &amp;quot;y&amp;quot; or&lt;br /&gt;
		match(initial, &amp;quot;^.[\128-\191]*$&amp;quot;) and umatch(initial, &amp;quot;[^&amp;quot; .. vowels .. &amp;quot;]&amp;quot;) or&lt;br /&gt;
		umatch(initial, &amp;quot;^[^&amp;quot; .. vowels .. &amp;quot;]*%f[^%l]$&amp;quot;)&lt;br /&gt;
	) and (str .. final) or str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function remove_silent_e(str)&lt;br /&gt;
	local final2 = sub(str, -2)&lt;br /&gt;
	if final2 == &amp;quot;ie&amp;quot; then&lt;br /&gt;
		-- Replace &amp;quot;ie&amp;quot; with &amp;quot;y&amp;quot;, unless it follows another &amp;quot;y&amp;quot; (e.g.&lt;br /&gt;
		-- &amp;quot;spulyie&amp;quot; → &amp;quot;spulyieing&amp;quot;).&lt;br /&gt;
		return ugsub(str, &amp;quot;([^yY%s%p])ie$&amp;quot;, &amp;quot;%1y&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local base_stem = sub(str, 1, -2)&lt;br /&gt;
	-- Silent &amp;quot;e&amp;quot; occurs after &amp;quot;u&amp;quot; or a consonant (cluster) preceded by a vowel.&lt;br /&gt;
	return (&lt;br /&gt;
		final2 == &amp;quot;ue&amp;quot; or&lt;br /&gt;
		umatch(normalize(base_stem, &amp;quot;e&amp;quot;), &amp;quot;[&amp;quot; .. vowels .. &amp;quot;][^&amp;quot; .. vowels .. &amp;quot;]+$&amp;quot;)&lt;br /&gt;
	) and base_stem or str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function export.add_suffix(term, suffix, pos)&lt;br /&gt;
	local data = suffixes[suffix]&lt;br /&gt;
	suffix = match(suffix, &amp;quot;^([^.]*)&amp;quot;)&lt;br /&gt;
	local final, stem = sub(term, -1)&lt;br /&gt;
	-- Proper nouns don&amp;#039;t have a final &amp;quot;y&amp;quot; changed to &amp;quot;i&amp;quot; (e.g. &amp;quot;the Gettys&amp;quot;,&lt;br /&gt;
	-- &amp;quot;the public Ivys&amp;quot;).&lt;br /&gt;
	if data.final_y_is_i and final == &amp;quot;y&amp;quot; and pos ~= &amp;quot;proper noun&amp;quot; then&lt;br /&gt;
		stem = convert_final_y_to_i(term, not data.final_guy_is_gui, data.final_ey_is_i, data.final_y_is_i_after_vowel)&lt;br /&gt;
	elseif data.remove_silent_e and final == &amp;quot;e&amp;quot; then&lt;br /&gt;
		stem = remove_silent_e(term)&lt;br /&gt;
	else&lt;br /&gt;
		stem = term&lt;br /&gt;
	end&lt;br /&gt;
	local epenthetic_e = data.epenthetic_e&lt;br /&gt;
	if epenthetic_e and epenthetic_e(stem, term) then&lt;br /&gt;
		suffix = &amp;quot;e&amp;quot; .. suffix&lt;br /&gt;
	end&lt;br /&gt;
	if (&lt;br /&gt;
		data.final_consonant_is_doubled and&lt;br /&gt;
		match(final, &amp;quot;^[bcdfgjklmnpqrstvz]$&amp;quot;) and -- Only double regular consonants.&lt;br /&gt;
		umatch(suffix, &amp;quot;^[&amp;quot; .. vowels .. &amp;quot;]&amp;quot;)&lt;br /&gt;
	) then&lt;br /&gt;
		stem = double_final_consonant(term, final)&lt;br /&gt;
	end&lt;br /&gt;
	return stem .. suffix&lt;br /&gt;
end&lt;br /&gt;
add_suffix = export.add_suffix&lt;br /&gt;
&lt;br /&gt;
--[==[&lt;br /&gt;
Pluralize a word in a smart fashion, according to normal English rules.&lt;br /&gt;
# If the word ends in a consonant or &amp;quot;qu&amp;quot; + &amp;quot;-y&amp;quot;, replace &amp;quot;-y&amp;quot; with &amp;quot;-ies&amp;quot;.&lt;br /&gt;
# If the word ends in &amp;quot;s&amp;quot;, &amp;quot;x&amp;quot;, &amp;quot;z&amp;quot;, &amp;quot;ch&amp;quot;, &amp;quot;sh&amp;quot; or &amp;quot;zh&amp;quot;, add &amp;quot;-es&amp;quot;.&lt;br /&gt;
# Otherwise, add &amp;quot;-s&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This handles links correctly:&lt;br /&gt;
# If a piped link, change the second part appropriately.&lt;br /&gt;
# If a non-piped link and rule #1 above applies, convert to a piped link with the second part containing the plural.&lt;br /&gt;
# If a non-piped link and rules #2 or #3 above apply, add the plural outside the link.&lt;br /&gt;
]==]&lt;br /&gt;
function export.pluralize(str)&lt;br /&gt;
	-- Treat as a link if a &amp;quot;[[&amp;quot; is present and the string ends with &amp;quot;]]&amp;quot;.&lt;br /&gt;
	if not (find(str, &amp;quot;[[&amp;quot;, 1, true) and sub(str, -2) == &amp;quot;]]&amp;quot;) then&lt;br /&gt;
		return add_suffix(str, &amp;quot;s.plural&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	-- Find the last &amp;quot;[[&amp;quot; (in case there is more than one) by reversing&lt;br /&gt;
	-- the string.&lt;br /&gt;
	local str_rev = reverse(str)&lt;br /&gt;
	local open = find(str_rev, &amp;quot;[[&amp;quot;, 3, true)&lt;br /&gt;
	-- If the last &amp;quot;[[&amp;quot; is followed by a &amp;quot;]]&amp;quot; which isn&amp;#039;t at the end,&lt;br /&gt;
	-- then the final &amp;quot;]]&amp;quot; is just plaintext (e.g. &amp;quot;[[foo]]bar]]&amp;quot;).&lt;br /&gt;
	local bad_close = find(str_rev, &amp;quot;]]&amp;quot;, 3, true)&lt;br /&gt;
	-- Note: the bad &amp;quot;]]&amp;quot; will have a lower index than the last &amp;quot;[[&amp;quot; in&lt;br /&gt;
	-- the reversed string.&lt;br /&gt;
	if bad_close and bad_close &amp;lt; open then&lt;br /&gt;
		return add_suffix(str, &amp;quot;s.plural&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	open = #str - open + 2&lt;br /&gt;
	-- Get the target and display text by searching from just after &amp;quot;[[&amp;quot;.&lt;br /&gt;
	local target, display = match(str, &amp;quot;([^|]*)|?(.*)%]%]$&amp;quot;, open)&lt;br /&gt;
	display = add_suffix(display ~= &amp;quot;&amp;quot; and display or target, &amp;quot;s.plural&amp;quot;)&lt;br /&gt;
	-- If the link target is a substring of the display text, then&lt;br /&gt;
	-- use a trail (e.g. &amp;quot;[[foo]]&amp;quot; → &amp;quot;[[foo]]s&amp;quot;, since &amp;quot;foo&amp;quot; is a substring&lt;br /&gt;
	-- of &amp;quot;foos&amp;quot;).&lt;br /&gt;
	local index, trail = find(display, target, 1, true)&lt;br /&gt;
	if index == 1 then&lt;br /&gt;
		return sub(str, 1, open - 1) .. target .. &amp;quot;]]&amp;quot; .. sub(display, trail + 1)&lt;br /&gt;
	end&lt;br /&gt;
	-- Otherwise, return a piped link.&lt;br /&gt;
	return sub(str, 1, open - 1) .. target .. &amp;quot;|&amp;quot; .. display .. &amp;quot;]]&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Returns true if `plural` is an expected, regular plural of `term`.&lt;br /&gt;
function export.is_regular_plural(plural, term, pos)&lt;br /&gt;
	-- Ignore any final punctuation that occurs in both forms, which is common&lt;br /&gt;
	-- in abbreviations (e.g. &amp;quot;abbr.&amp;quot; → &amp;quot;abbrs.&amp;quot;).&lt;br /&gt;
	local final_punc = umatch(term, &amp;quot;%p*$&amp;quot;)&lt;br /&gt;
	local final_punc_len = #final_punc&lt;br /&gt;
	if sub(plural, -final_punc_len) == final_punc then&lt;br /&gt;
		term = sub(term, 1, -final_punc_len - 1)&lt;br /&gt;
		plural = sub(plural, 1, -final_punc_len - 1)&lt;br /&gt;
	end&lt;br /&gt;
	if plural == term .. &amp;quot;s&amp;quot; or plural == add_suffix(term, &amp;quot;s.plural&amp;quot;, pos) then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	local final = sub(term, -1)&lt;br /&gt;
	return (&lt;br /&gt;
		-- Doubled final consonants in &amp;quot;s&amp;quot; and &amp;quot;z&amp;quot;.&lt;br /&gt;
		final == &amp;quot;s&amp;quot; and plural == term .. &amp;quot;ses&amp;quot; or -- e.g. &amp;quot;busses&amp;quot;&lt;br /&gt;
		final == &amp;quot;z&amp;quot; and plural == term .. &amp;quot;zes&amp;quot; or -- e.g. &amp;quot;quizzes&amp;quot;&lt;br /&gt;
		-- convert_final_y_to_i() without the `not_gu` flag set, to catch&lt;br /&gt;
		-- &amp;quot;-guy&amp;quot; → &amp;quot;-guies&amp;quot;, but not &amp;quot;day&amp;quot; → &amp;quot;daies&amp;quot;.&lt;br /&gt;
		final == &amp;quot;y&amp;quot; and plural == convert_final_y_to_i(term) .. &amp;quot;es&amp;quot; or&lt;br /&gt;
		-- Capitalized terms like &amp;quot;$DEITY&amp;quot; → &amp;quot;$DEITIES (should we treat this as regular?)&lt;br /&gt;
		final == &amp;quot;Y&amp;quot; and ulower(plural) == convert_final_y_to_i(ulower(term)) .. &amp;quot;es&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return export&lt;/div&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
</feed>