<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FErutuon</id>
	<title>Module:Sandbox/Erutuon - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FErutuon"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Erutuon&amp;action=history"/>
	<updated>2026-05-27T06:40:20Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/Erutuon&amp;diff=145373&amp;oldid=prev</id>
		<title>imported&gt;Erutuon: function to print data module for &quot;default ignorable&quot; property</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Erutuon&amp;diff=145373&amp;oldid=prev"/>
		<updated>2019-09-16T09:39:40Z</updated>

		<summary type="html">&lt;p&gt;function to print data module for &amp;quot;default ignorable&amp;quot; property&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.show(frame)&lt;br /&gt;
	local page = frame.args[1] or &amp;quot;User:Erutuon/Unicode/DerivedCoreProperties.txt&amp;quot;&lt;br /&gt;
	local text = assert(mw.title.new(page):getContent())&lt;br /&gt;
	local defaultIgnorable = text&lt;br /&gt;
		:match(&amp;quot;Derived Property: Default_Ignorable_Code_Point.-(%f[^\n]%x%x%x%x.-)%s*\n# Total code points&amp;quot;)&lt;br /&gt;
	local singles, ranges = {}, {}&lt;br /&gt;
	for codePoint1, codePoint2 in defaultIgnorable:gmatch(&amp;quot;%f[^\n%z](%x+)%.?%.?(%x*)&amp;quot;) do&lt;br /&gt;
		codePoint1, codePoint2 = tonumber(codePoint1, 16), tonumber(codePoint2, 16)&lt;br /&gt;
		local lastRange = ranges[#ranges]&lt;br /&gt;
		if lastRange and lastRange[2] == codePoint1 - 1 then&lt;br /&gt;
			lastRange[2] = codePoint2 or codePoint1&lt;br /&gt;
		else&lt;br /&gt;
			if not codePoint2 then&lt;br /&gt;
				singles[codePoint1] = true&lt;br /&gt;
			else&lt;br /&gt;
				table.insert(ranges, { codePoint1, codePoint2 })&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
		local template = [[&lt;br /&gt;
local data = {}&lt;br /&gt;
&lt;br /&gt;
data.defaultIgnorable = {&lt;br /&gt;
	singles = {&lt;br /&gt;
...&lt;br /&gt;
	},&lt;br /&gt;
	&lt;br /&gt;
	ranges = {&lt;br /&gt;
...&lt;br /&gt;
	},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return data&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
	local Array = require &amp;quot;Module:array&amp;quot;&lt;br /&gt;
	local printedRanges = Array()&lt;br /&gt;
	for _, range in ipairs(ranges) do&lt;br /&gt;
		local low, high, script_code = unpack(range)&lt;br /&gt;
		printedRanges:insert((&amp;#039;\t\t{ 0x%05X, 0x%05X },&amp;#039;):format(low, high))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local printedSingles = Array()&lt;br /&gt;
	for codepoint in require &amp;#039;Module:TableTools&amp;#039;.sortedPairs(singles) do&lt;br /&gt;
		printedSingles:insert((&amp;#039;\t\t[0x%05X] = true,&amp;#039;):format(codepoint))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local data = template&lt;br /&gt;
		:gsub(&amp;#039;%.%.%.&amp;#039;, printedSingles:concat(&amp;#039;\n&amp;#039;), 1)&lt;br /&gt;
		:gsub(&amp;#039;%.%.%.&amp;#039;, printedRanges:concat(&amp;#039;\n&amp;#039;), 1)&lt;br /&gt;
	&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local Unicode_data = require &amp;quot;Module:Unicode data/sandbox&amp;quot;&lt;br /&gt;
local fun = require &amp;quot;Module:fun&amp;quot;&lt;br /&gt;
local m_table = require &amp;quot;Module:TableTools&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local function errorf(level, ...)&lt;br /&gt;
	if type(level) == &amp;quot;number&amp;quot; then&lt;br /&gt;
		return error(string.format(...), level + 1)&lt;br /&gt;
	else -- level is actually the format string.&lt;br /&gt;
		return error(string.format(level, ...), 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.search_for_language_codes(frame)&lt;br /&gt;
	local page_name = frame.args[1] or &amp;quot;English language&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	local success, title_object = pcall(mw.title.new, page_name)&lt;br /&gt;
	if not (success and title_object) then&lt;br /&gt;
		mw.logf(&amp;quot;Could not make title object for &amp;#039;%s&amp;#039;.&amp;quot;, page_name)&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local content = title_object:getContent()&lt;br /&gt;
	&lt;br /&gt;
	local language_codes = {}&lt;br /&gt;
	for lang_template in content:gmatch &amp;quot;{{lang[^}]+&amp;quot; do&lt;br /&gt;
		local template_name = lang_template:match(&amp;quot;{{([^|}]+)&amp;quot;)&lt;br /&gt;
		local language_code&lt;br /&gt;
		if template_name == &amp;quot;lang&amp;quot; then&lt;br /&gt;
			language_code = lang_template:match &amp;quot;{{lang|([^|}]+)&amp;quot;&lt;br /&gt;
		elseif template_name:find &amp;quot;^lang-&amp;quot; then&lt;br /&gt;
			language_code = lang_template:match &amp;quot;{{lang-([^|}]+)&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		if language_code then&lt;br /&gt;
			language_codes[language_code] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(m_table.keysToList(language_codes), &amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local parsed_subtags_mt = {&lt;br /&gt;
	__index = {&lt;br /&gt;
		-- &amp;quot;error&amp;quot; is the error message.&lt;br /&gt;
		-- &amp;quot;index&amp;quot; is the ordinal of the subtag in which the error was found.&lt;br /&gt;
		throw = function (self, error, index)&lt;br /&gt;
			self.error = self.error_messages[error]&lt;br /&gt;
			self.invalid = table.concat(self.input, &amp;quot;-&amp;quot;, index)&lt;br /&gt;
			return self:remove_unnecessary_fields()&lt;br /&gt;
		end,&lt;br /&gt;
		&lt;br /&gt;
		remove_unnecessary_fields = function (self)&lt;br /&gt;
			-- Only useful internally.&lt;br /&gt;
			self.input = nil&lt;br /&gt;
			self:pretty_print()&lt;br /&gt;
			p.validate_lang_tag(self)&lt;br /&gt;
			return self&lt;br /&gt;
		end,&lt;br /&gt;
		&lt;br /&gt;
		-- Regularize capitalization of language subtags:&lt;br /&gt;
		-- ZH-LATN -&amp;gt; zh-Latn, FR-ca -&amp;gt; fr-CA&lt;br /&gt;
		pretty_print = function (self)&lt;br /&gt;
			for key, func in pairs(self.print_funcs) do&lt;br /&gt;
				if self[key] then&lt;br /&gt;
					self[key] = func(self[key])&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return self&lt;br /&gt;
		end,&lt;br /&gt;
		&lt;br /&gt;
		-- Re-create the original tag from the parsed subtags.&lt;br /&gt;
		get_tag = function (self)&lt;br /&gt;
			if self.tag then return self.tag end&lt;br /&gt;
			&lt;br /&gt;
			local tag = {}&lt;br /&gt;
			for _, subtag_name in ipairs(self.subtag_order) do&lt;br /&gt;
				if subtag_name == &amp;quot;private_use&amp;quot; then&lt;br /&gt;
					table.insert(tag, &amp;quot;x&amp;quot;)&lt;br /&gt;
				end&lt;br /&gt;
				&lt;br /&gt;
				if type(self[subtag_name]) == &amp;quot;table&amp;quot; then&lt;br /&gt;
					for _, subtag in ipairs(self[subtag_name]) do&lt;br /&gt;
						table.insert(tag, subtag)&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					table.insert(tag, self[subtag_name])&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			tag = table.concat(tag, &amp;quot;-&amp;quot;)&lt;br /&gt;
			self.tag = tag -- Cache the result.&lt;br /&gt;
			&lt;br /&gt;
			return tag&lt;br /&gt;
		end,&lt;br /&gt;
		&lt;br /&gt;
		subtag_order = {&lt;br /&gt;
			&amp;quot;language&amp;quot;, &amp;quot;script&amp;quot;, &amp;quot;region&amp;quot;, &amp;quot;variant&amp;quot;, &amp;quot;private_use&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&lt;br /&gt;
		error_messages = {&lt;br /&gt;
			invalid_characters = &amp;quot;invalid characters&amp;quot;,&lt;br /&gt;
			no_language = &amp;quot;no language subtag&amp;quot;,&lt;br /&gt;
			invalid_subtag = &amp;quot;invalid subtag&amp;quot;,&lt;br /&gt;
			invalid_private_use = &amp;quot;length of private-use subtag out of range&amp;quot;,&lt;br /&gt;
			empty_private_use = &amp;quot;empty private-use subtag&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
local function initial_caps_helper(initial, rest)&lt;br /&gt;
	return string.upper(initial) .. string.lower(rest)&lt;br /&gt;
end&lt;br /&gt;
local function lower_or_map_lower(str)&lt;br /&gt;
	if type(str) == &amp;quot;table&amp;quot; then&lt;br /&gt;
		return fun.map(string.lower, str)&lt;br /&gt;
	else&lt;br /&gt;
		return string.lower(str)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
parsed_subtags_mt.__index.print_funcs = {&lt;br /&gt;
	language = string.lower,&lt;br /&gt;
	script = function (script_code)&lt;br /&gt;
		return (string.gsub(script_code, &amp;quot;^(%a)(%a%a%a)$&amp;quot;, initial_caps_helper))&lt;br /&gt;
	end,&lt;br /&gt;
	region = string.upper,&lt;br /&gt;
	variant = lower_or_map_lower,&lt;br /&gt;
	private_use = lower_or_map_lower,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
setmetatable(parsed_subtags_mt, {&lt;br /&gt;
	__call = function (self, input)&lt;br /&gt;
		return setmetatable({ input = input }, self)&lt;br /&gt;
	end&lt;br /&gt;
})&lt;br /&gt;
	&lt;br /&gt;
-- An array of patterns for each subtag, and a &amp;quot;type&amp;quot; field for the name&lt;br /&gt;
-- of the subtag.&lt;br /&gt;
-- The patterns are checked in order, and any of the subtags can be skipped.&lt;br /&gt;
-- So, for example, the &amp;quot;language&amp;quot; subtag must precede the &amp;quot;script&amp;quot;&lt;br /&gt;
-- subtag, but a tag may contain a &amp;quot;language&amp;quot; subtag, no &amp;quot;script&amp;quot; subtag&lt;br /&gt;
-- and then a &amp;quot;region&amp;quot; subtag.&lt;br /&gt;
-- If the full list of subtags has been iterated over, the remaining subtags&lt;br /&gt;
-- must match the pattern for a private-use subtag, or the tag is invalid.&lt;br /&gt;
local subtag_info = { -- can be put in data module&lt;br /&gt;
	{ &amp;quot;%a%a%a?&amp;quot;, &amp;quot;1%a+&amp;quot;, type = &amp;quot;language&amp;quot; }, -- ll or lll; special case&lt;br /&gt;
	-- include extlang?&lt;br /&gt;
	{ &amp;quot;%a%a%a%a&amp;quot;, type = &amp;quot;script&amp;quot; }, -- Ssss&lt;br /&gt;
	{ &amp;quot;%a%a&amp;quot;, &amp;quot;%d%d%d&amp;quot;, type = &amp;quot;region&amp;quot; }, -- rr, DDD&lt;br /&gt;
	{&lt;br /&gt;
		&amp;quot;%d%d%d%d&amp;quot;, -- 4 digits&lt;br /&gt;
		&amp;quot;%w%w%w%w%w%w?%w?%w?&amp;quot;, -- 5-8 alnum characters&lt;br /&gt;
		type = &amp;quot;variant&amp;quot;,&lt;br /&gt;
		repeatable = true, -- There can be multiple variants.&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- A previous draft, in [[Module:Lang/sandbox]]:&lt;br /&gt;
-- https://en.wikipedia.org/w/index.php?oldid=812819217&lt;br /&gt;
&lt;br /&gt;
-- Based on https://www.w3.org/International/articles/language-tags/.&lt;br /&gt;
&lt;br /&gt;
-- Parse a language tag.&lt;br /&gt;
-- Returns nil if tag is not a string or empty.&lt;br /&gt;
-- Else returns a table with a map of subtag type to subtag for all subtags that&lt;br /&gt;
-- were parsed.&lt;br /&gt;
-- If there was an error, returns an &amp;quot;error&amp;quot; field with a description of the&lt;br /&gt;
-- error, and an &amp;quot;invalid&amp;quot; field with the suffix of the tag starting at the&lt;br /&gt;
-- index where the error occurred.&lt;br /&gt;
&lt;br /&gt;
-- Does not recognize &amp;quot;extension&amp;quot; tags, such as those introduced by &amp;quot;u&amp;quot;, as they&lt;br /&gt;
-- are not needed on Wikipedia. Does not recognize &amp;quot;grandfathered&amp;quot; tags.&lt;br /&gt;
-- Does not recognize extended language subtags, such as &amp;quot;zh-yue&amp;quot;.&lt;br /&gt;
-- https://www.rfc-editor.org/rfc/rfc6067.txt, https://tools.ietf.org/html/bcp47&lt;br /&gt;
&lt;br /&gt;
-- Only checks that the syntax is correct, not that the values are valid. For&lt;br /&gt;
-- instance, will accept non-existent language codes, like &amp;quot;zz&amp;quot;.&lt;br /&gt;
function p.parse_IETF(tag)&lt;br /&gt;
	if type(tag) ~= &amp;quot;string&amp;quot; or tag == &amp;quot;&amp;quot;  then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- This may contain the special fields &amp;quot;invalid&amp;quot;, &amp;quot;error&amp;quot;.&lt;br /&gt;
	-- &amp;quot;error&amp;quot; indicates why the&lt;br /&gt;
	-- tag is invalid (if applicable).&lt;br /&gt;
	-- All other fields are subtags, and they appear in the tag in the following&lt;br /&gt;
	-- order:&lt;br /&gt;
	-- &amp;quot;language&amp;quot;, &amp;quot;script&amp;quot;, &amp;quot;region&amp;quot;, &amp;quot;variant&amp;quot;, &amp;quot;private_use&amp;quot;, &amp;quot;invalid&amp;quot;&lt;br /&gt;
	-- All these subtags can be strings or nil, while &amp;quot;variant&amp;quot; can also be an&lt;br /&gt;
	-- array of strings if more than one variant subtag was found.&lt;br /&gt;
	-- &amp;quot;invalid&amp;quot; is the portion of the tag after the last valid subtag (minus a&lt;br /&gt;
	-- hyphen).&lt;br /&gt;
	local segments = mw.text.split(tag, &amp;quot;-&amp;quot;)&lt;br /&gt;
	local parsed_subtags = parsed_subtags_mt(segments)&lt;br /&gt;
	&lt;br /&gt;
	-- Language tags probably only contain ASCII alphabetic and numerical&lt;br /&gt;
	-- characters and hyphen-minus.&lt;br /&gt;
	if not tag:find &amp;quot;^[A-Za-z0-9-]+$&amp;quot; then&lt;br /&gt;
		return parsed_subtags:throw(&lt;br /&gt;
			&amp;quot;invalid_characters&amp;quot;,&lt;br /&gt;
			fun.indexOf(&lt;br /&gt;
				function (tag)&lt;br /&gt;
					return tag:find &amp;quot;[^A-Za-z0-9-]&amp;quot;&lt;br /&gt;
				end,&lt;br /&gt;
				segments))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local subtag_i = 1 -- Index of current item in subtag_info.&lt;br /&gt;
	local segment_i = 1 -- Index of current segment.&lt;br /&gt;
	while segments[segment_i] and subtag_info[subtag_i] do&lt;br /&gt;
		local segment = segments[segment_i]&lt;br /&gt;
		local subtag_type&lt;br /&gt;
		while not subtag_type and subtag_info[subtag_i] do&lt;br /&gt;
			-- Check each pattern for the subtag type at &amp;quot;subtag_i&amp;quot; in &amp;quot;subtag_info&amp;quot;.&lt;br /&gt;
			local cur_subtag = subtag_info[subtag_i]&lt;br /&gt;
			for _, pattern in ipairs(cur_subtag) do&lt;br /&gt;
				if segment:find(&amp;quot;^&amp;quot; .. pattern .. &amp;quot;$&amp;quot;) then&lt;br /&gt;
					subtag_type = cur_subtag.type&lt;br /&gt;
					-- There can be multiple &amp;quot;variant&amp;quot; subtags (and &amp;quot;extension&amp;quot;&lt;br /&gt;
					-- subtags, if those are added).&lt;br /&gt;
					if not cur_subtag.repeatable then&lt;br /&gt;
						subtag_i = subtag_i + 1&lt;br /&gt;
					end&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			if not subtag_type then -- No match; try next subtag.&lt;br /&gt;
				subtag_i = subtag_i + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- If language subtag has not been found, or the current segment has not&lt;br /&gt;
		-- been matched as a subtag, break the loop and check for&lt;br /&gt;
		-- a private-use subtag.&lt;br /&gt;
		if segment_i == 1 and subtag_type ~= &amp;quot;language&amp;quot; or not subtag_type then&lt;br /&gt;
			break&lt;br /&gt;
		else&lt;br /&gt;
			if parsed_subtags[subtag_type] then -- Create an array.&lt;br /&gt;
				if type(parsed_subtags[subtag_type]) == &amp;quot;string&amp;quot; then&lt;br /&gt;
					parsed_subtags[subtag_type] = { parsed_subtags[subtag_type] }&lt;br /&gt;
				end -- else table&lt;br /&gt;
				table.insert(parsed_subtags[subtag_type], segment)&lt;br /&gt;
			else&lt;br /&gt;
				parsed_subtags[subtag_type] = segment&lt;br /&gt;
			end&lt;br /&gt;
			last_matched_segment_i = segment_i&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		segment_i = segment_i + 1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if segments[segment_i] then -- More segments to scan?&lt;br /&gt;
		-- Not all potential subtags were matched. Check for private-use subtags.&lt;br /&gt;
		-- https://tools.ietf.org/html/bcp47#section-2.2.7&lt;br /&gt;
		-- Private-use subtags consist of one or more sequences of 1 to 8&lt;br /&gt;
		-- alphanumeric characters preceded by &amp;quot;x-&amp;quot;.&lt;br /&gt;
		-- Alphanumericity has already been checked.&lt;br /&gt;
		&lt;br /&gt;
		 -- A tag must start with either a language subtag or a private-use subtag.&lt;br /&gt;
		 -- If next segment is not &amp;quot;x&amp;quot;, introducing a private-use subtag, there&lt;br /&gt;
		 -- is no private-use subtag.&lt;br /&gt;
		if segments[segment_i] and segments[segment_i]:lower() ~= &amp;quot;x&amp;quot; then&lt;br /&gt;
			if not parsed_subtags.language then&lt;br /&gt;
				return parsed_subtags:throw(&amp;quot;no_language&amp;quot;, 1)&lt;br /&gt;
			else&lt;br /&gt;
				return parsed_subtags:throw(&amp;quot;invalid_subtag&amp;quot;,&lt;br /&gt;
					segment_i)&lt;br /&gt;
			end&lt;br /&gt;
		elseif not segments[segment_i + 1] then&lt;br /&gt;
			return parsed_subtags:throw(&amp;quot;empty_private_use&amp;quot;,&lt;br /&gt;
				segment_i)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Check length of all segments after &amp;quot;x&amp;quot;.&lt;br /&gt;
		for i = segment_i + 1, #segments do&lt;br /&gt;
			local length = #segments[i]&lt;br /&gt;
			&lt;br /&gt;
			if not (1 &amp;lt;= length and length &amp;lt;= 8) then&lt;br /&gt;
				return parsed_subtags&lt;br /&gt;
					:throw(&amp;quot;invalid_private_use&amp;quot;, segment_i)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if not segments[last_matched_segment_i + 3] then -- There is only one private-use subtag.&lt;br /&gt;
			parsed_subtags.private_use = segments[segment_i + 1]&lt;br /&gt;
		else&lt;br /&gt;
			parsed_subtags.private_use = {}&lt;br /&gt;
			for i = segment_i + 1, #segments do&lt;br /&gt;
				table.insert(parsed_subtags.private_use, segments[i])&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return parsed_subtags:remove_unnecessary_fields()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local lang_name_table = mw.loadData &amp;quot;Module:Language/name/data&amp;quot;&lt;br /&gt;
local synonym_table = mw.loadData &amp;quot;Module:Lang/ISO 639 synonyms&amp;quot;&lt;br /&gt;
local lang_data =  mw.loadData &amp;quot;Module:Lang/data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function p.validate_lang_tag(parsed_subtags)&lt;br /&gt;
	-- Already checked that the tag starts with a language subtag or a private-use subtag.&lt;br /&gt;
	-- Script code is initially capitalized, region code is uppercase,&lt;br /&gt;
	-- everything else is lowercase.&lt;br /&gt;
	&lt;br /&gt;
	-- Check existence of language tag.&lt;br /&gt;
	if parsed_subtags.language and&lt;br /&gt;
			not (lang_data.override[parsed_subtags.language]&lt;br /&gt;
			or lang_name_table.lang[parsed_subtags.language]) then&lt;br /&gt;
		mw.log(&amp;quot;Invalid language code&amp;quot;, parsed_subtags.language, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check existence of script tag.&lt;br /&gt;
	if parsed_subtags.script then&lt;br /&gt;
		local lower_script = parsed_subtags.script:lower()&lt;br /&gt;
		if not lang_name_table.script[lower_script] then&lt;br /&gt;
			mw.log(&amp;quot;Invalid script code&amp;quot;, parsed_subtags.script, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Check that script tag is not marked as superfluous (because the&lt;br /&gt;
		-- it is considered the default one for the language).&lt;br /&gt;
		if lang_name_table.suppressed[lower_script]&lt;br /&gt;
				and parsed_subtags.language&lt;br /&gt;
				and m_table.inArray(&lt;br /&gt;
					lang_name_table.suppressed[lower_script],&lt;br /&gt;
					parsed_subtags.language:lower()) then&lt;br /&gt;
			mw.log(parsed_subtags.script, &amp;quot;is suppressed with&amp;quot;,&lt;br /&gt;
				parsed_subtags.language, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check existence of region code..&lt;br /&gt;
	if parsed_subtags.region and not lang_name_table.region[parsed_subtags.region:lower()] then&lt;br /&gt;
		mw.log(&amp;quot;Invalid region code&amp;quot;, parsed_subtags.region, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check that variant code is valid, and that it can validly be used with the&lt;br /&gt;
	-- given combination of language, script, region, and variant.&lt;br /&gt;
	-- Check for duplicate variant subtags?&lt;br /&gt;
	if parsed_subtags.variant then&lt;br /&gt;
		local lower_tag = parsed_subtags:get_tag():lower()&lt;br /&gt;
		&lt;br /&gt;
		for _, variant in ipairs(type(parsed_subtags.variant) == &amp;quot;table&amp;quot;&lt;br /&gt;
				and parsed_subtags.variant or { parsed_subtags.variant }) do&lt;br /&gt;
			if not lang_name_table.variant[variant] then&lt;br /&gt;
				mw.log(&amp;quot;Invalid variant code&amp;quot;, variant, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
			else&lt;br /&gt;
				local prefix = parsed_subtags:get_tag():lower():match(&amp;quot;^(.-)%-&amp;quot; .. variant)&lt;br /&gt;
				&lt;br /&gt;
				-- Check that at least one of the prefixes is found at the&lt;br /&gt;
				-- beginning of lower_tag.&lt;br /&gt;
				if not fun.some(function (prefix)&lt;br /&gt;
							return lower_tag:find(prefix, 1, true) == 1&lt;br /&gt;
						end,&lt;br /&gt;
						lang_name_table.variant[variant].prefixes) then&lt;br /&gt;
					mw.log(&amp;quot;Variant tag&amp;quot;, variant, &amp;quot;does not belong with prefix&amp;quot;,&lt;br /&gt;
						prefix, &amp;quot;in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check that the private-use subtag is actually used by Wikipedia.&lt;br /&gt;
	if parsed_subtags.private_use and not lang_data.override[parsed_subtags.tag] then&lt;br /&gt;
		mw.log(&amp;quot;Invalid private-use subtag in&amp;quot;, parsed_subtags:get_tag())&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.show_COinS(frame)&lt;br /&gt;
	local ref = frame.args[1]&lt;br /&gt;
	&lt;br /&gt;
	local tag = ref:match(&amp;#039;&amp;lt;span [^&amp;gt;]*class=&amp;quot;Z3988&amp;quot;[^&amp;gt;]*&amp;gt;&amp;#039;)&lt;br /&gt;
	local data = tag:match(&amp;#039;title=&amp;quot;(.-)&amp;quot;&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	local vals = {}&lt;br /&gt;
	&lt;br /&gt;
	for item in mw.text.gsplit(data, &amp;quot;&amp;amp;&amp;quot;) do&lt;br /&gt;
		local key, value = item:match(&amp;quot;(.-)=(.*)&amp;quot;)&lt;br /&gt;
		vals[key] = mw.uri.decode(value)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return ref .. &amp;quot;\n\n&amp;quot; .. table.concat(&lt;br /&gt;
		require &amp;quot;Module:fun&amp;quot;.mapIter(&lt;br /&gt;
			function (value, key)&lt;br /&gt;
				return (&amp;quot;%s: %s&amp;quot;):format(key, value)&lt;br /&gt;
			end,&lt;br /&gt;
			m_table.sortedPairs(&lt;br /&gt;
				vals)),&lt;br /&gt;
		&amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Erutuon</name></author>
	</entry>
</feed>