<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://test.st34an.tech/index.php?action=history&amp;feed=atom&amp;title=Module%3ALanguages%2FdoSubstitutions</id>
	<title>Module:Languages/doSubstitutions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://test.st34an.tech/index.php?action=history&amp;feed=atom&amp;title=Module%3ALanguages%2FdoSubstitutions"/>
	<link rel="alternate" type="text/html" href="https://test.st34an.tech/index.php?title=Module:Languages/doSubstitutions&amp;action=history"/>
	<updated>2026-04-10T22:19:15Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://test.st34an.tech/index.php?title=Module:Languages/doSubstitutions&amp;diff=285&amp;oldid=prev</id>
		<title>Jsrs701: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://test.st34an.tech/index.php?title=Module:Languages/doSubstitutions&amp;diff=285&amp;oldid=prev"/>
		<updated>2026-04-10T07:29:35Z</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;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 07:29, 10 April 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&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;!-- diff cache key mediawikidb:diff:1.41:old-284:rev-285 --&gt;
&lt;/table&gt;</summary>
		<author><name>Jsrs701</name></author>
	</entry>
	<entry>
		<id>https://test.st34an.tech/index.php?title=Module:Languages/doSubstitutions&amp;diff=284&amp;oldid=prev</id>
		<title>bob&gt;Juelos: Reverted edit by Juelos (talk) to last revision by Djpwikiadmin</title>
		<link rel="alternate" type="text/html" href="https://test.st34an.tech/index.php?title=Module:Languages/doSubstitutions&amp;diff=284&amp;oldid=prev"/>
		<updated>2025-11-23T08:35:25Z</updated>

		<summary type="html">&lt;p&gt;Reverted edit by &lt;a href=&quot;/index.php?title=Special:Contributions/Juelos&quot; title=&quot;Special:Contributions/Juelos&quot;&gt;Juelos&lt;/a&gt; (&lt;a href=&quot;/index.php?title=User_talk:Juelos&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:Juelos (page does not exist)&quot;&gt;talk&lt;/a&gt;) to last revision by &lt;a href=&quot;/index.php?title=User:Djpwikiadmin&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User:Djpwikiadmin (page does not exist)&quot;&gt;Djpwikiadmin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt; local substitutes&lt;br /&gt;
&lt;br /&gt;
local function doRemoveExceptions(text, sc, remove_exceptions)&lt;br /&gt;
	local gsub = require(&amp;quot;Module:string utilities&amp;quot;).gsub&lt;br /&gt;
	substitutes = {} or substitutes&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _, exception in ipairs(remove_exceptions) do&lt;br /&gt;
		exception = sc:toFixedNFD(exception)&lt;br /&gt;
		text = gsub(text, exception, function(m)&lt;br /&gt;
			i = i + 1&lt;br /&gt;
			table.insert(substitutes, m)&lt;br /&gt;
			return &amp;quot;\127&amp;quot;&lt;br /&gt;
		end)&lt;br /&gt;
	end&lt;br /&gt;
	return text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function undoRemoveExceptions(text)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	return text:gsub(&amp;quot;\127&amp;quot;, function(m1)&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		return substitutes[i]&lt;br /&gt;
	end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function doSubstitutions(text, self, sc, substitution_data, function_name, recursed)&lt;br /&gt;
	local fail, cats = nil, {}&lt;br /&gt;
	-- If there are language-specific substitutes given in the data module, use those.&lt;br /&gt;
	if type(substitution_data) == &amp;quot;table&amp;quot; then&lt;br /&gt;
		-- If a script is specified, run this function with the script-specific data before continuing.&lt;br /&gt;
		local sc_code = sc:getCode()&lt;br /&gt;
		if substitution_data[sc_code] then&lt;br /&gt;
			text, fail, cats = doSubstitutions(text, self, sc, substitution_data[sc_code], function_name, true)&lt;br /&gt;
		-- Hant, Hans and Hani are usually treated the same, so add a special case to avoid having to specify each one separately.&lt;br /&gt;
		elseif sc_code:match(&amp;quot;^Han&amp;quot;) and substitution_data.Hani then&lt;br /&gt;
			text, fail, cats = doSubstitutions(text, self, sc, substitution_data.Hani, function_name, true)&lt;br /&gt;
		-- Substitution data with key 1 in the outer table may be given as a fallback.&lt;br /&gt;
		elseif substitution_data[1] then&lt;br /&gt;
			text, fail, cats = doSubstitutions(text, self, sc, substitution_data[1], function_name, true)&lt;br /&gt;
		end&lt;br /&gt;
		-- Iterate over all strings in the &amp;quot;from&amp;quot; subtable, and gsub with the corresponding string in &amp;quot;to&amp;quot;. We work with the NFD decomposed forms, as this simplifies many substitutions.&lt;br /&gt;
		if substitution_data.from then&lt;br /&gt;
			local gsub = require(&amp;quot;Module:string utilities&amp;quot;).gsub&lt;br /&gt;
			for i, from in ipairs(substitution_data.from) do&lt;br /&gt;
				-- We normalize each loop, to ensure multi-stage substitutions work correctly.&lt;br /&gt;
				text = sc:toFixedNFD(text)&lt;br /&gt;
				-- Check whether specific magic characters are present, as they rely on UTF-8 compatibility. If not, just use string.gsub. In most cases, doing this is faster than using mw.ustring.gsub every time.&lt;br /&gt;
				text = gsub(text, sc:toFixedNFD(from), substitution_data.to[i] or &amp;quot;&amp;quot;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if substitution_data.remove_diacritics then&lt;br /&gt;
			text = sc:toFixedNFD(text)&lt;br /&gt;
			-- Convert exceptions to PUA.&lt;br /&gt;
			if substitution_data.remove_exceptions then&lt;br /&gt;
				text = doRemoveExceptions(text, sc, substitution_data.remove_exceptions)&lt;br /&gt;
			end&lt;br /&gt;
			-- Strip diacritics.&lt;br /&gt;
			text =  require(&amp;quot;Module:string utilities&amp;quot;).gsub(text, &amp;quot;[&amp;quot; .. substitution_data.remove_diacritics .. &amp;quot;]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
			-- Convert exceptions back.&lt;br /&gt;
			if substitution_data.remove_exceptions then&lt;br /&gt;
				text = undoRemoveExceptions(text)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif type(substitution_data) == &amp;quot;string&amp;quot; then&lt;br /&gt;
		-- If there is a dedicated function module, use that.&lt;br /&gt;
		local is_module, module = pcall(require, &amp;quot;Module:&amp;quot; .. substitution_data)&lt;br /&gt;
		if is_module then&lt;br /&gt;
			if function_name == &amp;quot;tr&amp;quot; then&lt;br /&gt;
				text, fail, cats = module[function_name](text, self:getCode(), sc:getCode())&lt;br /&gt;
			else&lt;br /&gt;
				text, fail, cats = module[function_name](sc:toFixedNFD(text), self:getCode(), sc:getCode())&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			error(&amp;quot;Substitution data &amp;#039;&amp;quot; .. substitution_data .. &amp;quot;&amp;#039; does not match an existing module.&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Don&amp;#039;t normalize to NFC if this is the inner loop or if a module returned nil.&lt;br /&gt;
	if recursed or not text then&lt;br /&gt;
		return text, fail, cats&lt;br /&gt;
	else&lt;br /&gt;
		-- Fix any discouraged sequences created during the substitution process, and normalize into the final form.&lt;br /&gt;
		text = sc:fixDiscouragedSequences(text)&lt;br /&gt;
		return sc:toFixedNFC(text), fail, cats&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This avoids calling into globals with require when the main function recurses.&lt;br /&gt;
return function (text, self, sc, substitution_data, function_name)&lt;br /&gt;
	return doSubstitutions(text, self, sc, substitution_data, function_name)&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>bob&gt;Juelos</name></author>
	</entry>
</feed>