<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://austenasia.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Austenasia</id>
	<title>Austenasia Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://austenasia.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Austenasia"/>
	<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Special:Contributions/Austenasia"/>
	<updated>2026-08-23T12:33:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=121</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=121"/>
		<updated>2026-06-22T06:10:17Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Austenasia Wiki&#039;&#039;&#039; is the official encyclopaedia of the [[Empire of Austenasia]]. Information concerning Austenasia published by third parties may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking authoritative information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;br /&gt;
&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=120</id>
		<title>Lord Protector</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=120"/>
		<updated>2026-06-22T06:06:09Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Lord Protector of the Empire of Austenasia&#039;&#039;&#039; (formerly the &#039;&#039;Lord Protector of the Commonwealth of Austenasia&#039;&#039;) is a title of the acting [[wikipedia:head of state|head of state]] during the [[Austenasian Interregnum]]. The current holder is Lord [[Andrew Musgrave]], who also serves as [[Prime Minister]] and [[Regent to the Crown]].&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Regent&amp;diff=119</id>
		<title>Regent</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Regent&amp;diff=119"/>
		<updated>2026-06-22T06:04:07Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Redirected page to Regent to the Crown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Regent to the Crown]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=118</id>
		<title>List of Austenasian monarchs</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=118"/>
		<updated>2026-06-22T06:03:51Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* Interregnum */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;[[Emperor of Austenasia]]&#039;&#039;&#039; is the sovereign and head of state of the Empire of Austenasia. Since the foundation of Austenasia in 2008, five individuals have reigned as monarch. Since the [[overthrow of Aggelos I]] on 3 June 2025, the monarchy has been vacant during the [[Austenasian Interregnum]], during which [[Andrew Musgrave]] has served as [[Lord Protector]] and [[Regent]].&lt;br /&gt;
&lt;br /&gt;
==List of monarchs==&lt;br /&gt;
===Monarchs===&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Terry I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 September 2008&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 September 2008|16 February 2010|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorTerryI.jpg|140px]]&lt;br /&gt;
| [[File:Austenarms.png|140px]]&lt;br /&gt;
| 16 May 1961 &lt;br /&gt;
| [[Austen]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Esmond III]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 September 2011&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|16 February 2010|20 September 2011|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorEsmondIII.jpg|140px]]&lt;br /&gt;
| [[File:Cypher_of_Esmond_III_of_Austenasia.svg|140px]]&lt;br /&gt;
| 9 June 1995 &lt;br /&gt;
| McLaughlin&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Declan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;19 December 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|19 December 2010|20 January 2013|duration=yes}})&lt;br /&gt;
| [[File:ICDA2.jpg|140px]]&lt;br /&gt;
| [[File:Declanmonogram.png|140px]]&lt;br /&gt;
| 20 May 1994&lt;br /&gt;
| Mac Donnchadha-Houghton&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Jonathan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 January 2013|29 September 2024|duration=yes}})&lt;br /&gt;
| [[File:ICJA20.jpg|140px]]&lt;br /&gt;
| [[File:ICJAcipher3.png|140px]]&lt;br /&gt;
| 13 October 1994&lt;br /&gt;
| Austen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Aggelos I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;3 June 2025&amp;lt;br/&amp;gt;&#039;&#039; ([[Overthrown]] after {{Age in years and days|29 September 2024|3 June 2025|duration=yes}})&lt;br /&gt;
| [[File:Basileus_Aggelos.jpg|140px]]&lt;br /&gt;
| [[File:Imperial_Cipher_Emperor_Aggelos_of_Austenasia.png|140px]]&lt;br /&gt;
| 1 September 1981 &lt;br /&gt;
| Vatazides&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Interregnum===&lt;br /&gt;
Austenasia currently has no reigning monarch, with Lord Protector [[Andrew Musgrave]] serving as [[Lord Protector]] and [[Regent]] to the Crown during the [[Austenasian Interregnum|ongoing interregnum]]. Despite the vacancy of the throne, the [[Aggelosites]] continued to maintain their own rival claim to the Austenasian Crown, although this claim was not recognised by the Government of Austenasia.&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Andrew Musgrave]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;3 June 2025 &amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|3 June 2025}})&lt;br /&gt;
| [[File:AndrewOfficialAustenasianPortrait.png|140px]]&lt;br /&gt;
| [[File:Coat of Arms of House Musgrave.png|140px]]&lt;br /&gt;
| 8 September 1999 &lt;br /&gt;
| [[Musgrave]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=117</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=117"/>
		<updated>2026-06-22T06:03:14Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Austenasia Wiki&#039;&#039;&#039; is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published by third parties may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking authoritative information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;br /&gt;
&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=116</id>
		<title>Lord Protector</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=116"/>
		<updated>2026-06-22T06:02:39Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Lord Protector of the Empire of Austenasia&#039;&#039;&#039; (formerly the &#039;&#039;Lord Protector of the Commonwealth of Austenasia&#039;&#039;) is a title of the acting [[w:head of state|head of state]] during the [[Austenasian Interregnum]]. The current holder is Lord [[Andrew Musgrave]], who also serves as [[Prime Minister]] and [[Regent to the Crown]].&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=115</id>
		<title>Lord Protector</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=115"/>
		<updated>2026-06-22T06:02:01Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Lord Protector of the Empire of Austenasia&#039;&#039;&#039; (formerly the &#039;&#039;Lord Protector of the Commonwealth of Austenasia&#039;&#039;) is a title of the acting [[w:head of state|head of state]] during the [[Austenasian Interregnum]]. The current holder is Lord [[Andrew Musgrave]], who also serves as [[Prime Minister]] and [[Regent to the Crown]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=114</id>
		<title>Lord Protector</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=114"/>
		<updated>2026-06-22T06:01:32Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Lord Protector of the Empire of Austenasia&#039;&#039;&#039; (formerly the &#039;&#039;Lord Protector of the Commonwealth of Austenasia&#039;&#039;) is a title for the acting [[w:head of state|head of state]] during the [[Austenasian Interregnum]]. The current holder is Lord [[Andrew Musgrave]], who also serves as [[Prime Minister]] and [[Regent to the Crown]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=113</id>
		<title>Lord Protector</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Lord_Protector&amp;diff=113"/>
		<updated>2026-06-22T06:00:57Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;The &amp;#039;&amp;#039;&amp;#039;Lord Protector of the Empire of Austenasia&amp;#039;&amp;#039;&amp;#039; (formerly the &amp;#039;&amp;#039;Lord Protector of the Commonwealth of Austenasia&amp;#039;&amp;#039;) is a title for the acting head of state during the Austenasian Interregnum&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Lord Protector of the Empire of Austenasia&#039;&#039;&#039; (formerly the &#039;&#039;Lord Protector of the Commonwealth of Austenasia&#039;&#039;) is a title for the acting [[w:head of state|head of state]] during the [[Austenasian Interregnum]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=112</id>
		<title>List of Austenasian monarchs</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=112"/>
		<updated>2026-06-22T05:58:26Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* Interregnum */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;[[Emperor of Austenasia]]&#039;&#039;&#039; is the sovereign and head of state of the Empire of Austenasia. Since the foundation of Austenasia in 2008, five individuals have reigned as monarch. Since the [[overthrow of Aggelos I]] on 3 June 2025, the monarchy has been vacant during the [[Austenasian Interregnum]], during which [[Andrew Musgrave]] has served as [[Lord Protector]] and [[Regent]].&lt;br /&gt;
&lt;br /&gt;
==List of monarchs==&lt;br /&gt;
===Monarchs===&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Terry I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 September 2008&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 September 2008|16 February 2010|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorTerryI.jpg|140px]]&lt;br /&gt;
| [[File:Austenarms.png|140px]]&lt;br /&gt;
| 16 May 1961 &lt;br /&gt;
| [[Austen]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Esmond III]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 September 2011&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|16 February 2010|20 September 2011|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorEsmondIII.jpg|140px]]&lt;br /&gt;
| [[File:Cypher_of_Esmond_III_of_Austenasia.svg|140px]]&lt;br /&gt;
| 9 June 1995 &lt;br /&gt;
| McLaughlin&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Declan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;19 December 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|19 December 2010|20 January 2013|duration=yes}})&lt;br /&gt;
| [[File:ICDA2.jpg|140px]]&lt;br /&gt;
| [[File:Declanmonogram.png|140px]]&lt;br /&gt;
| 20 May 1994&lt;br /&gt;
| Mac Donnchadha-Houghton&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Jonathan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 January 2013|29 September 2024|duration=yes}})&lt;br /&gt;
| [[File:ICJA20.jpg|140px]]&lt;br /&gt;
| [[File:ICJAcipher3.png|140px]]&lt;br /&gt;
| 13 October 1994&lt;br /&gt;
| Austen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Aggelos I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;3 June 2025&amp;lt;br/&amp;gt;&#039;&#039; ([[Overthrown]] after {{Age in years and days|29 September 2024|3 June 2025|duration=yes}})&lt;br /&gt;
| [[File:Basileus_Aggelos.jpg|140px]]&lt;br /&gt;
| [[File:Imperial_Cipher_Emperor_Aggelos_of_Austenasia.png|140px]]&lt;br /&gt;
| 1 September 1981 &lt;br /&gt;
| Vatazides&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Interregnum===&lt;br /&gt;
Austenasia currently has no reigning monarch, with Lord Protector [[Andrew Musgrave]] serving as head of state and [[Regent]] to the Crown during the [[Austenasian Interregnum|ongoing interregnum]]. Despite the vacancy of the throne, the [[Aggelosites]] continued to maintain their own rival claim to the Austenasian Crown, although this claim was not recognised by the Government of Austenasia.&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Andrew Musgrave]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;3 June 2025 &amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|3 June 2025}})&lt;br /&gt;
| [[File:AndrewOfficialAustenasianPortrait.png|140px]]&lt;br /&gt;
| [[File:Coat of Arms of House Musgrave.png|140px]]&lt;br /&gt;
| 8 September 1999 &lt;br /&gt;
| [[Musgrave]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=111</id>
		<title>List of Austenasian monarchs</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=111"/>
		<updated>2026-06-22T05:57:38Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;[[Emperor of Austenasia]]&#039;&#039;&#039; is the sovereign and head of state of the Empire of Austenasia. Since the foundation of Austenasia in 2008, five individuals have reigned as monarch. Since the [[overthrow of Aggelos I]] on 3 June 2025, the monarchy has been vacant during the [[Austenasian Interregnum]], during which [[Andrew Musgrave]] has served as [[Lord Protector]] and [[Regent]].&lt;br /&gt;
&lt;br /&gt;
==List of monarchs==&lt;br /&gt;
===Monarchs===&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Terry I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 September 2008&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 September 2008|16 February 2010|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorTerryI.jpg|140px]]&lt;br /&gt;
| [[File:Austenarms.png|140px]]&lt;br /&gt;
| 16 May 1961 &lt;br /&gt;
| [[Austen]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Esmond III]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 September 2011&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|16 February 2010|20 September 2011|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorEsmondIII.jpg|140px]]&lt;br /&gt;
| [[File:Cypher_of_Esmond_III_of_Austenasia.svg|140px]]&lt;br /&gt;
| 9 June 1995 &lt;br /&gt;
| McLaughlin&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Declan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;19 December 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|19 December 2010|20 January 2013|duration=yes}})&lt;br /&gt;
| [[File:ICDA2.jpg|140px]]&lt;br /&gt;
| [[File:Declanmonogram.png|140px]]&lt;br /&gt;
| 20 May 1994&lt;br /&gt;
| Mac Donnchadha-Houghton&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Jonathan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 January 2013|29 September 2024|duration=yes}})&lt;br /&gt;
| [[File:ICJA20.jpg|140px]]&lt;br /&gt;
| [[File:ICJAcipher3.png|140px]]&lt;br /&gt;
| 13 October 1994&lt;br /&gt;
| Austen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Aggelos I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;3 June 2025&amp;lt;br/&amp;gt;&#039;&#039; ([[Overthrown]] after {{Age in years and days|29 September 2024|3 June 2025|duration=yes}})&lt;br /&gt;
| [[File:Basileus_Aggelos.jpg|140px]]&lt;br /&gt;
| [[File:Imperial_Cipher_Emperor_Aggelos_of_Austenasia.png|140px]]&lt;br /&gt;
| 1 September 1981 &lt;br /&gt;
| Vatazides&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Interregnum===&lt;br /&gt;
Austenasia currently has no reigning monarch, with Lord Protector [[Andrew Musgrave]] serving as head of state and [[Regent]] to the Crown during the ongoing interregnum. Despite the vacancy of the throne, the [[Aggelosites]] continued to maintain their own rival claim to the Austenasian Crown, although this claim was not recognised by the Government of Austenasia.&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Andrew Musgrave]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;3 June 2025 &amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|3 June 2025}})&lt;br /&gt;
| [[File:AndrewOfficialAustenasianPortrait.png|140px]]&lt;br /&gt;
| [[File:Coat of Arms of House Musgrave.png|140px]]&lt;br /&gt;
| 8 September 1999 &lt;br /&gt;
| [[Musgrave]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=110</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=110"/>
		<updated>2026-06-22T04:00:18Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* History */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
Discordenasia primarily operated through a Discord server, which served as the organisation&#039;s principal base of operations and communications. On 20 May 2026, the server was removed following a report submitted to Discord. The removal significantly disrupted the organisation&#039;s activities and communications.&lt;br /&gt;
&lt;br /&gt;
Despite the loss of its primary communications platform, Discordenasia continues to operate through social media and an independent rival website, maintaining its claims and organisational structure. Discordenasia maintains a presence on MicroWiki, where several of its members hold administrative positions and contribute to articles concerning Austenasia and related topics.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discordenasia]]&lt;br /&gt;
[[Category:Aggelositism]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=109</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=109"/>
		<updated>2026-06-22T03:55:08Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
Discordenasia primarily operated through a Discord server, which served as the organisation&#039;s principal base of operations and communications. On 20 May 2026, the server was removed following a report submitted to Discord. The removal significantly disrupted the organisation&#039;s activities and communications.&lt;br /&gt;
&lt;br /&gt;
Despite the loss of its primary communications platform, Discordenasia continues to operate through social media and an independent rival website, maintaining its claims and organisational structure.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discordenasia]]&lt;br /&gt;
[[Category:Aggelositism]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=108</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=108"/>
		<updated>2026-06-22T03:54:23Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* History */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
Discordenasia primarily operated through a Discord server, which served as the organisation&#039;s principal base of operations and communications. On 20 May 2026, the server was removed following a report submitted to Discord. The removal significantly disrupted the organisation&#039;s activities and communications.&lt;br /&gt;
&lt;br /&gt;
Despite the loss of its primary communications platform, Discordenasia continues to operate through social media and an independent rival website, maintaining its claims and organisational structure.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=107</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=107"/>
		<updated>2026-06-22T03:53:51Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* History */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
Discordenasia primarily operated through a Discord server, which served as the organisation&#039;s principal base of operations and communications. On 20 May 2026, the server was removed following a report submitted to Discord. The removal significantly disrupted the organisation&#039;s activities and communications.&lt;br /&gt;
&lt;br /&gt;
Despite the loss of its primary communications platform, Discordenasia continues to operate through social media and an independent website, maintaining its claims and organisational structure.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=106</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=106"/>
		<updated>2026-06-22T03:52:45Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
Discordenasia primarily operated through a Discord server, which served as the organisation&#039;s principal base of operations and communications. On 20 May 2026, the server was removed following a report submitted to Discord. The removal significantly disrupted the organisation&#039;s activities and communications.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=105</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=105"/>
		<updated>2026-06-22T03:51:37Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. The term &amp;quot;Discordenasia&amp;quot; originated as a nickname referencing the movement&#039;s organisation through the social platform Discord, and has since become a common informal name for the group and its associated institutions.&lt;br /&gt;
&lt;br /&gt;
Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=104</id>
		<title>Discordenasia</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Discordenasia&amp;diff=104"/>
		<updated>2026-06-22T03:51:07Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Discordenasia&amp;#039;&amp;#039;&amp;#039;, self-styled as the &amp;#039;&amp;#039;&amp;#039;Empire of Austenasia&amp;#039;&amp;#039;&amp;#039;, is a self-proclaimed government and political organisation established by supporters of Aggelos I following the commencement of the Austenasian Interregnum. Its supporters, known as Aggelosites, recognise Aggelos I, and subsequently Shiro, whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.  The organisation&amp;#039;s claims are not recog...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Discordenasia&#039;&#039;&#039;, self-styled as the &#039;&#039;&#039;Empire of Austenasia&#039;&#039;&#039;, is a self-proclaimed government and political organisation established by supporters of [[Aggelos I]] following the commencement of the [[Austenasian Interregnum]]. Its supporters, known as [[Aggelosites]], recognise Aggelos I, and subsequently [[Shiro]], whom was designated as his heir prior to the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The organisation&#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=103</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=103"/>
		<updated>2026-06-22T03:49:43Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown. The movement is commonly associated with the self-styled &amp;quot;Austenasian government&amp;quot; operating through Discord, colloquially referred to by its critics as [[Discordenasia]].&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the [[Austenasian Interregnum]].&lt;br /&gt;
&lt;br /&gt;
==Claimants to the throne of Austenasia==&lt;br /&gt;
*&#039;&#039;&#039;[[Aggelos I]]&#039;&#039;&#039; (3 June 2025 – 30 September 2025)&lt;br /&gt;
*&#039;&#039;&#039;[[Shiro|Alexander VI]]&#039;&#039;&#039; (30 September 2025 - present)&lt;br /&gt;
&lt;br /&gt;
[[Category:Aggelositism]]&lt;br /&gt;
[[Category:Aggelosite pretenders]]&lt;br /&gt;
[[Category:Discordenasia]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=102</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=102"/>
		<updated>2026-06-22T03:48:37Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown. The movement is commonly associated with the self-styled &amp;quot;Austenasian government&amp;quot; operating through Discord, colloquially referred to by its critics as [[Discordenasia]].&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the interregnum.&lt;br /&gt;
&lt;br /&gt;
==Claimants to the throne of Austenasia==&lt;br /&gt;
*&#039;&#039;&#039;[[Aggelos I]]&#039;&#039;&#039; (3 June 2025 – 30 September 2025)&lt;br /&gt;
*&#039;&#039;&#039;[[Shiro|Alexander VI]]&#039;&#039;&#039; (30 September 2025 - present)&lt;br /&gt;
&lt;br /&gt;
[[Category:Aggelositism]]&lt;br /&gt;
[[Category:Aggelosite pretenders]]&lt;br /&gt;
[[Category:Discordenasia]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=101</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=101"/>
		<updated>2026-06-22T03:48:23Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The movement is commonly associated with the self-styled &amp;quot;Austenasian government&amp;quot; operating through Discord, colloquially referred to by its critics as [[Discordenasia]].&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the interregnum.&lt;br /&gt;
&lt;br /&gt;
==Claimants to the throne of Austenasia==&lt;br /&gt;
*&#039;&#039;&#039;[[Aggelos I]]&#039;&#039;&#039; (3 June 2025 – 30 September 2025)&lt;br /&gt;
*&#039;&#039;&#039;[[Shiro|Alexander VI]]&#039;&#039;&#039; (30 September 2025 - present)&lt;br /&gt;
&lt;br /&gt;
[[Category:Aggelositism]]&lt;br /&gt;
[[Category:Aggelosite pretenders]]&lt;br /&gt;
[[Category:Discordenasia]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=100</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=100"/>
		<updated>2026-06-22T03:47:40Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the interregnum.&lt;br /&gt;
&lt;br /&gt;
==Claimants to the throne of Austenasia==&lt;br /&gt;
*&#039;&#039;&#039;[[Aggelos I]]&#039;&#039;&#039; (3 June 2025 – 30 September 2025)&lt;br /&gt;
*&#039;&#039;&#039;[[Shiro|Alexander VI]]&#039;&#039;&#039; (30 September 2025 - present)&lt;br /&gt;
&lt;br /&gt;
[[Category:Aggelositism]]&lt;br /&gt;
[[Category:Aggelosite pretenders]]&lt;br /&gt;
[[Category:Discordenasia]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=99</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=99"/>
		<updated>2026-06-22T03:45:03Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the interregnum.&lt;br /&gt;
&lt;br /&gt;
==Claimants to the throne of Austenasia==&lt;br /&gt;
*&#039;&#039;&#039;[[Aggelos I]]&#039;&#039;&#039; (3 June 2025 – 30 September 2025)&lt;br /&gt;
*&#039;&#039;&#039;[[Shiro|Alexander VI]]&#039;&#039;&#039; (30 September 2025 - present)&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=98</id>
		<title>Aggelositism</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelositism&amp;diff=98"/>
		<updated>2026-06-22T03:41:28Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Aggelositism&amp;#039;&amp;#039;&amp;#039; is a political movement that regards Aggelos I, and subsequently Shiro, whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown.  The movement&amp;#039;s claims are not recognised by the Government of Austenasia, which regards the throne as vacant and under the regency of the Lord Protector during the interregnum.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Aggelositism&#039;&#039;&#039; is a political movement that regards [[Aggelos I]], and subsequently [[Shiro]], whom was designated as his heir before the commencement of the interregnum, as the lawful continuation of the Austenasian Crown.&lt;br /&gt;
&lt;br /&gt;
The movement&#039;s claims are not recognised by the [[Government of Austenasia]], which regards the throne as vacant and under the regency of the [[Lord Protector]] during the interregnum.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Aggelosites&amp;diff=97</id>
		<title>Aggelosites</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Aggelosites&amp;diff=97"/>
		<updated>2026-06-22T03:38:56Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Redirected page to Aggelositism&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Aggelositism]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=96</id>
		<title>List of Austenasian monarchs</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=List_of_Austenasian_monarchs&amp;diff=96"/>
		<updated>2026-06-22T03:37:57Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* Interregnum */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Emperor of Austenasia&#039;&#039;&#039; is the sovereign and head of state of the Empire of Austenasia. Since the foundation of Austenasia in 2008, five individuals have reigned as monarch. Since the [[overthrow of Aggelos I]] on 3 June 2025, the monarchy has been vacant during the [[Austenasian Interregnum]], during which [[Andrew Musgrave]] has served as [[Lord Protector]] and [[Regent]].&lt;br /&gt;
&lt;br /&gt;
==List of monarchs==&lt;br /&gt;
===Monarchs===&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Terry I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 September 2008&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 September 2008|16 February 2010|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorTerryI.jpg|140px]]&lt;br /&gt;
| [[File:Austenarms.png|140px]]&lt;br /&gt;
| 16 May 1961 &lt;br /&gt;
| [[Austen]]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Esmond III]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;16 February 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 September 2011&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|16 February 2010|20 September 2011|duration=yes}})&lt;br /&gt;
| [[File:HIMEmperorEsmondIII.jpg|140px]]&lt;br /&gt;
| [[File:Cypher_of_Esmond_III_of_Austenasia.svg|140px]]&lt;br /&gt;
| 9 June 1995 &lt;br /&gt;
| McLaughlin&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Declan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;19 December 2010&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|19 December 2010|20 January 2013|duration=yes}})&lt;br /&gt;
| [[File:ICDA2.jpg|140px]]&lt;br /&gt;
| [[File:Declanmonogram.png|140px]]&lt;br /&gt;
| 20 May 1994&lt;br /&gt;
| Mac Donnchadha-Houghton&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Jonathan I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;20 January 2013&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|20 January 2013|29 September 2024|duration=yes}})&lt;br /&gt;
| [[File:ICJA20.jpg|140px]]&lt;br /&gt;
| [[File:ICJAcipher3.png|140px]]&lt;br /&gt;
| 13 October 1994&lt;br /&gt;
| Austen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Aggelos I]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;29 September 2024&amp;lt;br/&amp;gt;–&amp;lt;br/&amp;gt;3 June 2025&amp;lt;br/&amp;gt;&#039;&#039; ([[Overthrown]] after {{Age in years and days|29 September 2024|3 June 2025|duration=yes}})&lt;br /&gt;
| [[File:Basileus_Aggelos.jpg|140px]]&lt;br /&gt;
| [[File:Imperial_Cipher_Emperor_Aggelos_of_Austenasia.png|140px]]&lt;br /&gt;
| 1 September 1981 &lt;br /&gt;
| Vatazides&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Interregnum===&lt;br /&gt;
Austenasia currently has no reigning monarch, with Lord Protector [[Andrew Musgrave]] serving as head of state and [[Regent]] to the Crown during the ongoing interregnum. Despite the vacancy of the throne, the [[Aggelosites]] continued to maintain their own rival claim to the Austenasian Crown, although this claim was not recognised by the Government of Austenasia.&lt;br /&gt;
{| width=100% class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&lt;br /&gt;
! width=20% | Name&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Reign&amp;lt;/small&amp;gt;&lt;br /&gt;
!  width=20% | Portrait&lt;br /&gt;
!  width=20% | Arms&lt;br /&gt;
!  width=20% | Birth&lt;br /&gt;
!  width=20% | House&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;b&amp;gt;[[Andrew Musgrave]]&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;3 June 2025 &amp;lt;br/&amp;gt;&#039;&#039;({{Age in years and days|3 June 2025}})&lt;br /&gt;
| [[File:AndrewOfficialAustenasianPortrait.png|140px]]&lt;br /&gt;
| [[File:Coat of Arms of House Musgrave.png|140px]]&lt;br /&gt;
| 8 September 1999 &lt;br /&gt;
| [[Musgrave]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=95</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=95"/>
		<updated>2026-06-22T02:18:33Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: /* Notice */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;br /&gt;
&lt;br /&gt;
==Notice==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Austenasia Wiki&#039;&#039;&#039; is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published by third parties may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking authoritative information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=94</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=94"/>
		<updated>2026-06-22T02:18:20Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;br /&gt;
&lt;br /&gt;
==Notice==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Austenasia Wiki&#039;&#039; is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published by third parties may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking authoritative information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=93</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=93"/>
		<updated>2026-06-22T02:17:34Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;br /&gt;
&lt;br /&gt;
==Notice==&lt;br /&gt;
&lt;br /&gt;
The Austenasia Wiki is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published elsewhere may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking official information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=92</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=92"/>
		<updated>2026-06-22T02:17:14Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notice&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Austenasia Wiki is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published elsewhere may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking official information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;br /&gt;
&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=91</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=91"/>
		<updated>2026-06-22T02:17:09Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notice&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Austenasia Wiki is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published elsewhere may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking official information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;br /&gt;
&lt;br /&gt;
==Official links==&lt;br /&gt;
*[https://austenasia.com Official Website]&lt;br /&gt;
*[https://austenasia.news Austenasian Times]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Main_Page&amp;diff=90</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Main_Page&amp;diff=90"/>
		<updated>2026-06-22T02:16:18Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Notice&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Austenasia Wiki is the official encyclopaedia of the Empire of Austenasia. Information concerning Austenasia published elsewhere may not reflect the position of the Austenasian Government and may contain claims disputed by Austenasia&#039;s official institutions. Readers seeking official information regarding Austenasian history, government, officeholders, constitutional matters, and current events should refer to this wiki and other official Austenasian publications.&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:String&amp;diff=89</id>
		<title>Module:String</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:String&amp;diff=89"/>
		<updated>2026-06-22T02:08:54Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;--[[  This module is intended to provide access to basic string functions.  Most of the functions provided here can be invoked with named parameters, unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. Depending on the intended use, it may be advantageous to either preserve or remove such whitespace.  Global options     ignore_errors: If set to &amp;#039;true&amp;#039; or 1, any error c...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
&lt;br /&gt;
This module is intended to provide access to basic string functions.&lt;br /&gt;
&lt;br /&gt;
Most of the functions provided here can be invoked with named parameters,&lt;br /&gt;
unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will&lt;br /&gt;
automatically remove any leading or trailing whitespace from the parameter.&lt;br /&gt;
Depending on the intended use, it may be advantageous to either preserve or&lt;br /&gt;
remove such whitespace.&lt;br /&gt;
&lt;br /&gt;
Global options&lt;br /&gt;
    ignore_errors: If set to &#039;true&#039; or 1, any error condition will result in&lt;br /&gt;
        an empty string being returned rather than an error message.&lt;br /&gt;
&lt;br /&gt;
    error_category: If an error occurs, specifies the name of a category to&lt;br /&gt;
        include with the error message.  The default category is&lt;br /&gt;
        [Category:Errors reported by Module String].&lt;br /&gt;
&lt;br /&gt;
    no_category: If set to &#039;true&#039; or 1, no category will be added if an error&lt;br /&gt;
        is generated.&lt;br /&gt;
&lt;br /&gt;
Unit tests for this module are available at Module:String/tests.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local str = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
len&lt;br /&gt;
&lt;br /&gt;
This function returns the length of the target string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|len|target_string|}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|len|s=target_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string whose length to report&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.&lt;br /&gt;
]]&lt;br /&gt;
function str.len( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	return mw.ustring.len( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
sub&lt;br /&gt;
&lt;br /&gt;
This function returns a substring of the target string at specified indices.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|sub|target_string|start_index|end_index}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to return a subset of&lt;br /&gt;
    i: The first index of the substring to return, defaults to 1.&lt;br /&gt;
    j: The last index of the string to return, defaults to the last character.&lt;br /&gt;
&lt;br /&gt;
The first character of the string is assigned an index of 1.  If either i or j&lt;br /&gt;
is a negative value, it is interpreted the same as selecting a character by&lt;br /&gt;
counting from the end of the string.  Hence, a value of -1 is the same as&lt;br /&gt;
selecting the last character of the string.&lt;br /&gt;
&lt;br /&gt;
If the requested indices are out of range for the given string, an error is&lt;br /&gt;
reported.&lt;br /&gt;
]]&lt;br /&gt;
function str.sub( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, { &#039;s&#039;, &#039;i&#039;, &#039;j&#039; } )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local i = tonumber( new_args[&#039;i&#039;] ) or 1&lt;br /&gt;
	local j = tonumber( new_args[&#039;j&#039;] ) or -1&lt;br /&gt;
&lt;br /&gt;
	local len = mw.ustring.len( s )&lt;br /&gt;
&lt;br /&gt;
	-- Convert negatives for range checking&lt;br /&gt;
	if i &amp;lt; 0 then&lt;br /&gt;
		i = len + i + 1&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; 0 then&lt;br /&gt;
		j = len + j + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if i &amp;gt; len or j &amp;gt; len or i &amp;lt; 1 or j &amp;lt; 1 then&lt;br /&gt;
		return str._error( &#039;String subset index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; i then&lt;br /&gt;
		return str._error( &#039;String subset indices out of order&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( s, i, j )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
This function implements that features of {{str sub old}} and is kept in order&lt;br /&gt;
to maintain these older templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.sublength( frame )&lt;br /&gt;
	local i = tonumber( frame.args.i ) or 0&lt;br /&gt;
	local len = tonumber( frame.args.len )&lt;br /&gt;
	return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
_match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern. It is exported for use in other modules&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
strmatch = require(&amp;quot;Module:String&amp;quot;)._match&lt;br /&gt;
sresult = strmatch( s, pattern, start, match, plain, nomatch )&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This sub-routine is exported for use in other modules&lt;br /&gt;
function str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
	if s == &#039;&#039; then&lt;br /&gt;
		return str._error( &#039;Target string is empty&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		return str._error( &#039;Pattern string is empty&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	start = tonumber(start) or 1&lt;br /&gt;
	if math.abs(start) &amp;lt; 1 or math.abs(start) &amp;gt; mw.ustring.len( s ) then&lt;br /&gt;
		return str._error( &#039;Requested start is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if match_index == 0 then&lt;br /&gt;
		return str._error( &#039;Match index is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if plain_flag then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
	if match_index == 1 then&lt;br /&gt;
		-- Find first match is simple case&lt;br /&gt;
		result = mw.ustring.match( s, pattern, start )&lt;br /&gt;
	else&lt;br /&gt;
		if start &amp;gt; 1 then&lt;br /&gt;
			s = mw.ustring.sub( s, start )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local iterator = mw.ustring.gmatch(s, pattern)&lt;br /&gt;
		if match_index &amp;gt; 0 then&lt;br /&gt;
			-- Forward search&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				match_index = match_index - 1&lt;br /&gt;
				if match_index == 0 then&lt;br /&gt;
					result = w&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Reverse search&lt;br /&gt;
			local result_table = {}&lt;br /&gt;
			local count = 1&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				result_table[count] = w&lt;br /&gt;
				count = count + 1&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			result = result_table[ count + match_index ]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if result == nil then&lt;br /&gt;
		if nomatch == nil then&lt;br /&gt;
			return str._error( &#039;Match not found&#039; )&lt;br /&gt;
		else&lt;br /&gt;
			return nomatch&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return result&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index&lt;br /&gt;
    |match=match_number|plain=plain_flag|nomatch=nomatch_output}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from each string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
If the match_number or start_index are out of range for the string being queried, then&lt;br /&gt;
this function generates an error.  An error is also generated if no match is found.&lt;br /&gt;
If one adds the parameter ignore_errors=true, then the error will be suppressed and&lt;br /&gt;
an empty string will be returned on any failure.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This is the entry point for #invoke:String|match&lt;br /&gt;
function str.match( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;, &#039;pattern&#039;, &#039;start&#039;, &#039;match&#039;, &#039;plain&#039;, &#039;nomatch&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local start = tonumber( new_args[&#039;start&#039;] ) or 1&lt;br /&gt;
	local plain_flag = str._getBoolean( new_args[&#039;plain&#039;] or false )&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local match_index = math.floor( tonumber(new_args[&#039;match&#039;]) or 1 )&lt;br /&gt;
	local nomatch = new_args[&#039;nomatch&#039;]&lt;br /&gt;
&lt;br /&gt;
	return str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
pos&lt;br /&gt;
&lt;br /&gt;
This function returns a single character from the target string at position pos.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|pos|target_string|index_value}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|pos|target=target_string|pos=index_value}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    target: The string to search&lt;br /&gt;
    pos: The index for the character to return&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
The first character has an index value of 1.&lt;br /&gt;
&lt;br /&gt;
If one requests a negative value, this function will select a character by counting backwards&lt;br /&gt;
from the end of the string.  In other words pos = -1 is the same as asking for the last character.&lt;br /&gt;
&lt;br /&gt;
A requested value of zero, or a value greater than the length of the string returns an error.&lt;br /&gt;
]]&lt;br /&gt;
function str.pos( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;target&#039;, &#039;pos&#039;} )&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local pos = tonumber( new_args[&#039;pos&#039;] ) or 0&lt;br /&gt;
&lt;br /&gt;
	if pos == 0 or math.abs(pos) &amp;gt; mw.ustring.len( target_str ) then&lt;br /&gt;
		return str._error( &#039;String index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( target_str, pos, pos )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
str_find&lt;br /&gt;
&lt;br /&gt;
This function duplicates the behavior of {{str_find}}, including all of its quirks.&lt;br /&gt;
This is provided in order to support existing templates, but is NOT RECOMMENDED for&lt;br /&gt;
new code and templates.  New code is recommended to use the &amp;quot;find&amp;quot; function instead.&lt;br /&gt;
&lt;br /&gt;
Returns the first index in &amp;quot;source&amp;quot; that is a match to &amp;quot;target&amp;quot;.  Indexing is 1-based,&lt;br /&gt;
and the function returns -1 if the &amp;quot;target&amp;quot; string is not present in &amp;quot;source&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Important Note: If the &amp;quot;target&amp;quot; string is empty / missing, this function returns a&lt;br /&gt;
value of &amp;quot;1&amp;quot;, which is generally unexpected behavior, and must be accounted for&lt;br /&gt;
separatetly.&lt;br /&gt;
]]&lt;br /&gt;
function str.str_find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;} )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
	if target_str == &#039;&#039; then&lt;br /&gt;
		return 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, target_str, 1, true )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
find&lt;br /&gt;
&lt;br /&gt;
This function allows one to search for a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    target: The string or pattern to find within source&lt;br /&gt;
    start: The index within the source string to start the search, defaults to 1&lt;br /&gt;
    plain: Boolean flag indicating that target should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the parameter.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
This function returns the first index &amp;gt;= &amp;quot;start&amp;quot; where &amp;quot;target&amp;quot; can be found&lt;br /&gt;
within &amp;quot;source&amp;quot;.  Indices are 1-based.  If &amp;quot;target&amp;quot; is not found, then this&lt;br /&gt;
function returns 0.  If either &amp;quot;source&amp;quot; or &amp;quot;target&amp;quot; are missing / empty, this&lt;br /&gt;
function also returns 0.&lt;br /&gt;
&lt;br /&gt;
This function should be safe for UTF-8 strings.&lt;br /&gt;
]]&lt;br /&gt;
function str.find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;, &#039;start&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local start_pos = tonumber(new_args[&#039;start&#039;]) or 1&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, pattern, start_pos, plain )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
replace&lt;br /&gt;
&lt;br /&gt;
This function allows one to replace a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|&lt;br /&gt;
   count=replacement_count|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    pattern: The string or pattern to find within source&lt;br /&gt;
    replace: The replacement text&lt;br /&gt;
    count: The number of occurences to replace, defaults to all.&lt;br /&gt;
    plain: Boolean flag indicating that pattern should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
]]&lt;br /&gt;
function str.replace( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;replace&#039;, &#039;count&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local replace = new_args[&#039;replace&#039;] or &#039;&#039;&lt;br /&gt;
	local count = tonumber( new_args[&#039;count&#039;] )&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return source_str&lt;br /&gt;
	end&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
		replace = string.gsub( replace, &amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot; ) --Only need to escape replacement sequences.&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
&lt;br /&gt;
	if count ~= nil then&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace, count )&lt;br /&gt;
	else&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
    simple function to pipe string.rep to templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.rep( frame )&lt;br /&gt;
	local repetitions = tonumber( frame.args[2] )&lt;br /&gt;
	if not repetitions then&lt;br /&gt;
		return str._error( &#039;function rep expects a number as second parameter, received &amp;quot;&#039; .. ( frame.args[2] or &#039;&#039; ) .. &#039;&amp;quot;&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return string.rep( frame.args[1] or &#039;&#039;, repetitions )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
escapePattern&lt;br /&gt;
&lt;br /&gt;
This function escapes special characters from a Lua string pattern. See [1]&lt;br /&gt;
for details on how patterns work.&lt;br /&gt;
&lt;br /&gt;
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|escapePattern|pattern_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    pattern_string: The pattern string to escape.&lt;br /&gt;
]]&lt;br /&gt;
function str.escapePattern( frame )&lt;br /&gt;
	local pattern_str = frame.args[1]&lt;br /&gt;
	if not pattern_str then&lt;br /&gt;
		return str._error( &#039;No pattern string specified&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	local result = str._escapePattern( pattern_str )&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
count&lt;br /&gt;
This function counts the number of occurrences of one string in another.&lt;br /&gt;
]]&lt;br /&gt;
function str.count(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;plain&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	local plain = str._getBoolean(args.plain or true)&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern(pattern)&lt;br /&gt;
	end&lt;br /&gt;
	local _, count = mw.ustring.gsub(source, pattern, &#039;&#039;)&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
endswith&lt;br /&gt;
This function determines whether a string ends with another string.&lt;br /&gt;
]]&lt;br /&gt;
function str.endswith(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		-- All strings end with the empty string.&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
join&lt;br /&gt;
&lt;br /&gt;
Join all non empty arguments together; the first argument is the separator.&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|join|sep|one|two|three}}&lt;br /&gt;
]]&lt;br /&gt;
function str.join(frame)&lt;br /&gt;
	local args = {}&lt;br /&gt;
	local sep&lt;br /&gt;
	for _, v in ipairs( frame.args ) do&lt;br /&gt;
		if sep then&lt;br /&gt;
			if v ~= &#039;&#039; then&lt;br /&gt;
				table.insert(args, v)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			sep = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat( args, sep or &#039;&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- findpagetext returns the position of a piece of text in a page&lt;br /&gt;
-- First positional parameter or |text is the search text&lt;br /&gt;
-- Optional parameter |title is the page title, defaults to current page&lt;br /&gt;
-- Optional parameter |plain is either true for plain search (default) or false for Lua pattern search&lt;br /&gt;
-- Optional parameter |nomatch is the return value when no match is found; default is nil&lt;br /&gt;
function str._findpagetext(args)&lt;br /&gt;
	-- process parameters&lt;br /&gt;
	local nomatch = args.nomatch or &amp;quot;&amp;quot;&lt;br /&gt;
	if nomatch == &amp;quot;&amp;quot; then nomatch = nil end&lt;br /&gt;
	--&lt;br /&gt;
	local text = mw.text.trim(args[1] or args.text or &amp;quot;&amp;quot;)&lt;br /&gt;
	if text == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
	--&lt;br /&gt;
	local title = args.title or &amp;quot;&amp;quot;&lt;br /&gt;
	local titleobj&lt;br /&gt;
	if title == &amp;quot;&amp;quot; then&lt;br /&gt;
		titleobj = mw.title.getCurrentTitle()&lt;br /&gt;
	else&lt;br /&gt;
		titleobj = mw.title.new(title)&lt;br /&gt;
	end&lt;br /&gt;
	--&lt;br /&gt;
	local plain = args.plain or &amp;quot;&amp;quot;&lt;br /&gt;
	if plain:sub(1, 1) == &amp;quot;f&amp;quot; then plain = false else plain = true end&lt;br /&gt;
	-- get the page content and look for &#039;text&#039; - return position or nomatch&lt;br /&gt;
	local content = titleobj and titleobj:getContent()&lt;br /&gt;
	return content and mw.ustring.find(content, text, 1, plain) or nomatch&lt;br /&gt;
end&lt;br /&gt;
function str.findpagetext(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	for k, v in pairs(pargs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	if not (args[1] or args.text) then return nil end&lt;br /&gt;
	-- just the first value&lt;br /&gt;
	return (str._findpagetext(args))&lt;br /&gt;
end&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that populates the argument list given that user may need to use a mix of&lt;br /&gt;
named and unnamed parameters.  This is relevant because named parameters are not&lt;br /&gt;
identical to unnamed parameters due to string trimming, and when dealing with strings&lt;br /&gt;
we sometimes want to either preserve or remove that whitespace depending on the application.&lt;br /&gt;
]]&lt;br /&gt;
function str._getParameters( frame_args, arg_list )&lt;br /&gt;
	local new_args = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	local value&lt;br /&gt;
&lt;br /&gt;
	for _, arg in ipairs( arg_list ) do&lt;br /&gt;
		value = frame_args[arg]&lt;br /&gt;
		if value == nil then&lt;br /&gt;
			value = frame_args[index]&lt;br /&gt;
			index = index + 1&lt;br /&gt;
		end&lt;br /&gt;
		new_args[arg] = value&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return new_args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function to handle error messages.&lt;br /&gt;
]]&lt;br /&gt;
function str._error( error_str )&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local error_category = frame.args.error_category or &#039;Errors reported by Module String&#039;&lt;br /&gt;
	local ignore_errors = frame.args.ignore_errors or false&lt;br /&gt;
	local no_category = frame.args.no_category or false&lt;br /&gt;
&lt;br /&gt;
	if str._getBoolean(ignore_errors) then&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local error_str = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;String Module Error: &#039; .. error_str .. &#039;&amp;lt;/strong&amp;gt;&#039;&lt;br /&gt;
	if error_category ~= &#039;&#039; and not str._getBoolean( no_category ) then&lt;br /&gt;
		error_str = &#039;[[Category:&#039; .. error_category .. &#039;]]&#039; .. error_str&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return error_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper Function to interpret boolean strings&lt;br /&gt;
]]&lt;br /&gt;
function str._getBoolean( boolean_str )&lt;br /&gt;
	local boolean_value&lt;br /&gt;
&lt;br /&gt;
	if type( boolean_str ) == &#039;string&#039; then&lt;br /&gt;
		boolean_str = boolean_str:lower()&lt;br /&gt;
		if boolean_str == &#039;false&#039; or boolean_str == &#039;no&#039; or boolean_str == &#039;0&#039;&lt;br /&gt;
				or boolean_str == &#039;&#039; then&lt;br /&gt;
			boolean_value = false&lt;br /&gt;
		else&lt;br /&gt;
			boolean_value = true&lt;br /&gt;
		end&lt;br /&gt;
	elseif type( boolean_str ) == &#039;boolean&#039; then&lt;br /&gt;
		boolean_value = boolean_str&lt;br /&gt;
	else&lt;br /&gt;
		error( &#039;No boolean value found&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return boolean_value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that escapes all pattern characters so that they will be treated&lt;br /&gt;
as plain text.&lt;br /&gt;
]]&lt;br /&gt;
function str._escapePattern( pattern_str )&lt;br /&gt;
	return ( string.gsub( pattern_str, &amp;quot;[%(%)%.%%%+%-%*%?%[%^%$%]]&amp;quot;, &amp;quot;%%%0&amp;quot; ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return str&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:PAGENAMEBASE&amp;diff=88</id>
		<title>Template:PAGENAMEBASE</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:PAGENAMEBASE&amp;diff=88"/>
		<updated>2026-06-22T02:08:34Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;{{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:String|replace|{{{1|{{safesubst:&amp;lt;noinclude/&amp;gt;PAGENAME}}}}}|%s+%b()$||1|false}}&amp;lt;noinclude&amp;gt; {{documentation}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:String|replace|{{{1|{{safesubst:&amp;lt;noinclude/&amp;gt;PAGENAME}}}}}|%s+%b()$||1|false}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Fallbacklist&amp;diff=87</id>
		<title>Template:Fallbacklist</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Fallbacklist&amp;diff=87"/>
		<updated>2026-06-22T02:07:57Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Austenasia moved page Template:Fallbacklist to Module:Fallbacklist&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Module:Fallbacklist]]&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Fallbacklist&amp;diff=86</id>
		<title>Module:Fallbacklist</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Fallbacklist&amp;diff=86"/>
		<updated>2026-06-22T02:07:57Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Austenasia moved page Template:Fallbacklist to Module:Fallbacklist&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--- Language fallback rules for other Lua modules.&lt;br /&gt;
-- @see       [[c:Module:Fallbacklist]]&lt;br /&gt;
-- @release   stable&lt;br /&gt;
-- @submodule&lt;br /&gt;
return {&lt;br /&gt;
&lt;br /&gt;
    -- crh (Crimean Tatar) cluster: crh-cyrl , crh-latn -&amp;gt; crh (Crimean Tatar)&lt;br /&gt;
    [&#039;crh&#039;]          = {&#039;crh-latn&#039;},&lt;br /&gt;
    [&#039;crh-cyrl&#039;]     = {&#039;crh&#039;, &#039;ru&#039;}, &lt;br /&gt;
    [&#039;crh-latn&#039;]     = {&#039;crh&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- de (German) cluster:&lt;br /&gt;
    [&#039;als&#039;]          = {&#039;gsw&#039;, &#039;de&#039;},                       -- Alemannisch&lt;br /&gt;
    [&#039;bar&#039;]          = {&#039;de&#039;},                              -- Bavarian&lt;br /&gt;
    [&#039;de-at&#039;]        = {&#039;de&#039;},                              -- Austrian German&lt;br /&gt;
    [&#039;de-ch&#039;]        = {&#039;de&#039;},                              -- Swiss High German&lt;br /&gt;
    [&#039;de-formal&#039;]    = {&#039;de&#039;},                              -- German (formal address)&lt;br /&gt;
    [&#039;dsb&#039;]          = {&#039;de&#039;},                              -- Lower Sorbian&lt;br /&gt;
    [&#039;frr&#039;]          = {&#039;de&#039;},                              -- Northern Frisian&lt;br /&gt;
    [&#039;hsb&#039;]          = {&#039;de&#039;},                              -- Upper Sorbian&lt;br /&gt;
    [&#039;ksh&#039;]          = {&#039;de&#039;},                              -- Colognian&lt;br /&gt;
    [&#039;lb&#039;]           = {&#039;de&#039;},                              -- Luxembourgish&lt;br /&gt;
    [&#039;nds&#039;]          = {&#039;nds-nl&#039;, &#039;de&#039;},                    -- Low German&lt;br /&gt;
    [&#039;nds-nl&#039;]       = {&#039;nds&#039;, &#039;nl&#039;},                       -- Low Saxon (Netherlands)&lt;br /&gt;
    [&#039;pdc&#039;]          = {&#039;de&#039;},                              -- Deitsch&lt;br /&gt;
    [&#039;pdt&#039;]          = {&#039;nds&#039;, &#039;de&#039;},                       -- Plautdietsch&lt;br /&gt;
    [&#039;pfl&#039;]          = {&#039;de&#039;},                              -- Pälzisch&lt;br /&gt;
    [&#039;sli&#039;]          = {&#039;de&#039;},                              -- Lower Silesian&lt;br /&gt;
    [&#039;stq&#039;]          = {&#039;de&#039;},                              -- Seeltersk&lt;br /&gt;
    [&#039;vmf&#039;]          = {&#039;de&#039;},                              -- Upper Franconian&lt;br /&gt;
&lt;br /&gt;
    -- es (Spanish) cluster&lt;br /&gt;
    [&#039;an&#039;]           = {&#039;es&#039;},                              -- Aragonese&lt;br /&gt;
    [&#039;arn&#039;]          = {&#039;es&#039;},                              -- Mapuche&lt;br /&gt;
    [&#039;ay&#039;]           = {&#039;es&#039;},                              -- Aymara&lt;br /&gt;
    [&#039;cbk-zam&#039;]      = {&#039;es&#039;},                              -- Chavacano de Zamboanga&lt;br /&gt;
    [&#039;gn&#039;]           = {&#039;es&#039;},                              -- Guarani&lt;br /&gt;
    [&#039;lad&#039;]          = {&#039;es&#039;},                              -- Ladino&lt;br /&gt;
    [&#039;nah&#039;]          = {&#039;es&#039;},                              -- Nahuatl&lt;br /&gt;
    [&#039;qu&#039;]           = {&#039;es&#039;},                              -- Quechua&lt;br /&gt;
    [&#039;qug&#039;]          = {&#039;qu&#039;, &#039;es&#039;},                        -- Runa shimi&lt;br /&gt;
&lt;br /&gt;
    -- et (Estonian) cluster&lt;br /&gt;
    [&#039;liv&#039;]          = {&#039;et&#039;},                              -- Līvõ kēļ&lt;br /&gt;
    [&#039;vep&#039;]          = {&#039;et&#039;},                              -- Veps&lt;br /&gt;
    [&#039;vro&#039;]          = {&#039;et&#039;},                              -- Võro&lt;br /&gt;
    [&#039;fiu-vro&#039;]      = {&#039;vro&#039;, &#039;et&#039;},                       -- Võro&lt;br /&gt;
&lt;br /&gt;
    -- fa (Persian) cluster&lt;br /&gt;
    [&#039;bcc&#039;]          = {&#039;fa&#039;},                              -- Southern Balochi&lt;br /&gt;
    [&#039;bqi&#039;]          = {&#039;fa&#039;},                              -- Bakhtiari&lt;br /&gt;
    [&#039;glk&#039;]          = {&#039;fa&#039;},                              -- Gilaki&lt;br /&gt;
    [&#039;mzn&#039;]          = {&#039;fa&#039;},                              -- Mazandarani&lt;br /&gt;
&lt;br /&gt;
    -- fi (Finnish) cluster:&lt;br /&gt;
    [&#039;fit&#039;]          = {&#039;fi&#039;},                              -- meänkieli&lt;br /&gt;
    [&#039;vot&#039;]          = {&#039;fi&#039;},                              -- Votic&lt;br /&gt;
&lt;br /&gt;
    -- fr (French) cluster:&lt;br /&gt;
    [&#039;bm&#039;]           = {&#039;fr&#039;},                              -- Bambara&lt;br /&gt;
    [&#039;br&#039;]           = {&#039;fr&#039;},                              -- Breton&lt;br /&gt;
    [&#039;co&#039;]           = {&#039;fr&#039;},                              -- Corsican&lt;br /&gt;
    [&#039;ff&#039;]           = {&#039;fr&#039;},                              -- Fulah&lt;br /&gt;
    [&#039;frc&#039;]          = {&#039;fr&#039;},                              -- Cajun French&lt;br /&gt;
    [&#039;frp&#039;]          = {&#039;fr&#039;},                              -- Franco-Provençal&lt;br /&gt;
    [&#039;ht&#039;]           = {&#039;fr&#039;},                              -- Haitian&lt;br /&gt;
    [&#039;ln&#039;]           = {&#039;fr&#039;},                              -- Lingala&lt;br /&gt;
    [&#039;mg&#039;]           = {&#039;fr&#039;},                              -- Malagasy&lt;br /&gt;
    [&#039;pcd&#039;]          = {&#039;fr&#039;},                              -- Picard&lt;br /&gt;
    [&#039;sg&#039;]           = {&#039;fr&#039;},                              -- Sango&lt;br /&gt;
    [&#039;ty&#039;]           = {&#039;fr&#039;},                              -- Tahitian&lt;br /&gt;
    [&#039;wa&#039;]           = {&#039;fr&#039;},                              -- Walloon&lt;br /&gt;
    [&#039;wo&#039;]           = {&#039;fr&#039;},                              -- Wolof&lt;br /&gt;
&lt;br /&gt;
    -- hi (Hindi) cluster&lt;br /&gt;
    [&#039;anp&#039;]          = {&#039;hi&#039;},                              -- Angika&lt;br /&gt;
    [&#039;mai&#039;]          = {&#039;hi&#039;},                              -- Maithili&lt;br /&gt;
    [&#039;sa&#039;]           = {&#039;hi&#039;},                              -- Sanskrit&lt;br /&gt;
&lt;br /&gt;
    -- hif (Fiji Hindi) cluster: hif-deva , hif-latn -&amp;gt; hif (Fiji Hindi)&lt;br /&gt;
    [&#039;hif&#039;]          = {&#039;hif-latn&#039;},&lt;br /&gt;
    [&#039;hif-deva&#039;]     = {&#039;hif&#039;}, &lt;br /&gt;
    [&#039;hif-latn&#039;]     = {&#039;hif&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- id (Indonesian) cluster&lt;br /&gt;
    [&#039;min&#039;]          = {&#039;id&#039;},                              -- Minangkabau&lt;br /&gt;
    [&#039;ace&#039;]          = {&#039;id&#039;},                              -- Achinese&lt;br /&gt;
    [&#039;bug&#039;]          = {&#039;id&#039;},                              -- Buginese&lt;br /&gt;
    [&#039;bjn&#039;]          = {&#039;id&#039;},                              -- Banjar&lt;br /&gt;
    [&#039;jv&#039;]           = {&#039;id&#039;},                              -- Javanese&lt;br /&gt;
    [&#039;su&#039;]           = {&#039;id&#039;},                              -- Sundanese&lt;br /&gt;
    [&#039;map-bms&#039;]      = {&#039;jv&#039;, &#039;id&#039;},                        -- Basa Banyumasan&lt;br /&gt;
&lt;br /&gt;
    -- ike (Eastern Canadian Inuktitut) cluster: ike-cans , ike-latn -&amp;gt; ike (Eastern Canadian Inuktitut)&lt;br /&gt;
    [&#039;ike-cans&#039;]     = {&#039;ik&#039;}, &lt;br /&gt;
    [&#039;ike-latn&#039;]     = {&#039;ik&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- it (Italian) cluster&lt;br /&gt;
    [&#039;egl&#039;]          = {&#039;it&#039;},                              -- Emiliàn&lt;br /&gt;
    [&#039;eml&#039;]          = {&#039;it&#039;},                              -- Emiliano-Romagnolo&lt;br /&gt;
    [&#039;fur&#039;]          = {&#039;it&#039;},                              -- Friulian&lt;br /&gt;
    [&#039;lij&#039;]          = {&#039;it&#039;},                              -- Ligure&lt;br /&gt;
    [&#039;lmo&#039;]          = {&#039;it&#039;},                              -- lumbaart&lt;br /&gt;
    [&#039;nap&#039;]          = {&#039;it&#039;},                              -- Neapolitan&lt;br /&gt;
    [&#039;pms&#039;]          = {&#039;it&#039;},                              -- Piedmontese&lt;br /&gt;
    [&#039;rgn&#039;]          = {&#039;it&#039;},                              -- Romagnol&lt;br /&gt;
    [&#039;scn&#039;]          = {&#039;it&#039;},                              -- Sicilian&lt;br /&gt;
    [&#039;vec&#039;]          = {&#039;it&#039;},                              -- vèneto&lt;br /&gt;
&lt;br /&gt;
    -- kk (Kazakh) cluster:&lt;br /&gt;
    -- kk-arab , kk-cyrl , kk-latn , kk-cn , kk-kz , kk-tr -&amp;gt; kk (Kazakh)&lt;br /&gt;
    [&#039;kk&#039;]           = {&#039;kk-cyrl&#039;},                         -- Kazakh&lt;br /&gt;
    [&#039;kk-arab&#039;]      = {&#039;kk-cyrl&#039;, &#039;kk&#039;},                   -- Kazakh (Arabic script)&lt;br /&gt;
    [&#039;kk-cn&#039;]        = {&#039;kk-arab&#039;, &#039;kk-cyrl&#039;, &#039;kk&#039;},        -- Kazakh (China)&lt;br /&gt;
    [&#039;kk-cyrl&#039;]      = {&#039;kk&#039;},                              -- Kazakh (Cyrillic script)&lt;br /&gt;
    [&#039;kk-kz&#039;]        = {&#039;kk&#039;, &#039;kk-cyrl&#039;},                   -- Kazakh (Kazakhstan)&lt;br /&gt;
    [&#039;kk-latn&#039;]      = {&#039;kk-cyrl&#039;, &#039;kk&#039;},                   -- Kazakh (Latin script)&lt;br /&gt;
    [&#039;kk-tr&#039;]        = {&#039;kk-latn&#039;, &#039;kk-cyrl&#039;, &#039;kk&#039;},        -- Kazakh (Turkey)&lt;br /&gt;
    [&#039;kaa&#039;]          = {&#039;kk-latn&#039;, &#039;kk-cyrl&#039;},              -- Kara-Kalpak&lt;br /&gt;
&lt;br /&gt;
    -- ku (Kurdish) cluster: ku-latn , ku-arab -&amp;gt; ku (Kurdish)&lt;br /&gt;
    [&#039;ku&#039;]           = {&#039;ku-latn&#039;},&lt;br /&gt;
    [&#039;ku-arab&#039;]      = {&#039;ckb&#039;, &#039;ckb-arab&#039;, &#039;ku&#039;},           -- كوردي (عەرەبی)&lt;br /&gt;
    [&#039;ku-latn&#039;]      = {&#039;ku&#039;},&lt;br /&gt;
    [&#039;ckb&#039;]          = {&#039;ckb-arab&#039;, &#039;ku&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- nl (Dutch) cluster&lt;br /&gt;
    [&#039;af&#039;]           = {&#039;nl&#039;},                              -- Afrikaans&lt;br /&gt;
    [&#039;fy&#039;]           = {&#039;nl&#039;},                              -- Western Frisian&lt;br /&gt;
    [&#039;li&#039;]           = {&#039;nl&#039;},                              -- Liechtenstein&lt;br /&gt;
    [&#039;nl-informal&#039;]  = {&#039;nl&#039;},                              -- Nederlands (informeel)&lt;br /&gt;
    [&#039;vls&#039;]          = {&#039;nl&#039;},                              -- Vlaams&lt;br /&gt;
    [&#039;zea&#039;]          = {&#039;nl&#039;},                              -- Zeeuws&lt;br /&gt;
&lt;br /&gt;
    --pl (Polish) cluster&lt;br /&gt;
    [&#039;csb&#039;]          = {&#039;pl&#039;},                              -- Kashubian&lt;br /&gt;
    [&#039;szl&#039;]          = {&#039;pl&#039;},                              -- Silesian&lt;br /&gt;
&lt;br /&gt;
    -- pt (Portuguese) cluster&lt;br /&gt;
    [&#039;gl&#039;]           = {&#039;pt&#039;},                              -- Galician&lt;br /&gt;
    [&#039;mwl&#039;]          = {&#039;pt&#039;},                              -- Mirandese&lt;br /&gt;
    [&#039;pt-br&#039;]        = {&#039;pt&#039;},                              -- Brazilian Portuguese&lt;br /&gt;
&lt;br /&gt;
    -- ro (Romanian) cluster&lt;br /&gt;
    [&#039;mo&#039;]           = {&#039;ro&#039;},                              -- Moldavian&lt;br /&gt;
    [&#039;rmy&#039;]          = {&#039;ro&#039;},                              -- Romani&lt;br /&gt;
&lt;br /&gt;
    -- ru (Russian) cluster&lt;br /&gt;
    [&#039;ab&#039;]           = {&#039;ru&#039;},                              -- Abkhazian&lt;br /&gt;
    [&#039;av&#039;]           = {&#039;ru&#039;},                              -- Avaric&lt;br /&gt;
    [&#039;ba&#039;]           = {&#039;ru&#039;},                              -- Bashkir&lt;br /&gt;
    [&#039;be-tarask&#039;]    = {&#039;ru&#039;},                              -- Belorussian&lt;br /&gt;
    [&#039;ce&#039;]           = {&#039;ru&#039;},                              -- Chechen&lt;br /&gt;
    [&#039;crh-cyrl&#039;]     = {&#039;ru&#039;},                              -- Crimean Tatar (Cyrillic script)&lt;br /&gt;
    [&#039;cv&#039;]           = {&#039;ru&#039;},                              -- Chuvash&lt;br /&gt;
    [&#039;inh&#039;]          = {&#039;ru&#039;},                              -- Ingush&lt;br /&gt;
    [&#039;koi&#039;]          = {&#039;ru&#039;},                              -- Komi-Permyak&lt;br /&gt;
    [&#039;krc&#039;]          = {&#039;ru&#039;},                              -- Karachay-Balkar&lt;br /&gt;
    [&#039;kv&#039;]           = {&#039;ru&#039;},                              -- Komi&lt;br /&gt;
    [&#039;lbe&#039;]          = {&#039;ru&#039;},                              -- лакку&lt;br /&gt;
    [&#039;lez&#039;]          = {&#039;ru&#039;},                              -- Lezghian&lt;br /&gt;
    [&#039;mhr&#039;]          = {&#039;ru&#039;},                              -- Eastern Mari&lt;br /&gt;
    [&#039;mrj&#039;]          = {&#039;ru&#039;},                              -- Hill Mari&lt;br /&gt;
    [&#039;myv&#039;]          = {&#039;ru&#039;},                              -- Erzya&lt;br /&gt;
    [&#039;os&#039;]           = {&#039;ru&#039;},                              -- Ossetic&lt;br /&gt;
    [&#039;rue&#039;]          = {&#039;uk&#039;, &#039;ru&#039;},                        -- Rusyn&lt;br /&gt;
    [&#039;sah&#039;]          = {&#039;ru&#039;},                              -- Sakha&lt;br /&gt;
    [&#039;tt&#039;]           = {&#039;tt-cyrl&#039;, &#039;ru&#039;},                   -- Tatar&lt;br /&gt;
    [&#039;tt-cyrl&#039;]      = {&#039;ru&#039;},                              -- Tatar (Cyrillic script)&lt;br /&gt;
    [&#039;udm&#039;]          = {&#039;ru&#039;},                              -- Udmurt&lt;br /&gt;
    [&#039;uk&#039;]           = {&#039;ru&#039;},                              -- Ukranian&lt;br /&gt;
    [&#039;xal&#039;]          = {&#039;ru&#039;},                              -- Kalmyk&lt;br /&gt;
    [&#039;tt&#039;]           = {&#039;tt-cyrl&#039;, &#039;ru&#039;},                   -- Tatar&lt;br /&gt;
&lt;br /&gt;
    -- ruq (Megleno Romanian) cluster: ruq-cyrl , ruq-grek , ruq-latn -&amp;gt; ruq (Megleno Romanian)&lt;br /&gt;
    [&#039;ruq&#039;]          = {&#039;ruq-latn&#039;, &#039;ro&#039;},                  -- Megleno-Romanian&lt;br /&gt;
    [&#039;ruq-cyrl&#039;]     = {&#039;ruq&#039;, &#039;mk&#039;},                       -- Megleno-Romanian (Cyrillic script)&lt;br /&gt;
    [&#039;ruq-grek&#039;]     = {&#039;ruq&#039;},                             -- Megleno-Romanian (Greek script)&lt;br /&gt;
    [&#039;ruq-latn&#039;]     = {&#039;ro&#039;, &#039;ruq&#039;},                       -- Megleno-Romanian (Latin script)&lt;br /&gt;
&lt;br /&gt;
    -- sr (Serbian) cluster: sr-ec , sr-el -&amp;gt; sr (Serbian)&lt;br /&gt;
    [&#039;sr&#039;]           = {&#039;sr-ec&#039;},&lt;br /&gt;
    [&#039;sr-ec&#039;]        = {&#039;sr&#039;}, &lt;br /&gt;
    [&#039;sr-el&#039;]        = {&#039;sr&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- tg (Tajik) cluster: tg-cyrl , tg-latn -&amp;gt; tg (Tajik)&lt;br /&gt;
    [&#039;tg&#039;]           = {&#039;tg-cyrl&#039;},&lt;br /&gt;
    [&#039;tg-cyrl&#039;]      = {&#039;tg&#039;}, &lt;br /&gt;
    [&#039;tg-latn&#039;]      = {&#039;tg&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- tr (Turkish) cluster&lt;br /&gt;
    [&#039;gag&#039;]          = {&#039;tr&#039;},                              -- Gagauz&lt;br /&gt;
    [&#039;kiu&#039;]          = {&#039;tr&#039;},                              -- Kirmanjki&lt;br /&gt;
    [&#039;lzz&#039;]          = {&#039;tr&#039;},                              -- Lazuri&lt;br /&gt;
&lt;br /&gt;
    -- tt (Tatar) cluster: tt-cyrl , tt-latn -&amp;gt; tt (Tatar)&lt;br /&gt;
    [&#039;tt-cyrl&#039;]      = {&#039;tt&#039;},&lt;br /&gt;
    [&#039;tt-latn&#039;]      = {&#039;tt&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- zh (Chinese) cluster&lt;br /&gt;
    -- /includes/language/converters/ZhConverter.php&lt;br /&gt;
    -- https://gerrit.wikimedia.org/r/703560&lt;br /&gt;
    [&#039;cdo&#039;]          = {&#039;nan&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Min Dong Chinese&lt;br /&gt;
    [&#039;gan&#039;]          = {&#039;gan-hant&#039;, &#039;gan-hans&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Gan &lt;br /&gt;
    [&#039;gan-hans&#039;]     = {&#039;gan&#039;, &#039;gan-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},      -- Simplified Gan script&lt;br /&gt;
    [&#039;gan-hant&#039;]     = {&#039;gan&#039;, &#039;gan-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},      -- Traditional Gan script&lt;br /&gt;
    [&#039;hak&#039;]          = {&#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},        -- Hakka&lt;br /&gt;
    [&#039;ii&#039;]           = {&#039;zh-cn&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Sichuan Yi&lt;br /&gt;
    [&#039;lzh&#039;]          = {&#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},        -- Literary Chinese&lt;br /&gt;
    [&#039;nan&#039;]          = {&#039;cdo&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Min Nan Chinese&lt;br /&gt;
    [&#039;szy&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Sakizaya&lt;br /&gt;
    [&#039;tay&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Atayal&lt;br /&gt;
    [&#039;trv&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Seediq&lt;br /&gt;
    [&#039;wuu&#039;]          = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;},        -- Wu&lt;br /&gt;
    -- https://phabricator.wikimedia.org/T59138&lt;br /&gt;
    -- [&#039;wuu&#039;]          = {&#039;wuu-hans, &#039;wuu-hant&#039;, &#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;}, -- Wu&lt;br /&gt;
    -- [&#039;wuu-hans&#039;]     = {&#039;wuu&#039;, &#039;wuu-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},     -- Simplified Wu&lt;br /&gt;
    -- [&#039;wuu-hant&#039;]     = {&#039;wuu&#039;, &#039;wuu-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},     -- Traditional Wu&lt;br /&gt;
    [&#039;yue&#039;]          = {&#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Cantonese&lt;br /&gt;
    -- https://phabricator.wikimedia.org/T59106&lt;br /&gt;
    -- [&#039;yue&#039;]          = {&#039;yue-hant&#039;, &#039;yue-hans, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Cantonese&lt;br /&gt;
    -- [&#039;yue-hans&#039;]     = {&#039;yue&#039;, &#039;yue-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;},     -- Simplified Cantonese&lt;br /&gt;
    -- [&#039;yue-hant&#039;]     = {&#039;yue&#039;, &#039;yue-hans&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},     -- Traditional Cantonese&lt;br /&gt;
    [&#039;za&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;},        -- Zhuang&lt;br /&gt;
    -- The time allocated for running scripts has expired.&lt;br /&gt;
    -- [&#039;zh&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh-cn&#039;, &#039;zh-tw&#039;, &#039;zh-hk&#039;}, -- Chinese&lt;br /&gt;
    -- [&#039;zh-hans&#039;]      = {&#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},   -- Simplified Chinese&lt;br /&gt;
    -- [&#039;zh-hant&#039;]      = {&#039;zh-tw&#039;, &#039;zh-hk&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},   -- Traditional Chinese&lt;br /&gt;
    -- [&#039;zh-tw&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Taiwan)&lt;br /&gt;
    -- [&#039;zh-hk&#039;]        = {&#039;zh-hant&#039;, &#039;zh-tw&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Hong Kong)&lt;br /&gt;
    [&#039;zh&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh-hk&#039;}, -- Chinese&lt;br /&gt;
    [&#039;zh-hans&#039;]      = {&#039;zh-hant&#039;, &#039;zh-hk&#039;},   -- Simplified Chinese&lt;br /&gt;
    [&#039;zh-hant&#039;]      = {&#039;zh-hk&#039;, &#039;zh-hans&#039;},   -- Traditional Chinese&lt;br /&gt;
    [&#039;zh-cn&#039;]        = {&#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Mainland China)&lt;br /&gt;
    [&#039;zh-sg&#039;]        = {&#039;zh-hans&#039;, &#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Singapore)&lt;br /&gt;
    [&#039;zh-my&#039;]        = {&#039;zh-hans&#039;, &#039;zh-sg&#039;, &#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Malaysia)&lt;br /&gt;
    [&#039;zh-tw&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh-hans&#039;}, -- Chinese (Taiwan)&lt;br /&gt;
    [&#039;zh-hk&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hans&#039;}, -- Chinese (Hong Kong)&lt;br /&gt;
    [&#039;zh-mo&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh-tw&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Macau)&lt;br /&gt;
    [&#039;zh-classical&#039;] = {&#039;lzh&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Classical Chinese -&amp;gt; Literary Chinese&lt;br /&gt;
    [&#039;zh-min-nan&#039;]   = {&#039;nan&#039;, &#039;cdo&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},   -- Chinese (Min Nan) -&amp;gt; Min Nan Chinese&lt;br /&gt;
    [&#039;zh-yue&#039;]       = {&#039;yue&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Yue Chinese -&amp;gt; Cantonese&lt;br /&gt;
&lt;br /&gt;
    ------------------------&lt;br /&gt;
    --------- misc ---------&lt;br /&gt;
    ------------------------&lt;br /&gt;
    [&#039;arz&#039;]          = {&#039;ar&#039;},                              -- Egyptian Arabic -&amp;gt; Arabic&lt;br /&gt;
    [&#039;azb&#039;]          = {&#039;az&#039;},                              -- Southern Azerbaijani -&amp;gt; Azerbaijani &lt;br /&gt;
    [&#039;be-x-old&#039;]     = {&#039;be-tarask&#039;},                       -- be-x-old -&amp;gt; be-tarask (wrong to correct Taraškievica form of Belarusian orthography)&lt;br /&gt;
    [&#039;bh&#039;]           = {&#039;bho&#039;},                             -- Bihari -&amp;gt; Bhojpuri&lt;br /&gt;
    [&#039;bpy&#039;]          = {&#039;bn&#039;},                              -- Bishnupria Manipuri -&amp;gt; Bengali&lt;br /&gt;
&lt;br /&gt;
    -- da&lt;br /&gt;
    [&#039;jut&#039;]          = {&#039;da&#039;},                              -- Jutish -&amp;gt; Danish&lt;br /&gt;
    [&#039;kl&#039;]           = {&#039;da&#039;},                              -- Kalaallisut -&amp;gt; Danish&lt;br /&gt;
&lt;br /&gt;
    [&#039;en-gb&#039;]        = {&#039;en&#039;},                              -- Brexit -&amp;gt; English&lt;br /&gt;
    [&#039;yi&#039;]           = {&#039;he&#039;},                              -- Yiddish -&amp;gt; Hebrew&lt;br /&gt;
    [&#039;iu&#039;]           = {&#039;ike-cans&#039;},                        -- Inuktitut -&amp;gt; Eastern Canadian (Aboriginal syllabics)&lt;br /&gt;
    [&#039;xmf&#039;]          = {&#039;ka&#039;},                              -- Mingrelian -&amp;gt; Georgian&lt;br /&gt;
    [&#039;kbd&#039;]          = {&#039;kbd-cyrl&#039;, &#039;ru&#039;},                  -- Kabardian -&amp;gt; Адыгэбзэ&lt;br /&gt;
    [&#039;tcy&#039;]          = {&#039;kn&#039;},                              -- Tulu -&amp;gt; Kannada&lt;br /&gt;
    [&#039;ko-kp&#039;]        = {&#039;ko&#039;},                              -- 한국어 (조선) -&amp;gt; Korean&lt;br /&gt;
    [&#039;ks&#039;]           = {&#039;ks-arab&#039;},                         -- Kashmiri -&amp;gt; Kashmiri (Arabic script)&lt;br /&gt;
&lt;br /&gt;
    -- lt&lt;br /&gt;
    [&#039;bat-smg&#039;]      = {&#039;sgs&#039;, &#039;lt&#039;},                       -- Samogitian -&amp;gt; Lithuanian&lt;br /&gt;
    [&#039;sgs&#039;]          = {&#039;lt&#039;},                              -- Samogitian -&amp;gt; Lithuanian&lt;br /&gt;
&lt;br /&gt;
    [&#039;ltg&#039;]          = {&#039;lv&#039;},                              -- Latvian -&amp;gt; Latgalian&lt;br /&gt;
    [&#039;dtp&#039;]          = {&#039;ms&#039;},                              -- Central Dusun -&amp;gt; Malay&lt;br /&gt;
    [&#039;no&#039;]           = {&#039;nb&#039;},                              -- Norwegian (bokmål) -&amp;gt; Norwegian Bokmål&lt;br /&gt;
    [&#039;roa-rup&#039;]      = {&#039;rup&#039;},                             -- Aromanian (other Romance) -&amp;gt; Aromanian&lt;br /&gt;
    [&#039;aln&#039;]          = {&#039;sq&#039;},                              -- Gheg Albanian -&amp;gt; Albanian&lt;br /&gt;
    [&#039;ug&#039;]           = {&#039;ug-arab&#039;},                         -- Uyghur -&amp;gt; Uyghur (Arabic script)&lt;br /&gt;
    [&#039;khw&#039;]          = {&#039;ur&#039;},                              -- Khowar -&amp;gt; Urdu&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Fallbacklist&amp;diff=85</id>
		<title>Module:Fallbacklist</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Fallbacklist&amp;diff=85"/>
		<updated>2026-06-22T02:07:26Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;--- Language fallback rules for other Lua modules. -- @see       c:Module:Fallbacklist -- @release   stable -- @submodule return {      -- crh (Crimean Tatar) cluster: crh-cyrl , crh-latn -&amp;gt; crh (Crimean Tatar)     [&amp;#039;crh&amp;#039;]          = {&amp;#039;crh-latn&amp;#039;},     [&amp;#039;crh-cyrl&amp;#039;]     = {&amp;#039;crh&amp;#039;, &amp;#039;ru&amp;#039;},      [&amp;#039;crh-latn&amp;#039;]     = {&amp;#039;crh&amp;#039;},      -- de (German) cluster:     [&amp;#039;als&amp;#039;]          = {&amp;#039;gsw&amp;#039;, &amp;#039;de&amp;#039;},                       -- Alemannisch     [&amp;#039;bar&amp;#039;]          = {&amp;#039;de&amp;#039;},...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--- Language fallback rules for other Lua modules.&lt;br /&gt;
-- @see       [[c:Module:Fallbacklist]]&lt;br /&gt;
-- @release   stable&lt;br /&gt;
-- @submodule&lt;br /&gt;
return {&lt;br /&gt;
&lt;br /&gt;
    -- crh (Crimean Tatar) cluster: crh-cyrl , crh-latn -&amp;gt; crh (Crimean Tatar)&lt;br /&gt;
    [&#039;crh&#039;]          = {&#039;crh-latn&#039;},&lt;br /&gt;
    [&#039;crh-cyrl&#039;]     = {&#039;crh&#039;, &#039;ru&#039;}, &lt;br /&gt;
    [&#039;crh-latn&#039;]     = {&#039;crh&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- de (German) cluster:&lt;br /&gt;
    [&#039;als&#039;]          = {&#039;gsw&#039;, &#039;de&#039;},                       -- Alemannisch&lt;br /&gt;
    [&#039;bar&#039;]          = {&#039;de&#039;},                              -- Bavarian&lt;br /&gt;
    [&#039;de-at&#039;]        = {&#039;de&#039;},                              -- Austrian German&lt;br /&gt;
    [&#039;de-ch&#039;]        = {&#039;de&#039;},                              -- Swiss High German&lt;br /&gt;
    [&#039;de-formal&#039;]    = {&#039;de&#039;},                              -- German (formal address)&lt;br /&gt;
    [&#039;dsb&#039;]          = {&#039;de&#039;},                              -- Lower Sorbian&lt;br /&gt;
    [&#039;frr&#039;]          = {&#039;de&#039;},                              -- Northern Frisian&lt;br /&gt;
    [&#039;hsb&#039;]          = {&#039;de&#039;},                              -- Upper Sorbian&lt;br /&gt;
    [&#039;ksh&#039;]          = {&#039;de&#039;},                              -- Colognian&lt;br /&gt;
    [&#039;lb&#039;]           = {&#039;de&#039;},                              -- Luxembourgish&lt;br /&gt;
    [&#039;nds&#039;]          = {&#039;nds-nl&#039;, &#039;de&#039;},                    -- Low German&lt;br /&gt;
    [&#039;nds-nl&#039;]       = {&#039;nds&#039;, &#039;nl&#039;},                       -- Low Saxon (Netherlands)&lt;br /&gt;
    [&#039;pdc&#039;]          = {&#039;de&#039;},                              -- Deitsch&lt;br /&gt;
    [&#039;pdt&#039;]          = {&#039;nds&#039;, &#039;de&#039;},                       -- Plautdietsch&lt;br /&gt;
    [&#039;pfl&#039;]          = {&#039;de&#039;},                              -- Pälzisch&lt;br /&gt;
    [&#039;sli&#039;]          = {&#039;de&#039;},                              -- Lower Silesian&lt;br /&gt;
    [&#039;stq&#039;]          = {&#039;de&#039;},                              -- Seeltersk&lt;br /&gt;
    [&#039;vmf&#039;]          = {&#039;de&#039;},                              -- Upper Franconian&lt;br /&gt;
&lt;br /&gt;
    -- es (Spanish) cluster&lt;br /&gt;
    [&#039;an&#039;]           = {&#039;es&#039;},                              -- Aragonese&lt;br /&gt;
    [&#039;arn&#039;]          = {&#039;es&#039;},                              -- Mapuche&lt;br /&gt;
    [&#039;ay&#039;]           = {&#039;es&#039;},                              -- Aymara&lt;br /&gt;
    [&#039;cbk-zam&#039;]      = {&#039;es&#039;},                              -- Chavacano de Zamboanga&lt;br /&gt;
    [&#039;gn&#039;]           = {&#039;es&#039;},                              -- Guarani&lt;br /&gt;
    [&#039;lad&#039;]          = {&#039;es&#039;},                              -- Ladino&lt;br /&gt;
    [&#039;nah&#039;]          = {&#039;es&#039;},                              -- Nahuatl&lt;br /&gt;
    [&#039;qu&#039;]           = {&#039;es&#039;},                              -- Quechua&lt;br /&gt;
    [&#039;qug&#039;]          = {&#039;qu&#039;, &#039;es&#039;},                        -- Runa shimi&lt;br /&gt;
&lt;br /&gt;
    -- et (Estonian) cluster&lt;br /&gt;
    [&#039;liv&#039;]          = {&#039;et&#039;},                              -- Līvõ kēļ&lt;br /&gt;
    [&#039;vep&#039;]          = {&#039;et&#039;},                              -- Veps&lt;br /&gt;
    [&#039;vro&#039;]          = {&#039;et&#039;},                              -- Võro&lt;br /&gt;
    [&#039;fiu-vro&#039;]      = {&#039;vro&#039;, &#039;et&#039;},                       -- Võro&lt;br /&gt;
&lt;br /&gt;
    -- fa (Persian) cluster&lt;br /&gt;
    [&#039;bcc&#039;]          = {&#039;fa&#039;},                              -- Southern Balochi&lt;br /&gt;
    [&#039;bqi&#039;]          = {&#039;fa&#039;},                              -- Bakhtiari&lt;br /&gt;
    [&#039;glk&#039;]          = {&#039;fa&#039;},                              -- Gilaki&lt;br /&gt;
    [&#039;mzn&#039;]          = {&#039;fa&#039;},                              -- Mazandarani&lt;br /&gt;
&lt;br /&gt;
    -- fi (Finnish) cluster:&lt;br /&gt;
    [&#039;fit&#039;]          = {&#039;fi&#039;},                              -- meänkieli&lt;br /&gt;
    [&#039;vot&#039;]          = {&#039;fi&#039;},                              -- Votic&lt;br /&gt;
&lt;br /&gt;
    -- fr (French) cluster:&lt;br /&gt;
    [&#039;bm&#039;]           = {&#039;fr&#039;},                              -- Bambara&lt;br /&gt;
    [&#039;br&#039;]           = {&#039;fr&#039;},                              -- Breton&lt;br /&gt;
    [&#039;co&#039;]           = {&#039;fr&#039;},                              -- Corsican&lt;br /&gt;
    [&#039;ff&#039;]           = {&#039;fr&#039;},                              -- Fulah&lt;br /&gt;
    [&#039;frc&#039;]          = {&#039;fr&#039;},                              -- Cajun French&lt;br /&gt;
    [&#039;frp&#039;]          = {&#039;fr&#039;},                              -- Franco-Provençal&lt;br /&gt;
    [&#039;ht&#039;]           = {&#039;fr&#039;},                              -- Haitian&lt;br /&gt;
    [&#039;ln&#039;]           = {&#039;fr&#039;},                              -- Lingala&lt;br /&gt;
    [&#039;mg&#039;]           = {&#039;fr&#039;},                              -- Malagasy&lt;br /&gt;
    [&#039;pcd&#039;]          = {&#039;fr&#039;},                              -- Picard&lt;br /&gt;
    [&#039;sg&#039;]           = {&#039;fr&#039;},                              -- Sango&lt;br /&gt;
    [&#039;ty&#039;]           = {&#039;fr&#039;},                              -- Tahitian&lt;br /&gt;
    [&#039;wa&#039;]           = {&#039;fr&#039;},                              -- Walloon&lt;br /&gt;
    [&#039;wo&#039;]           = {&#039;fr&#039;},                              -- Wolof&lt;br /&gt;
&lt;br /&gt;
    -- hi (Hindi) cluster&lt;br /&gt;
    [&#039;anp&#039;]          = {&#039;hi&#039;},                              -- Angika&lt;br /&gt;
    [&#039;mai&#039;]          = {&#039;hi&#039;},                              -- Maithili&lt;br /&gt;
    [&#039;sa&#039;]           = {&#039;hi&#039;},                              -- Sanskrit&lt;br /&gt;
&lt;br /&gt;
    -- hif (Fiji Hindi) cluster: hif-deva , hif-latn -&amp;gt; hif (Fiji Hindi)&lt;br /&gt;
    [&#039;hif&#039;]          = {&#039;hif-latn&#039;},&lt;br /&gt;
    [&#039;hif-deva&#039;]     = {&#039;hif&#039;}, &lt;br /&gt;
    [&#039;hif-latn&#039;]     = {&#039;hif&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- id (Indonesian) cluster&lt;br /&gt;
    [&#039;min&#039;]          = {&#039;id&#039;},                              -- Minangkabau&lt;br /&gt;
    [&#039;ace&#039;]          = {&#039;id&#039;},                              -- Achinese&lt;br /&gt;
    [&#039;bug&#039;]          = {&#039;id&#039;},                              -- Buginese&lt;br /&gt;
    [&#039;bjn&#039;]          = {&#039;id&#039;},                              -- Banjar&lt;br /&gt;
    [&#039;jv&#039;]           = {&#039;id&#039;},                              -- Javanese&lt;br /&gt;
    [&#039;su&#039;]           = {&#039;id&#039;},                              -- Sundanese&lt;br /&gt;
    [&#039;map-bms&#039;]      = {&#039;jv&#039;, &#039;id&#039;},                        -- Basa Banyumasan&lt;br /&gt;
&lt;br /&gt;
    -- ike (Eastern Canadian Inuktitut) cluster: ike-cans , ike-latn -&amp;gt; ike (Eastern Canadian Inuktitut)&lt;br /&gt;
    [&#039;ike-cans&#039;]     = {&#039;ik&#039;}, &lt;br /&gt;
    [&#039;ike-latn&#039;]     = {&#039;ik&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- it (Italian) cluster&lt;br /&gt;
    [&#039;egl&#039;]          = {&#039;it&#039;},                              -- Emiliàn&lt;br /&gt;
    [&#039;eml&#039;]          = {&#039;it&#039;},                              -- Emiliano-Romagnolo&lt;br /&gt;
    [&#039;fur&#039;]          = {&#039;it&#039;},                              -- Friulian&lt;br /&gt;
    [&#039;lij&#039;]          = {&#039;it&#039;},                              -- Ligure&lt;br /&gt;
    [&#039;lmo&#039;]          = {&#039;it&#039;},                              -- lumbaart&lt;br /&gt;
    [&#039;nap&#039;]          = {&#039;it&#039;},                              -- Neapolitan&lt;br /&gt;
    [&#039;pms&#039;]          = {&#039;it&#039;},                              -- Piedmontese&lt;br /&gt;
    [&#039;rgn&#039;]          = {&#039;it&#039;},                              -- Romagnol&lt;br /&gt;
    [&#039;scn&#039;]          = {&#039;it&#039;},                              -- Sicilian&lt;br /&gt;
    [&#039;vec&#039;]          = {&#039;it&#039;},                              -- vèneto&lt;br /&gt;
&lt;br /&gt;
    -- kk (Kazakh) cluster:&lt;br /&gt;
    -- kk-arab , kk-cyrl , kk-latn , kk-cn , kk-kz , kk-tr -&amp;gt; kk (Kazakh)&lt;br /&gt;
    [&#039;kk&#039;]           = {&#039;kk-cyrl&#039;},                         -- Kazakh&lt;br /&gt;
    [&#039;kk-arab&#039;]      = {&#039;kk-cyrl&#039;, &#039;kk&#039;},                   -- Kazakh (Arabic script)&lt;br /&gt;
    [&#039;kk-cn&#039;]        = {&#039;kk-arab&#039;, &#039;kk-cyrl&#039;, &#039;kk&#039;},        -- Kazakh (China)&lt;br /&gt;
    [&#039;kk-cyrl&#039;]      = {&#039;kk&#039;},                              -- Kazakh (Cyrillic script)&lt;br /&gt;
    [&#039;kk-kz&#039;]        = {&#039;kk&#039;, &#039;kk-cyrl&#039;},                   -- Kazakh (Kazakhstan)&lt;br /&gt;
    [&#039;kk-latn&#039;]      = {&#039;kk-cyrl&#039;, &#039;kk&#039;},                   -- Kazakh (Latin script)&lt;br /&gt;
    [&#039;kk-tr&#039;]        = {&#039;kk-latn&#039;, &#039;kk-cyrl&#039;, &#039;kk&#039;},        -- Kazakh (Turkey)&lt;br /&gt;
    [&#039;kaa&#039;]          = {&#039;kk-latn&#039;, &#039;kk-cyrl&#039;},              -- Kara-Kalpak&lt;br /&gt;
&lt;br /&gt;
    -- ku (Kurdish) cluster: ku-latn , ku-arab -&amp;gt; ku (Kurdish)&lt;br /&gt;
    [&#039;ku&#039;]           = {&#039;ku-latn&#039;},&lt;br /&gt;
    [&#039;ku-arab&#039;]      = {&#039;ckb&#039;, &#039;ckb-arab&#039;, &#039;ku&#039;},           -- كوردي (عەرەبی)&lt;br /&gt;
    [&#039;ku-latn&#039;]      = {&#039;ku&#039;},&lt;br /&gt;
    [&#039;ckb&#039;]          = {&#039;ckb-arab&#039;, &#039;ku&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- nl (Dutch) cluster&lt;br /&gt;
    [&#039;af&#039;]           = {&#039;nl&#039;},                              -- Afrikaans&lt;br /&gt;
    [&#039;fy&#039;]           = {&#039;nl&#039;},                              -- Western Frisian&lt;br /&gt;
    [&#039;li&#039;]           = {&#039;nl&#039;},                              -- Liechtenstein&lt;br /&gt;
    [&#039;nl-informal&#039;]  = {&#039;nl&#039;},                              -- Nederlands (informeel)&lt;br /&gt;
    [&#039;vls&#039;]          = {&#039;nl&#039;},                              -- Vlaams&lt;br /&gt;
    [&#039;zea&#039;]          = {&#039;nl&#039;},                              -- Zeeuws&lt;br /&gt;
&lt;br /&gt;
    --pl (Polish) cluster&lt;br /&gt;
    [&#039;csb&#039;]          = {&#039;pl&#039;},                              -- Kashubian&lt;br /&gt;
    [&#039;szl&#039;]          = {&#039;pl&#039;},                              -- Silesian&lt;br /&gt;
&lt;br /&gt;
    -- pt (Portuguese) cluster&lt;br /&gt;
    [&#039;gl&#039;]           = {&#039;pt&#039;},                              -- Galician&lt;br /&gt;
    [&#039;mwl&#039;]          = {&#039;pt&#039;},                              -- Mirandese&lt;br /&gt;
    [&#039;pt-br&#039;]        = {&#039;pt&#039;},                              -- Brazilian Portuguese&lt;br /&gt;
&lt;br /&gt;
    -- ro (Romanian) cluster&lt;br /&gt;
    [&#039;mo&#039;]           = {&#039;ro&#039;},                              -- Moldavian&lt;br /&gt;
    [&#039;rmy&#039;]          = {&#039;ro&#039;},                              -- Romani&lt;br /&gt;
&lt;br /&gt;
    -- ru (Russian) cluster&lt;br /&gt;
    [&#039;ab&#039;]           = {&#039;ru&#039;},                              -- Abkhazian&lt;br /&gt;
    [&#039;av&#039;]           = {&#039;ru&#039;},                              -- Avaric&lt;br /&gt;
    [&#039;ba&#039;]           = {&#039;ru&#039;},                              -- Bashkir&lt;br /&gt;
    [&#039;be-tarask&#039;]    = {&#039;ru&#039;},                              -- Belorussian&lt;br /&gt;
    [&#039;ce&#039;]           = {&#039;ru&#039;},                              -- Chechen&lt;br /&gt;
    [&#039;crh-cyrl&#039;]     = {&#039;ru&#039;},                              -- Crimean Tatar (Cyrillic script)&lt;br /&gt;
    [&#039;cv&#039;]           = {&#039;ru&#039;},                              -- Chuvash&lt;br /&gt;
    [&#039;inh&#039;]          = {&#039;ru&#039;},                              -- Ingush&lt;br /&gt;
    [&#039;koi&#039;]          = {&#039;ru&#039;},                              -- Komi-Permyak&lt;br /&gt;
    [&#039;krc&#039;]          = {&#039;ru&#039;},                              -- Karachay-Balkar&lt;br /&gt;
    [&#039;kv&#039;]           = {&#039;ru&#039;},                              -- Komi&lt;br /&gt;
    [&#039;lbe&#039;]          = {&#039;ru&#039;},                              -- лакку&lt;br /&gt;
    [&#039;lez&#039;]          = {&#039;ru&#039;},                              -- Lezghian&lt;br /&gt;
    [&#039;mhr&#039;]          = {&#039;ru&#039;},                              -- Eastern Mari&lt;br /&gt;
    [&#039;mrj&#039;]          = {&#039;ru&#039;},                              -- Hill Mari&lt;br /&gt;
    [&#039;myv&#039;]          = {&#039;ru&#039;},                              -- Erzya&lt;br /&gt;
    [&#039;os&#039;]           = {&#039;ru&#039;},                              -- Ossetic&lt;br /&gt;
    [&#039;rue&#039;]          = {&#039;uk&#039;, &#039;ru&#039;},                        -- Rusyn&lt;br /&gt;
    [&#039;sah&#039;]          = {&#039;ru&#039;},                              -- Sakha&lt;br /&gt;
    [&#039;tt&#039;]           = {&#039;tt-cyrl&#039;, &#039;ru&#039;},                   -- Tatar&lt;br /&gt;
    [&#039;tt-cyrl&#039;]      = {&#039;ru&#039;},                              -- Tatar (Cyrillic script)&lt;br /&gt;
    [&#039;udm&#039;]          = {&#039;ru&#039;},                              -- Udmurt&lt;br /&gt;
    [&#039;uk&#039;]           = {&#039;ru&#039;},                              -- Ukranian&lt;br /&gt;
    [&#039;xal&#039;]          = {&#039;ru&#039;},                              -- Kalmyk&lt;br /&gt;
    [&#039;tt&#039;]           = {&#039;tt-cyrl&#039;, &#039;ru&#039;},                   -- Tatar&lt;br /&gt;
&lt;br /&gt;
    -- ruq (Megleno Romanian) cluster: ruq-cyrl , ruq-grek , ruq-latn -&amp;gt; ruq (Megleno Romanian)&lt;br /&gt;
    [&#039;ruq&#039;]          = {&#039;ruq-latn&#039;, &#039;ro&#039;},                  -- Megleno-Romanian&lt;br /&gt;
    [&#039;ruq-cyrl&#039;]     = {&#039;ruq&#039;, &#039;mk&#039;},                       -- Megleno-Romanian (Cyrillic script)&lt;br /&gt;
    [&#039;ruq-grek&#039;]     = {&#039;ruq&#039;},                             -- Megleno-Romanian (Greek script)&lt;br /&gt;
    [&#039;ruq-latn&#039;]     = {&#039;ro&#039;, &#039;ruq&#039;},                       -- Megleno-Romanian (Latin script)&lt;br /&gt;
&lt;br /&gt;
    -- sr (Serbian) cluster: sr-ec , sr-el -&amp;gt; sr (Serbian)&lt;br /&gt;
    [&#039;sr&#039;]           = {&#039;sr-ec&#039;},&lt;br /&gt;
    [&#039;sr-ec&#039;]        = {&#039;sr&#039;}, &lt;br /&gt;
    [&#039;sr-el&#039;]        = {&#039;sr&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- tg (Tajik) cluster: tg-cyrl , tg-latn -&amp;gt; tg (Tajik)&lt;br /&gt;
    [&#039;tg&#039;]           = {&#039;tg-cyrl&#039;},&lt;br /&gt;
    [&#039;tg-cyrl&#039;]      = {&#039;tg&#039;}, &lt;br /&gt;
    [&#039;tg-latn&#039;]      = {&#039;tg&#039;}, &lt;br /&gt;
&lt;br /&gt;
    -- tr (Turkish) cluster&lt;br /&gt;
    [&#039;gag&#039;]          = {&#039;tr&#039;},                              -- Gagauz&lt;br /&gt;
    [&#039;kiu&#039;]          = {&#039;tr&#039;},                              -- Kirmanjki&lt;br /&gt;
    [&#039;lzz&#039;]          = {&#039;tr&#039;},                              -- Lazuri&lt;br /&gt;
&lt;br /&gt;
    -- tt (Tatar) cluster: tt-cyrl , tt-latn -&amp;gt; tt (Tatar)&lt;br /&gt;
    [&#039;tt-cyrl&#039;]      = {&#039;tt&#039;},&lt;br /&gt;
    [&#039;tt-latn&#039;]      = {&#039;tt&#039;},&lt;br /&gt;
&lt;br /&gt;
    -- zh (Chinese) cluster&lt;br /&gt;
    -- /includes/language/converters/ZhConverter.php&lt;br /&gt;
    -- https://gerrit.wikimedia.org/r/703560&lt;br /&gt;
    [&#039;cdo&#039;]          = {&#039;nan&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Min Dong Chinese&lt;br /&gt;
    [&#039;gan&#039;]          = {&#039;gan-hant&#039;, &#039;gan-hans&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Gan &lt;br /&gt;
    [&#039;gan-hans&#039;]     = {&#039;gan&#039;, &#039;gan-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},      -- Simplified Gan script&lt;br /&gt;
    [&#039;gan-hant&#039;]     = {&#039;gan&#039;, &#039;gan-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},      -- Traditional Gan script&lt;br /&gt;
    [&#039;hak&#039;]          = {&#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},        -- Hakka&lt;br /&gt;
    [&#039;ii&#039;]           = {&#039;zh-cn&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Sichuan Yi&lt;br /&gt;
    [&#039;lzh&#039;]          = {&#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},        -- Literary Chinese&lt;br /&gt;
    [&#039;nan&#039;]          = {&#039;cdo&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Min Nan Chinese&lt;br /&gt;
    [&#039;szy&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Sakizaya&lt;br /&gt;
    [&#039;tay&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Atayal&lt;br /&gt;
    [&#039;trv&#039;]          = {&#039;zh-tw&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Seediq&lt;br /&gt;
    [&#039;wuu&#039;]          = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;},        -- Wu&lt;br /&gt;
    -- https://phabricator.wikimedia.org/T59138&lt;br /&gt;
    -- [&#039;wuu&#039;]          = {&#039;wuu-hans, &#039;wuu-hant&#039;, &#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;}, -- Wu&lt;br /&gt;
    -- [&#039;wuu-hans&#039;]     = {&#039;wuu&#039;, &#039;wuu-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},     -- Simplified Wu&lt;br /&gt;
    -- [&#039;wuu-hant&#039;]     = {&#039;wuu&#039;, &#039;wuu-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},     -- Traditional Wu&lt;br /&gt;
    [&#039;yue&#039;]          = {&#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Cantonese&lt;br /&gt;
    -- https://phabricator.wikimedia.org/T59106&lt;br /&gt;
    -- [&#039;yue&#039;]          = {&#039;yue-hant&#039;, &#039;yue-hans, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Cantonese&lt;br /&gt;
    -- [&#039;yue-hans&#039;]     = {&#039;yue&#039;, &#039;yue-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;},     -- Simplified Cantonese&lt;br /&gt;
    -- [&#039;yue-hant&#039;]     = {&#039;yue&#039;, &#039;yue-hans&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},     -- Traditional Cantonese&lt;br /&gt;
    [&#039;za&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh&#039;},        -- Zhuang&lt;br /&gt;
    -- The time allocated for running scripts has expired.&lt;br /&gt;
    -- [&#039;zh&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh-cn&#039;, &#039;zh-tw&#039;, &#039;zh-hk&#039;}, -- Chinese&lt;br /&gt;
    -- [&#039;zh-hans&#039;]      = {&#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;},   -- Simplified Chinese&lt;br /&gt;
    -- [&#039;zh-hant&#039;]      = {&#039;zh-tw&#039;, &#039;zh-hk&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},   -- Traditional Chinese&lt;br /&gt;
    -- [&#039;zh-tw&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Taiwan)&lt;br /&gt;
    -- [&#039;zh-hk&#039;]        = {&#039;zh-hant&#039;, &#039;zh-tw&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Hong Kong)&lt;br /&gt;
    [&#039;zh&#039;]           = {&#039;zh-hans&#039;, &#039;zh-hant&#039;, &#039;zh-hk&#039;}, -- Chinese&lt;br /&gt;
    [&#039;zh-hans&#039;]      = {&#039;zh-hant&#039;, &#039;zh-hk&#039;},   -- Simplified Chinese&lt;br /&gt;
    [&#039;zh-hant&#039;]      = {&#039;zh-hk&#039;, &#039;zh-hans&#039;},   -- Traditional Chinese&lt;br /&gt;
    [&#039;zh-cn&#039;]        = {&#039;zh-hans&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Mainland China)&lt;br /&gt;
    [&#039;zh-sg&#039;]        = {&#039;zh-hans&#039;, &#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Singapore)&lt;br /&gt;
    [&#039;zh-my&#039;]        = {&#039;zh-hans&#039;, &#039;zh-sg&#039;, &#039;zh-cn&#039;, &#039;zh&#039;, &#039;zh-hant&#039;}, -- Chinese (Malaysia)&lt;br /&gt;
    [&#039;zh-tw&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh-hans&#039;}, -- Chinese (Taiwan)&lt;br /&gt;
    [&#039;zh-hk&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hans&#039;}, -- Chinese (Hong Kong)&lt;br /&gt;
    [&#039;zh-mo&#039;]        = {&#039;zh-hant&#039;, &#039;zh-hk&#039;, &#039;zh-tw&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Chinese (Macau)&lt;br /&gt;
    [&#039;zh-classical&#039;] = {&#039;lzh&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;}, -- Classical Chinese -&amp;gt; Literary Chinese&lt;br /&gt;
    [&#039;zh-min-nan&#039;]   = {&#039;nan&#039;, &#039;cdo&#039;, &#039;zh-hant&#039;, &#039;zh&#039;, &#039;zh-hans&#039;},   -- Chinese (Min Nan) -&amp;gt; Min Nan Chinese&lt;br /&gt;
    [&#039;zh-yue&#039;]       = {&#039;yue&#039;, &#039;zh-hk&#039;, &#039;zh-hant&#039;, &#039;zh-hans&#039;, &#039;zh&#039;}, -- Yue Chinese -&amp;gt; Cantonese&lt;br /&gt;
&lt;br /&gt;
    ------------------------&lt;br /&gt;
    --------- misc ---------&lt;br /&gt;
    ------------------------&lt;br /&gt;
    [&#039;arz&#039;]          = {&#039;ar&#039;},                              -- Egyptian Arabic -&amp;gt; Arabic&lt;br /&gt;
    [&#039;azb&#039;]          = {&#039;az&#039;},                              -- Southern Azerbaijani -&amp;gt; Azerbaijani &lt;br /&gt;
    [&#039;be-x-old&#039;]     = {&#039;be-tarask&#039;},                       -- be-x-old -&amp;gt; be-tarask (wrong to correct Taraškievica form of Belarusian orthography)&lt;br /&gt;
    [&#039;bh&#039;]           = {&#039;bho&#039;},                             -- Bihari -&amp;gt; Bhojpuri&lt;br /&gt;
    [&#039;bpy&#039;]          = {&#039;bn&#039;},                              -- Bishnupria Manipuri -&amp;gt; Bengali&lt;br /&gt;
&lt;br /&gt;
    -- da&lt;br /&gt;
    [&#039;jut&#039;]          = {&#039;da&#039;},                              -- Jutish -&amp;gt; Danish&lt;br /&gt;
    [&#039;kl&#039;]           = {&#039;da&#039;},                              -- Kalaallisut -&amp;gt; Danish&lt;br /&gt;
&lt;br /&gt;
    [&#039;en-gb&#039;]        = {&#039;en&#039;},                              -- Brexit -&amp;gt; English&lt;br /&gt;
    [&#039;yi&#039;]           = {&#039;he&#039;},                              -- Yiddish -&amp;gt; Hebrew&lt;br /&gt;
    [&#039;iu&#039;]           = {&#039;ike-cans&#039;},                        -- Inuktitut -&amp;gt; Eastern Canadian (Aboriginal syllabics)&lt;br /&gt;
    [&#039;xmf&#039;]          = {&#039;ka&#039;},                              -- Mingrelian -&amp;gt; Georgian&lt;br /&gt;
    [&#039;kbd&#039;]          = {&#039;kbd-cyrl&#039;, &#039;ru&#039;},                  -- Kabardian -&amp;gt; Адыгэбзэ&lt;br /&gt;
    [&#039;tcy&#039;]          = {&#039;kn&#039;},                              -- Tulu -&amp;gt; Kannada&lt;br /&gt;
    [&#039;ko-kp&#039;]        = {&#039;ko&#039;},                              -- 한국어 (조선) -&amp;gt; Korean&lt;br /&gt;
    [&#039;ks&#039;]           = {&#039;ks-arab&#039;},                         -- Kashmiri -&amp;gt; Kashmiri (Arabic script)&lt;br /&gt;
&lt;br /&gt;
    -- lt&lt;br /&gt;
    [&#039;bat-smg&#039;]      = {&#039;sgs&#039;, &#039;lt&#039;},                       -- Samogitian -&amp;gt; Lithuanian&lt;br /&gt;
    [&#039;sgs&#039;]          = {&#039;lt&#039;},                              -- Samogitian -&amp;gt; Lithuanian&lt;br /&gt;
&lt;br /&gt;
    [&#039;ltg&#039;]          = {&#039;lv&#039;},                              -- Latvian -&amp;gt; Latgalian&lt;br /&gt;
    [&#039;dtp&#039;]          = {&#039;ms&#039;},                              -- Central Dusun -&amp;gt; Malay&lt;br /&gt;
    [&#039;no&#039;]           = {&#039;nb&#039;},                              -- Norwegian (bokmål) -&amp;gt; Norwegian Bokmål&lt;br /&gt;
    [&#039;roa-rup&#039;]      = {&#039;rup&#039;},                             -- Aromanian (other Romance) -&amp;gt; Aromanian&lt;br /&gt;
    [&#039;aln&#039;]          = {&#039;sq&#039;},                              -- Gheg Albanian -&amp;gt; Albanian&lt;br /&gt;
    [&#039;ug&#039;]           = {&#039;ug-arab&#039;},                         -- Uyghur -&amp;gt; Uyghur (Arabic script)&lt;br /&gt;
    [&#039;khw&#039;]          = {&#039;ur&#039;},                              -- Khowar -&amp;gt; Urdu&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:I18n&amp;diff=84</id>
		<title>Module:I18n</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:I18n&amp;diff=84"/>
		<updated>2026-06-22T02:06:56Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;--- I18n library for message storage in Lua datastores. --  The module is designed to enable message separation from modules &amp;amp; --  templates. It has support for handling language fallbacks. This --  module is a Lua port of wikia:dev:I18n-js and i18n modules that can be loaded --  by it are editable through wikia:dev:I18nEdit. --   --  On Wikimedia projects, i18n messages are editable  --  through Data:i18n/ subpages on --  Wik...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--- I18n library for message storage in Lua datastores.&lt;br /&gt;
--  The module is designed to enable message separation from modules &amp;amp;&lt;br /&gt;
--  templates. It has support for handling language fallbacks. This&lt;br /&gt;
--  module is a Lua port of [[wikia:dev:I18n-js]] and i18n modules that can be loaded&lt;br /&gt;
--  by it are editable through [[wikia:dev:I18nEdit]].&lt;br /&gt;
--  &lt;br /&gt;
--  On Wikimedia projects, i18n messages are editable &lt;br /&gt;
--  through [[c:Special:PrefixIndex/Data:i18n/|Data:i18n/]] subpages on&lt;br /&gt;
--  Wikimedia Commons.&lt;br /&gt;
--  &lt;br /&gt;
--  @module		 i18n&lt;br /&gt;
--  @version		1.4.0&lt;br /&gt;
--  @require		Module:Entrypoint&lt;br /&gt;
--  @require		Module:Fallbacklist&lt;br /&gt;
--  @author		 [[wikia:dev:User:KockaAdmiralac|KockaAdmiralac]] (original Fandom implementation)&lt;br /&gt;
--  @author		 [[wikia:dev:User:Speedit|Speedit]] (original Fandom implementation)&lt;br /&gt;
--  @author			[[User:Awesome Aasim|Awesome Aasim]] (Wikimedia port)&lt;br /&gt;
--  @attribution	[[wikia:dev:User:Cqm|Cqm]]&lt;br /&gt;
--  @release		beta&lt;br /&gt;
--  @see			[[wikia:dev:I18n|I18n guide]]&lt;br /&gt;
--  @see			[[wikia:dev:I18n-js]]&lt;br /&gt;
--  @see			[[wikia:dev:I18nEdit]]&lt;br /&gt;
--  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
local i18n, _i18n = {}, {}&lt;br /&gt;
&lt;br /&gt;
--  Module variables &amp;amp; dependencies.&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
local fallbacks = require(&#039;Module:Fallbacklist&#039;)&lt;br /&gt;
local entrypoint = require(&#039;Module:Entrypoint&#039;)&lt;br /&gt;
local uselang&lt;br /&gt;
&lt;br /&gt;
--- Argument substitution as $n where n &amp;gt; 0.&lt;br /&gt;
--  @function		   _i18n.handleArgs&lt;br /&gt;
--  @param			  {string} msg Message to substitute arguments into.&lt;br /&gt;
--  @param			  {table} args Arguments table to substitute.&lt;br /&gt;
--  @return			 {string} Resulting message.&lt;br /&gt;
--  @local&lt;br /&gt;
function _i18n.handleArgs(msg, args)&lt;br /&gt;
	for i, a in ipairs(args) do&lt;br /&gt;
		msg = (string.gsub(msg, &#039;%$&#039; .. tostring(i), tostring(a)))&lt;br /&gt;
	end&lt;br /&gt;
	return msg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Checks whether a language code is valid.&lt;br /&gt;
--  @function		   _i18n.isValidCode&lt;br /&gt;
--  @param			  {string} code Language code to check.&lt;br /&gt;
--  @return			 {boolean} Whether the language code is valid.&lt;br /&gt;
--  @local&lt;br /&gt;
function _i18n.isValidCode(code)&lt;br /&gt;
	return type(code) == &#039;string&#039; and #mw.language.fetchLanguageName(code) ~= 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Checks whether a message contains unprocessed wikitext.&lt;br /&gt;
--  Used to optimise message getter by not preprocessing pure text.&lt;br /&gt;
--  @function		   _i18n.isWikitext&lt;br /&gt;
--  @param			  {string} msg Message to check.&lt;br /&gt;
--  @return			 {boolean} Whether the message contains wikitext.&lt;br /&gt;
function _i18n.isWikitext(msg)&lt;br /&gt;
	return&lt;br /&gt;
		type(msg) == &#039;string&#039; and&lt;br /&gt;
		(&lt;br /&gt;
			msg:find(&#039;%-%-%-%-&#039;) or&lt;br /&gt;
			msg:find(&#039;%f[^\n%z][;:*#] &#039;) or&lt;br /&gt;
			msg:find(&#039;%f[^\n%z]==* *[^\n|]+ =*=%f[\n]&#039;) or&lt;br /&gt;
			msg:find(&#039;%b&amp;lt;&amp;gt;&#039;) or msg:find(&#039;\&#039;\&#039;&#039;) or&lt;br /&gt;
			msg:find(&#039;%[%b[]%]&#039;) or msg:find(&#039;{%b{}}&#039;)&lt;br /&gt;
		)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- I18n datastore class.&lt;br /&gt;
--  This is used to control language translation and access to individual&lt;br /&gt;
--  messages. The datastore instance provides language and message&lt;br /&gt;
--  getter-setter methods, which can be used to internationalize Lua modules.&lt;br /&gt;
--  The language methods (any ending in `Lang`) are all **chainable**.&lt;br /&gt;
--  @type			Data&lt;br /&gt;
local Data = {}&lt;br /&gt;
Data.__index = Data&lt;br /&gt;
&lt;br /&gt;
--- Datastore message getter utility.&lt;br /&gt;
--  This method returns localized messages from the datastore corresponding&lt;br /&gt;
--  to a `key`. These messages may have `$n` parameters, which can be&lt;br /&gt;
--  replaced by optional argument strings supplied by the `msg` call.&lt;br /&gt;
--  &lt;br /&gt;
--  This function supports [[mw:Extension:Scribunto/Lua reference manual#named_arguments|named&lt;br /&gt;
--  arguments]]. The named argument syntax is more versatile despite its&lt;br /&gt;
--  verbosity; it can be used to select message language &amp;amp; source(s).&lt;br /&gt;
--  @function		   Data:msg&lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--	  ds:msg{&lt;br /&gt;
--		  key = &#039;message-name&#039;,&lt;br /&gt;
--		  lang = &#039;&#039;,&lt;br /&gt;
--		  args = {...},&lt;br /&gt;
--		  sources = {}&lt;br /&gt;
--	  }&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--	  ds:msg(&#039;message-name&#039;, ...)&lt;br /&gt;
--  &lt;br /&gt;
--  @param			  {string|table} opts Message configuration or key.&lt;br /&gt;
--  @param[opt]		 {string} opts.key Message key to return from the&lt;br /&gt;
--					  datastore.&lt;br /&gt;
--  @param[opt]		 {table} opts.args Arguments to substitute into the&lt;br /&gt;
--					  message (`$n`).&lt;br /&gt;
--  @param[opt]		 {table} opts.sources Source names to limit to (see&lt;br /&gt;
--					  `Data:fromSources`).&lt;br /&gt;
--  @param[opt]		 {table} opts.lang Temporary language to use (see&lt;br /&gt;
--					  `Data:inLang`).&lt;br /&gt;
--  @param[opt]		 {string} ... Arguments to substitute into the message&lt;br /&gt;
--					  (`$n`).&lt;br /&gt;
--  @error[115]		 {string} &#039;missing arguments in Data:msg&#039;&lt;br /&gt;
--  @return			 {string} Localised datastore message or `&#039;&amp;lt;key&amp;gt;&#039;`.&lt;br /&gt;
function Data:msg(opts, ...)&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	-- Argument normalization.&lt;br /&gt;
	if not self or not opts then&lt;br /&gt;
		error(&#039;missing arguments in Data:msg&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local key = type(opts) == &#039;table&#039; and opts.key or opts&lt;br /&gt;
	local args = opts.args or {...}&lt;br /&gt;
	-- Configuration parameters.&lt;br /&gt;
	if opts.sources then&lt;br /&gt;
		self:fromSources(unpack(opts.sources))&lt;br /&gt;
	end&lt;br /&gt;
	if opts.lang then&lt;br /&gt;
		self:inLang(opts.lang)&lt;br /&gt;
	end&lt;br /&gt;
	-- Source handling.&lt;br /&gt;
	local source_n = self.tempSources or self._sources&lt;br /&gt;
	local source_i = {}&lt;br /&gt;
	for n, i in pairs(source_n) do&lt;br /&gt;
		source_i[i] = n&lt;br /&gt;
	end&lt;br /&gt;
	self.tempSources = nil&lt;br /&gt;
	-- Language handling.&lt;br /&gt;
	local lang = self.tempLang or self.defaultLang&lt;br /&gt;
	self.tempLang = nil&lt;br /&gt;
	-- Message fetching.&lt;br /&gt;
	local msg&lt;br /&gt;
	for i, messages in ipairs(self._messages) do&lt;br /&gt;
		-- Message data.&lt;br /&gt;
		local msg = (messages[lang] or {})[key]&lt;br /&gt;
		-- Fallback support (experimental).&lt;br /&gt;
		for _, l in ipairs((fallbacks[lang] or {})) do&lt;br /&gt;
			if msg == nil then&lt;br /&gt;
				msg = (messages[l] or {})[key]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		-- Internal fallback to &#039;en&#039;.&lt;br /&gt;
		msg = msg ~= nil and msg or messages.en[key]&lt;br /&gt;
		-- Handling argument substitution from Lua.&lt;br /&gt;
		if msg and source_i[i] and #args &amp;gt; 0 then&lt;br /&gt;
			msg = _i18n.handleArgs(msg, args)&lt;br /&gt;
		end&lt;br /&gt;
		if msg and source_i[i] and lang ~= &#039;qqx&#039; then&lt;br /&gt;
			return frame and _i18n.isWikitext(msg)&lt;br /&gt;
				and frame:preprocess(mw.text.trim(msg))&lt;br /&gt;
				or  mw.text.trim(msg)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;&amp;amp;#x29FC;&#039; .. mw.text.nowiki(key) .. &#039;&amp;amp;#x29FD;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore template parameter getter utility.&lt;br /&gt;
--  This method, given a table of arguments, tries to find a parameter&#039;s&lt;br /&gt;
--  localized name in the datastore and returns its value, or nil if&lt;br /&gt;
--  not present.&lt;br /&gt;
--&lt;br /&gt;
--  This method always uses the wiki&#039;s content language.&lt;br /&gt;
--  @function		   Data:parameter&lt;br /&gt;
--  @param			  {string} parameter Parameter&#039;s key in the datastore&lt;br /&gt;
--  @param			  {table} args Arguments to find the parameter in&lt;br /&gt;
--  @error[176]		 {string} &#039;missing arguments in Data:parameter&#039;&lt;br /&gt;
--  @return			 {string|nil} Parameter&#039;s value or nil if not present&lt;br /&gt;
function Data:parameter(key, args)&lt;br /&gt;
	-- Argument normalization.&lt;br /&gt;
	if not self or not key or not args then&lt;br /&gt;
		error(&#039;missing arguments in Data:parameter&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local contentLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
	-- Message fetching.&lt;br /&gt;
	for i, messages in ipairs(self._messages) do&lt;br /&gt;
		local msg = (messages[contentLang] or {})[key]&lt;br /&gt;
		if msg ~= nil and args[msg] ~= nil then&lt;br /&gt;
			return args[msg]&lt;br /&gt;
		end&lt;br /&gt;
		for _, l in ipairs((fallbacks[contentLang] or {})) do&lt;br /&gt;
			if msg == nil or args[msg] == nil then&lt;br /&gt;
				-- Check next fallback.&lt;br /&gt;
				msg = (messages[l] or {})[key]&lt;br /&gt;
			else&lt;br /&gt;
				-- A localized message was found.&lt;br /&gt;
				return args[msg]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		-- Fallback to English.&lt;br /&gt;
		msg = messages.en[key]&lt;br /&gt;
		if msg ~= nil and args[msg] ~= nil then&lt;br /&gt;
			return args[msg]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore temporary source setter to a specificed subset of datastores.&lt;br /&gt;
--  By default, messages are fetched from the datastore in the same&lt;br /&gt;
--  order of priority as `i18n.loadMessages`.&lt;br /&gt;
--  @function		   Data:fromSource&lt;br /&gt;
--  @param			  {string} ... Source name(s) to use.&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:fromSource(...)&lt;br /&gt;
	local c = select(&#039;#&#039;, ...)&lt;br /&gt;
	if c ~= 0 then&lt;br /&gt;
		self.tempSources = {}&lt;br /&gt;
		for i = 1, c do&lt;br /&gt;
			local n = select(i, ...)&lt;br /&gt;
			if type(n) == &#039;string&#039; and type(self._sources[n]) == &#039;number&#039; then&lt;br /&gt;
				self.tempSources[n] = self._sources[n]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore default language getter.&lt;br /&gt;
--  @function		   Data:getLang&lt;br /&gt;
--  @return			 {string} Default language to serve datastore messages in.&lt;br /&gt;
function Data:getLang()&lt;br /&gt;
	return self.defaultLang&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to `wgUserLanguage`.&lt;br /&gt;
--  @function		   Data:useUserLang&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
--  @note			   Scribunto only registers `wgUserLanguage` when an&lt;br /&gt;
--					  invocation is at the top of the call stack.&lt;br /&gt;
function Data:useUserLang()&lt;br /&gt;
	self.defaultLang = i18n.getLang() or self.defaultLang&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to `wgContentLanguage`.&lt;br /&gt;
--  @function		   Data:useContentLang&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:useContentLang()&lt;br /&gt;
	self.defaultLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to specificed language.&lt;br /&gt;
--  @function		   Data:useLang&lt;br /&gt;
--  @param			  {string} code Language code to use.&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:useLang(code)&lt;br /&gt;
	self.defaultLang = _i18n.isValidCode(code)&lt;br /&gt;
		and code&lt;br /&gt;
		or  self.defaultLang&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to `wgUserLanguage`.&lt;br /&gt;
--  The datastore language reverts to the default language in the next&lt;br /&gt;
--  @{Data:msg} call.&lt;br /&gt;
--  @function		   Data:inUserLang&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:inUserLang()&lt;br /&gt;
	self.tempLang = i18n.getLang() or self.tempLang&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to `wgContentLanguage`.&lt;br /&gt;
--  Only affects the next @{Data:msg} call.&lt;br /&gt;
--  @function		   Data:inContentLang&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:inContentLang()&lt;br /&gt;
	self.tempLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to a specificed language.&lt;br /&gt;
--  Only affects the next @{Data:msg} call.&lt;br /&gt;
--  @function		   Data:inLang&lt;br /&gt;
--  @param			  {string} code Language code to use.&lt;br /&gt;
--  @return			 {Data} Datastore instance.&lt;br /&gt;
function Data:inLang(code)&lt;br /&gt;
	self.tempLang = _i18n.isValidCode(code)&lt;br /&gt;
		and code&lt;br /&gt;
		or  self.tempLang&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--  Package functions.&lt;br /&gt;
&lt;br /&gt;
--- Localized message getter by key.&lt;br /&gt;
--  Can be used to fetch messages in a specific language code through `uselang`&lt;br /&gt;
--  parameter. Extra numbered parameters can be supplied for substitution into&lt;br /&gt;
--  the datastore message.&lt;br /&gt;
--  @function		   i18n.getMsg&lt;br /&gt;
--  @param			  {table} frame Frame table from invocation.&lt;br /&gt;
--  @param			  {table} frame.args Metatable containing arguments.&lt;br /&gt;
--  @param			  {string} frame.args[1] ROOTPAGENAME of i18n submodule.&lt;br /&gt;
--  @param			  {string} frame.args[2] Key of i18n message.&lt;br /&gt;
--  @param[opt]		 {string} frame.args.lang Default language of message.&lt;br /&gt;
--  @error[271]		 {string} &#039;missing arguments in i18n.getMsg&#039;&lt;br /&gt;
--  @return			 {string} I18n message in localised language.&lt;br /&gt;
function i18n.getMsg(frame)&lt;br /&gt;
	if&lt;br /&gt;
		not frame or&lt;br /&gt;
		not frame.args or&lt;br /&gt;
		not frame.args[1] or&lt;br /&gt;
		not frame.args[2]&lt;br /&gt;
	then&lt;br /&gt;
		error(&#039;missing arguments in i18n.getMsg&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local source = frame.args[1]&lt;br /&gt;
	local key = frame.args[2]&lt;br /&gt;
	-- Pass through extra arguments.&lt;br /&gt;
	local repl = {}&lt;br /&gt;
	for i, a in ipairs(frame.args) do&lt;br /&gt;
		if i &amp;gt;= 3 then&lt;br /&gt;
			repl[i-2] = a&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- Load message data.&lt;br /&gt;
	local ds = i18n.loadMessages(source)&lt;br /&gt;
	-- Pass through language argument.&lt;br /&gt;
	ds:inLang(frame.args.uselang)&lt;br /&gt;
	-- Return message.&lt;br /&gt;
	return ds:msg { key = key, args = repl }&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
--- I18n message datastore loader.&lt;br /&gt;
--  @function		   i18n.loadMessages&lt;br /&gt;
--  @param			  {string} ... ROOTPAGENAME/path for target i18n&lt;br /&gt;
--					  submodules.&lt;br /&gt;
--  @error[322]		 {string} &#039;no source supplied to i18n.loadMessages&#039;&lt;br /&gt;
--  @return			 {table} I18n datastore instance.&lt;br /&gt;
--  @usage			  require(&#039;Module:I18n&#039;).loadMessages(&#039;1&#039;, &#039;2&#039;)&lt;br /&gt;
function i18n.loadMessages(...)&lt;br /&gt;
	local ds&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local s = {}&lt;br /&gt;
	for j = 1, select(&#039;#&#039;, ...) do&lt;br /&gt;
		local source = select(j, ...)&lt;br /&gt;
		if type(source) == &#039;string&#039; and source ~= &#039;&#039; then&lt;br /&gt;
			i = i + 1&lt;br /&gt;
			s[source] = i&lt;br /&gt;
			if not ds then&lt;br /&gt;
				-- Instantiate datastore.&lt;br /&gt;
				ds = {}&lt;br /&gt;
				ds._messages = {}&lt;br /&gt;
				-- Set default language.&lt;br /&gt;
				setmetatable(ds, Data)&lt;br /&gt;
				ds:useUserLang()&lt;br /&gt;
			end&lt;br /&gt;
			source = string.gsub(source, &#039;^.&#039;, mw.ustring.upper)&lt;br /&gt;
			local success, messages = pcall(mw.loadData, mw.ustring.find(source, &#039;:&#039;)&lt;br /&gt;
				and source&lt;br /&gt;
				or  &#039;Module:&#039; .. source .. &#039;/i18n&#039;)&lt;br /&gt;
			if success then&lt;br /&gt;
				local msgCopy = {}&lt;br /&gt;
				local langSecond = nil&lt;br /&gt;
				for lang_id, msgtbl in pairs(messages) do&lt;br /&gt;
					if langSecond == nil then&lt;br /&gt;
						if lang_id == &amp;quot;qqq&amp;quot; or fallbacks[lang_id] ~= nil then&lt;br /&gt;
							langSecond = false&lt;br /&gt;
						else&lt;br /&gt;
							langSecond = true&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					for id_lang, msg in pairs(msgtbl) do&lt;br /&gt;
						if langSecond then&lt;br /&gt;
							msgCopy[id_lang] = msgCopy[id_lang] or {}&lt;br /&gt;
							msgCopy[id_lang][lang_id] = msg&lt;br /&gt;
						else&lt;br /&gt;
							msgCopy[lang_id] = msgCopy[lang_id] or {}&lt;br /&gt;
							msgCopy[lang_id][id_lang] = msg&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				ds._messages[i] = msgCopy&lt;br /&gt;
			end&lt;br /&gt;
			local tab = mw.ext.data.get(&#039;I18n/&#039; .. source .. &#039;.tab&#039;, &#039;_&#039;)&lt;br /&gt;
			local T = {}&lt;br /&gt;
			if not success and not tab then error(&amp;quot;i18n for &amp;quot; .. source .. &amp;quot; is missing&amp;quot;) end&lt;br /&gt;
			for _, row in pairs(tab.data) do -- convert the output into a dictionary table&lt;br /&gt;
				local id, t = unpack(row)&lt;br /&gt;
				for lang, msg in pairs(t) do&lt;br /&gt;
					if not T[lang] then T[lang] = {} end&lt;br /&gt;
					T[lang][id] = msg&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not success then&lt;br /&gt;
				ds._messages[i] = T&lt;br /&gt;
			else&lt;br /&gt;
				for lang, msgTbl in pairs(T) do&lt;br /&gt;
					ds._messages[i][lang] = ds._messages[i][lang] or msgTbl&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not ds then&lt;br /&gt;
		error(&#039;no source supplied to i18n.loadMessages&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		-- Attach source index map.&lt;br /&gt;
		ds._sources = s&lt;br /&gt;
		-- Return datastore instance.&lt;br /&gt;
		return ds&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Language code getter.&lt;br /&gt;
--  Can validate a template&#039;s language code through `uselang` parameter.&lt;br /&gt;
--  @function		   i18n.getLang&lt;br /&gt;
--  @return			 {string} Language code.&lt;br /&gt;
function i18n.getLang()&lt;br /&gt;
	local frame = mw.getCurrentFrame() or {}&lt;br /&gt;
	local parentFrame = frame.getParent and frame:getParent() or {}&lt;br /&gt;
&lt;br /&gt;
	local code = mw.language.getContentLanguage():getCode()&lt;br /&gt;
	local subPage = title.subpageText&lt;br /&gt;
&lt;br /&gt;
	-- Language argument test.&lt;br /&gt;
	local langOverride =&lt;br /&gt;
		(frame.args or {}).uselang or&lt;br /&gt;
		(parentFrame.args or {}).uselang&lt;br /&gt;
	if _i18n.isValidCode(langOverride) then&lt;br /&gt;
		code = langOverride&lt;br /&gt;
&lt;br /&gt;
	-- Subpage language test.&lt;br /&gt;
	elseif title.isSubpage and _i18n.isValidCode(subPage) then&lt;br /&gt;
		code = _i18n.isValidCode(subPage) and subPage or code&lt;br /&gt;
&lt;br /&gt;
	-- User language test.&lt;br /&gt;
	elseif parentFrame.preprocess or frame.preprocess then&lt;br /&gt;
		uselang = uselang&lt;br /&gt;
			or  parentFrame.preprocess&lt;br /&gt;
				and parentFrame:preprocess(&#039;{{int:lang}}&#039;)&lt;br /&gt;
				or  frame:preprocess(&#039;{{int:lang}}&#039;)&lt;br /&gt;
		local decodedLang = mw.text.decode(uselang) &lt;br /&gt;
		if decodedLang ~= &#039;&amp;lt;lang&amp;gt;&#039; and decodedLang ~= &#039;⧼lang⧽&#039; then&lt;br /&gt;
			code = decodedLang == &#039;(lang)&#039;&lt;br /&gt;
				and &#039;qqx&#039;&lt;br /&gt;
				or  uselang&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return code&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Credit to http://stackoverflow.com/a/1283608/2644759&lt;br /&gt;
-- cc-by-sa 3.0&lt;br /&gt;
local function tableMerge(t1, t2, overwrite)&lt;br /&gt;
	for k,v in pairs(t2) do&lt;br /&gt;
		if type(v) == &amp;quot;table&amp;quot; and type(t1[k]) == &amp;quot;table&amp;quot; then&lt;br /&gt;
			-- since type(t1[k]) == type(v) == &amp;quot;table&amp;quot;, so t1[k] and v is true&lt;br /&gt;
			tableMerge(t1[k], v, overwrite) -- t2[k] == v&lt;br /&gt;
		else&lt;br /&gt;
			if overwrite or t1[k] == nil then t1[k] = v end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return t1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Given an i18n table instantiates the values (deprecated)&lt;br /&gt;
--  @function i18n.loadI18n&lt;br /&gt;
--  @param {string} name name of module with i18n&lt;br /&gt;
--  @param {table} i18n_arg existing i18n&lt;br /&gt;
function i18n.loadI18n(name, i18n_arg)&lt;br /&gt;
	local exist, res = pcall(require, name)&lt;br /&gt;
	if exist and next(res) ~= nil then&lt;br /&gt;
		if i18n_arg then&lt;br /&gt;
			tableMerge(i18n_arg, res.i18n, true)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Loads an i18n for a specific frame (deprecated)&lt;br /&gt;
--  @function i18n.loadI18nFrame&lt;br /&gt;
--  @param {string} name name of module with i18n&lt;br /&gt;
--  @param {table} i18n_arg existing i18n&lt;br /&gt;
function i18n.loadI18nFrame(frame, i18n_arg)&lt;br /&gt;
	return i18n.loadI18n(frame:getTitle()..&amp;quot;/i18n&amp;quot;, i18n_arg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Wrapper for the module.&lt;br /&gt;
--  @function		   i18n.main&lt;br /&gt;
--  @param			  {table} frame Frame invocation object.&lt;br /&gt;
--  @return			 {string} Module output in template context.&lt;br /&gt;
--  @usage			  {{#invoke:i18n|main}}&lt;br /&gt;
i18n.main = entrypoint(i18n)&lt;br /&gt;
&lt;br /&gt;
return require(&amp;quot;Module:Deprecated&amp;quot;)(i18n, &lt;br /&gt;
	{&lt;br /&gt;
		[&amp;quot;loadI18n&amp;quot;] = {&lt;br /&gt;
			deprecated = true,&lt;br /&gt;
			replacement = &amp;quot;use &amp;lt;code&amp;gt;i18n.loadMessages&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		[&amp;quot;loadI18nFrame&amp;quot;] = {&lt;br /&gt;
			deprecated = true,&lt;br /&gt;
			replacement = &amp;quot;use &amp;lt;code&amp;gt;i18n.loadMessages&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
)&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Wikidata&amp;diff=83</id>
		<title>Module:Wikidata</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Wikidata&amp;diff=83"/>
		<updated>2026-06-22T02:06:24Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;-- vim: set noexpandtab ft=lua ts=4 sw=4: require(&amp;#039;strict&amp;#039;)  local p = {} local debug = false   ------------------------------------------------------------------------------ -- module local variables and functions  local wiki = { 	langcode = mw.language.getContentLanguage().code }  -- internationalisation local i18n = { 	[&amp;quot;errors&amp;quot;] = 	{ 		[&amp;quot;property-not-found&amp;quot;] = &amp;quot;Property not found.&amp;quot;, 		[&amp;quot;entity-not-found&amp;quot;] = &amp;quot;Wikidata entity not found.&amp;quot;, 		[&amp;quot;unknown-claim-type&amp;quot;] = &amp;quot;Un...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- vim: set noexpandtab ft=lua ts=4 sw=4:&lt;br /&gt;
require(&#039;strict&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
local debug = false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
-- module local variables and functions&lt;br /&gt;
&lt;br /&gt;
local wiki =&lt;br /&gt;
{&lt;br /&gt;
	langcode = mw.language.getContentLanguage().code&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- internationalisation&lt;br /&gt;
local i18n =&lt;br /&gt;
{&lt;br /&gt;
	[&amp;quot;errors&amp;quot;] =&lt;br /&gt;
	{&lt;br /&gt;
		[&amp;quot;property-not-found&amp;quot;] = &amp;quot;Property not found.&amp;quot;,&lt;br /&gt;
		[&amp;quot;entity-not-found&amp;quot;] = &amp;quot;Wikidata entity not found.&amp;quot;,&lt;br /&gt;
		[&amp;quot;unknown-claim-type&amp;quot;] = &amp;quot;Unknown claim type.&amp;quot;,&lt;br /&gt;
		[&amp;quot;unknown-entity-type&amp;quot;] = &amp;quot;Unknown entity type.&amp;quot;,&lt;br /&gt;
		[&amp;quot;qualifier-not-found&amp;quot;] = &amp;quot;Qualifier not found.&amp;quot;,&lt;br /&gt;
		[&amp;quot;site-not-found&amp;quot;] = &amp;quot;Wikimedia project not found.&amp;quot;,&lt;br /&gt;
		[&amp;quot;unknown-datetime-format&amp;quot;] = &amp;quot;Unknown datetime format.&amp;quot;,&lt;br /&gt;
		[&amp;quot;local-article-not-found&amp;quot;] = &amp;quot;Article is not yet available in this wiki.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	[&amp;quot;datetime&amp;quot;] =&lt;br /&gt;
	{&lt;br /&gt;
		-- $1 is a placeholder for the actual number&lt;br /&gt;
		[0] = &amp;quot;$1 billion years&amp;quot;,	-- precision: billion years&lt;br /&gt;
		[1] = &amp;quot;$100 million years&amp;quot;,	-- precision: hundred million years&lt;br /&gt;
		[2] = &amp;quot;$10 million years&amp;quot;,	-- precision: ten million years&lt;br /&gt;
		[3] = &amp;quot;$1 million years&amp;quot;,	-- precision: million years&lt;br /&gt;
		[4] = &amp;quot;$100,000 years&amp;quot;,		-- precision: hundred thousand years&lt;br /&gt;
		[5] = &amp;quot;$10,000 years&amp;quot;,		-- precision: ten thousand years&lt;br /&gt;
		[6] = &amp;quot;$1 millennium&amp;quot;,		-- precision: millennium&lt;br /&gt;
		[7] = &amp;quot;$1 century&amp;quot;,			-- precision: century&lt;br /&gt;
		[8] = &amp;quot;$1s&amp;quot;,				-- precision: decade&lt;br /&gt;
		-- the following use the format of #time parser function&lt;br /&gt;
		[9]  = &amp;quot;Y&amp;quot;,					-- precision: year,&lt;br /&gt;
		[10] = &amp;quot;F Y&amp;quot;,				-- precision: month&lt;br /&gt;
		[11] = &amp;quot;F j, Y&amp;quot;,			-- precision: day&lt;br /&gt;
		[12] = &amp;quot;F j, Y ga&amp;quot;,			-- precision: hour&lt;br /&gt;
		[13] = &amp;quot;F j, Y g:ia&amp;quot;,		-- precision: minute&lt;br /&gt;
		[14] = &amp;quot;F j, Y g:i:sa&amp;quot;,		-- precision: second&lt;br /&gt;
		[&amp;quot;beforenow&amp;quot;] = &amp;quot;$1 BCE&amp;quot;,	-- how to format negative numbers for precisions 0 to 5&lt;br /&gt;
		[&amp;quot;afternow&amp;quot;] = &amp;quot;$1 CE&amp;quot;,		-- how to format positive numbers for precisions 0 to 5&lt;br /&gt;
		[&amp;quot;bc&amp;quot;] = &#039;$1 &amp;quot;BCE&amp;quot;&#039;,		-- how print negative years&lt;br /&gt;
		[&amp;quot;ad&amp;quot;] = &amp;quot;$1&amp;quot;,				-- how print positive years&lt;br /&gt;
		-- the following are for function getDateValue() and getQualifierDateValue()&lt;br /&gt;
		[&amp;quot;default-format&amp;quot;] = &amp;quot;dmy&amp;quot;, -- default value of the #3 (getDateValue) or&lt;br /&gt;
									-- #4 (getQualifierDateValue) argument&lt;br /&gt;
		[&amp;quot;default-addon&amp;quot;] = &amp;quot;BC&amp;quot;,	-- default value of the #4 (getDateValue) or&lt;br /&gt;
									-- #5 (getQualifierDateValue) argument&lt;br /&gt;
		[&amp;quot;prefix-addon&amp;quot;] = false,	-- set to true for languages put &amp;quot;BC&amp;quot; in front of the&lt;br /&gt;
									-- datetime string; or the addon will be suffixed&lt;br /&gt;
		[&amp;quot;addon-sep&amp;quot;] = &amp;quot; &amp;quot;,		-- separator between datetime string and addon (or inverse)&lt;br /&gt;
		[&amp;quot;format&amp;quot;] =				-- options of the 3rd argument&lt;br /&gt;
		{&lt;br /&gt;
			[&amp;quot;mdy&amp;quot;] = &amp;quot;F j, Y&amp;quot;,&lt;br /&gt;
			[&amp;quot;my&amp;quot;] = &amp;quot;F Y&amp;quot;,&lt;br /&gt;
			[&amp;quot;y&amp;quot;] = &amp;quot;Y&amp;quot;,&lt;br /&gt;
			[&amp;quot;dmy&amp;quot;] = &amp;quot;j F Y&amp;quot;,&lt;br /&gt;
			[&amp;quot;ymd&amp;quot;] = &amp;quot;Y-m-d&amp;quot;,&lt;br /&gt;
			[&amp;quot;ym&amp;quot;] = &amp;quot;Y-m&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	[&amp;quot;monolingualtext&amp;quot;] = &#039;&amp;lt;span lang=&amp;quot;%language&amp;quot;&amp;gt;%text&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	[&amp;quot;warnDump&amp;quot;] = &amp;quot;[[Category:Called function &#039;Dump&#039; from module Wikidata]]&amp;quot;,&lt;br /&gt;
	[&amp;quot;ordinal&amp;quot;] =&lt;br /&gt;
	{&lt;br /&gt;
		[1] = &amp;quot;st&amp;quot;,&lt;br /&gt;
		[2] = &amp;quot;nd&amp;quot;,&lt;br /&gt;
		[3] = &amp;quot;rd&amp;quot;,&lt;br /&gt;
		[&amp;quot;default&amp;quot;] = &amp;quot;th&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if wiki.langcode ~= &amp;quot;en&amp;quot; then&lt;br /&gt;
	--require(&amp;quot;Module:i18n&amp;quot;).loadI18n(&amp;quot;Module:Wikidata/i18n&amp;quot;, i18n)&lt;br /&gt;
	-- got idea from [[:w:Module:Wd]]&lt;br /&gt;
	local module_title; if ... == nil then&lt;br /&gt;
		module_title = mw.getCurrentFrame():getTitle()&lt;br /&gt;
	else&lt;br /&gt;
		module_title = ...&lt;br /&gt;
	end&lt;br /&gt;
	require(&#039;Module:i18n&#039;).loadI18n(module_title..&#039;/i18n&#039;, i18n)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- this function needs to be internationalised along with the above:&lt;br /&gt;
-- takes cardinal numer as a numeric and returns the ordinal as a string&lt;br /&gt;
-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.&lt;br /&gt;
local function makeOrdinal (cardinal)&lt;br /&gt;
	local ordsuffix = i18n.ordinal.default&lt;br /&gt;
	if cardinal % 10 == 1 then&lt;br /&gt;
		ordsuffix = i18n.ordinal[1]&lt;br /&gt;
	elseif cardinal % 10 == 2 then&lt;br /&gt;
		ordsuffix = i18n.ordinal[2]&lt;br /&gt;
	elseif cardinal % 10 == 3 then&lt;br /&gt;
		ordsuffix = i18n.ordinal[3]&lt;br /&gt;
	end&lt;br /&gt;
	-- In English, 1, 21, 31, etc. use &#039;st&#039;, but 11, 111, etc. use &#039;th&#039;&lt;br /&gt;
	-- similarly for 12 and 13, etc.&lt;br /&gt;
	if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then&lt;br /&gt;
		ordsuffix = i18n.ordinal.default&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(cardinal) .. ordsuffix&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function printError(code)&lt;br /&gt;
	return &#039;&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;&#039; .. (i18n.errors[code] or code) .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
end&lt;br /&gt;
local function parseDateFormat(f, timestamp, addon, prefix_addon, addon_sep) &lt;br /&gt;
	local year_suffix&lt;br /&gt;
	local tstr = &amp;quot;&amp;quot;&lt;br /&gt;
	local lang_obj = mw.language.new(wiki.langcode)&lt;br /&gt;
	local f_parts = mw.text.split(f, &#039;Y&#039;, true)&lt;br /&gt;
	for idx, f_part in pairs(f_parts) do&lt;br /&gt;
		year_suffix = &#039;&#039;&lt;br /&gt;
		if string.match(f_part, &amp;quot;x[mijkot]$&amp;quot;) then&lt;br /&gt;
			-- for non-Gregorian year&lt;br /&gt;
			f_part = f_part .. &#039;Y&#039;&lt;br /&gt;
		elseif idx &amp;lt; #f_parts then&lt;br /&gt;
			-- supress leading zeros in year&lt;br /&gt;
			year_suffix = lang_obj:formatDate(&#039;Y&#039;, timestamp)&lt;br /&gt;
			year_suffix = string.gsub(year_suffix, &#039;^0+&#039;, &#039;&#039;, 1)&lt;br /&gt;
		end&lt;br /&gt;
		tstr = tstr .. lang_obj:formatDate(f_part, timestamp) .. year_suffix&lt;br /&gt;
	end&lt;br /&gt;
	if addon ~= &amp;quot;&amp;quot; and prefix_addon then&lt;br /&gt;
		return addon .. addon_sep .. tstr&lt;br /&gt;
	elseif addon ~= &amp;quot;&amp;quot; then&lt;br /&gt;
		return tstr .. addon_sep .. addon&lt;br /&gt;
	else&lt;br /&gt;
		return tstr&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
local function parseDateValue(timestamp, date_format, date_addon)&lt;br /&gt;
	local prefix_addon = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;prefix-addon&amp;quot;]&lt;br /&gt;
	local addon_sep = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;addon-sep&amp;quot;]&lt;br /&gt;
	local addon = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	-- check for negative date&lt;br /&gt;
	if string.sub(timestamp, 1, 1) == &#039;-&#039; then&lt;br /&gt;
		timestamp = &#039;+&#039; .. string.sub(timestamp, 2)&lt;br /&gt;
		addon = date_addon&lt;br /&gt;
	end&lt;br /&gt;
	local _date_format = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;format&amp;quot;][date_format]&lt;br /&gt;
	if _date_format ~= nil then&lt;br /&gt;
		return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)&lt;br /&gt;
	else&lt;br /&gt;
		return printError(&amp;quot;unknown-datetime-format&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This local function combines the year/month/day/BC/BCE handling of parseDateValue{}&lt;br /&gt;
-- with the millennium/century/decade handling of formatDate()&lt;br /&gt;
local function parseDateFull(timestamp, precision, date_format, date_addon)&lt;br /&gt;
	local prefix_addon = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;prefix-addon&amp;quot;]&lt;br /&gt;
	local addon_sep = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;addon-sep&amp;quot;]&lt;br /&gt;
	local addon = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	-- check for negative date&lt;br /&gt;
	if string.sub(timestamp, 1, 1) == &#039;-&#039; then&lt;br /&gt;
		timestamp = &#039;+&#039; .. string.sub(timestamp, 2)&lt;br /&gt;
		addon = date_addon&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- get the next four characters after the + (should be the year now in all cases)&lt;br /&gt;
	-- ok, so this is dirty, but let&#039;s get it working first&lt;br /&gt;
	local intyear = tonumber(string.sub(timestamp, 2, 5))&lt;br /&gt;
	if intyear == 0 and precision &amp;lt;= 9 then&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- precision is 10000 years or more&lt;br /&gt;
	if precision &amp;lt;= 5 then&lt;br /&gt;
		local factor = 10 ^ ((5 - precision) + 4)&lt;br /&gt;
		local y2 = math.ceil(math.abs(intyear) / factor)&lt;br /&gt;
		local relative = mw.ustring.gsub(i18n.datetime[precision], &amp;quot;$1&amp;quot;, tostring(y2))&lt;br /&gt;
		if addon ~= &amp;quot;&amp;quot; then&lt;br /&gt;
			-- negative date&lt;br /&gt;
			relative = mw.ustring.gsub(i18n.datetime.beforenow, &amp;quot;$1&amp;quot;, relative)&lt;br /&gt;
		else&lt;br /&gt;
			relative = mw.ustring.gsub(i18n.datetime.afternow, &amp;quot;$1&amp;quot;, relative)&lt;br /&gt;
		end&lt;br /&gt;
		return relative&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- precision is decades (8), centuries (7) and millennia (6)&lt;br /&gt;
	local era, card&lt;br /&gt;
	if precision == 6 then&lt;br /&gt;
		card = math.floor((intyear - 1) / 1000) + 1&lt;br /&gt;
		era = mw.ustring.gsub(i18n.datetime[6], &amp;quot;$1&amp;quot;, makeOrdinal(card))&lt;br /&gt;
	end&lt;br /&gt;
	if precision == 7 then&lt;br /&gt;
		card = math.floor((intyear - 1) / 100) + 1&lt;br /&gt;
		era = mw.ustring.gsub(i18n.datetime[7], &amp;quot;$1&amp;quot;, makeOrdinal(card))&lt;br /&gt;
	end&lt;br /&gt;
	if precision == 8 then&lt;br /&gt;
		era = mw.ustring.gsub(i18n.datetime[8], &amp;quot;$1&amp;quot;, tostring(math.floor(math.abs(intyear) / 10) * 10))&lt;br /&gt;
	end&lt;br /&gt;
	if era then&lt;br /&gt;
		if addon ~= &amp;quot;&amp;quot; then&lt;br /&gt;
			era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, &#039;&amp;quot;&#039;, &amp;quot;&amp;quot;), &amp;quot;$1&amp;quot;, era)&lt;br /&gt;
		else&lt;br /&gt;
			era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, &#039;&amp;quot;&#039;, &amp;quot;&amp;quot;), &amp;quot;$1&amp;quot;, era)&lt;br /&gt;
		end&lt;br /&gt;
		return era&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local _date_format = i18n[&amp;quot;datetime&amp;quot;][&amp;quot;format&amp;quot;][date_format]&lt;br /&gt;
	if _date_format ~= nil then&lt;br /&gt;
		-- check for precision is year and override supplied date_format&lt;br /&gt;
		if precision == 9 then&lt;br /&gt;
			_date_format = i18n[&amp;quot;datetime&amp;quot;][9]&lt;br /&gt;
		end&lt;br /&gt;
		return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)&lt;br /&gt;
	else&lt;br /&gt;
		return printError(&amp;quot;unknown-datetime-format&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- the &amp;quot;qualifiers&amp;quot; and &amp;quot;snaks&amp;quot; field have a respective &amp;quot;qualifiers-order&amp;quot; and &amp;quot;snaks-order&amp;quot; field&lt;br /&gt;
-- use these as the second parameter and this function instead of the built-in &amp;quot;pairs&amp;quot; function&lt;br /&gt;
-- to iterate over all qualifiers and snaks in the intended order.&lt;br /&gt;
local function orderedpairs(array, order)&lt;br /&gt;
	if not order then return pairs(array) end&lt;br /&gt;
&lt;br /&gt;
	-- return iterator function&lt;br /&gt;
	local i = 0&lt;br /&gt;
	return function()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if order[i] then&lt;br /&gt;
			return order[i], array[order[i]]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second&lt;br /&gt;
local function normalizeDate(date)&lt;br /&gt;
	date = mw.text.trim(date, &amp;quot;+&amp;quot;)&lt;br /&gt;
	-- extract year&lt;br /&gt;
	local yearstr = mw.ustring.match(date, &amp;quot;^\-?%d+&amp;quot;)&lt;br /&gt;
	local year = tonumber(yearstr)&lt;br /&gt;
	-- remove leading zeros of year&lt;br /&gt;
	return year .. mw.ustring.sub(date, #yearstr + 1), year&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatDate(date, precision, timezone)&lt;br /&gt;
	precision = precision or 11&lt;br /&gt;
	local date, year = normalizeDate(date)&lt;br /&gt;
	if year == 0 and precision &amp;lt;= 9 then return &amp;quot;&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
	-- precision is 10000 years or more&lt;br /&gt;
	if precision &amp;lt;= 5 then&lt;br /&gt;
		local factor = 10 ^ ((5 - precision) + 4)&lt;br /&gt;
		local y2 = math.ceil(math.abs(year) / factor)&lt;br /&gt;
		local relative = mw.ustring.gsub(i18n.datetime[precision], &amp;quot;$1&amp;quot;, tostring(y2))&lt;br /&gt;
		if year &amp;lt; 0 then&lt;br /&gt;
			relative = mw.ustring.gsub(i18n.datetime.beforenow, &amp;quot;$1&amp;quot;, relative)&lt;br /&gt;
		else&lt;br /&gt;
			relative = mw.ustring.gsub(i18n.datetime.afternow, &amp;quot;$1&amp;quot;, relative)&lt;br /&gt;
		end&lt;br /&gt;
		return relative&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- precision is decades, centuries and millennia&lt;br /&gt;
	local era&lt;br /&gt;
	if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], &amp;quot;$1&amp;quot;, tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end&lt;br /&gt;
	if precision == 7 then era = mw.ustring.gsub(i18n.datetime[7], &amp;quot;$1&amp;quot;, tostring(math.floor((math.abs(year) - 1) / 100) + 1)) end&lt;br /&gt;
	if precision == 8 then era = mw.ustring.gsub(i18n.datetime[8], &amp;quot;$1&amp;quot;, tostring(math.floor(math.abs(year) / 10) * 10)) end&lt;br /&gt;
	if era then&lt;br /&gt;
		if year &amp;lt; 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, &#039;&amp;quot;&#039;, &amp;quot;&amp;quot;), &amp;quot;$1&amp;quot;, era)&lt;br /&gt;
		elseif year &amp;gt; 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, &#039;&amp;quot;&#039;, &amp;quot;&amp;quot;), &amp;quot;$1&amp;quot;, era) end&lt;br /&gt;
		return era&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- precision is year&lt;br /&gt;
	if precision == 9 then&lt;br /&gt;
		return year&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- precision is less than years&lt;br /&gt;
	if precision &amp;gt; 9 then&lt;br /&gt;
		--[[ the following code replaces the UTC suffix with the given negated timezone to convert the global time to the given local time&lt;br /&gt;
		timezone = tonumber(timezone)&lt;br /&gt;
		if timezone and timezone ~= 0 then&lt;br /&gt;
			timezone = -timezone&lt;br /&gt;
			timezone = string.format(&amp;quot;%.2d%.2d&amp;quot;, timezone / 60, timezone % 60)&lt;br /&gt;
			if timezone[1] ~= &#039;-&#039; then timezone = &amp;quot;+&amp;quot; .. timezone end&lt;br /&gt;
			date = mw.text.trim(date, &amp;quot;Z&amp;quot;) .. &amp;quot; &amp;quot; .. timezone&lt;br /&gt;
		end&lt;br /&gt;
		]]--&lt;br /&gt;
&lt;br /&gt;
		local formatstr = i18n.datetime[precision]&lt;br /&gt;
		if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], &amp;quot;&amp;quot;)&lt;br /&gt;
		elseif year &amp;lt; 0 then&lt;br /&gt;
			-- Mediawiki formatDate doesn&#039;t support negative years&lt;br /&gt;
			date = mw.ustring.sub(date, 2)&lt;br /&gt;
			formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.bc, &amp;quot;$1&amp;quot;, i18n.datetime[9]))&lt;br /&gt;
		elseif year &amp;gt; 0 and i18n.datetime.ad ~= &amp;quot;$1&amp;quot; then&lt;br /&gt;
			formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.ad, &amp;quot;$1&amp;quot;, i18n.datetime[9]))&lt;br /&gt;
		end&lt;br /&gt;
		return mw.language.new(wiki.langcode):formatDate(formatstr, date)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function printDatavalueEntity(data, parameter)&lt;br /&gt;
	-- data fields: entity-type [string], numeric-id [int, Wikidata id]&lt;br /&gt;
	local id&lt;br /&gt;
&lt;br /&gt;
	if data[&amp;quot;entity-type&amp;quot;] == &amp;quot;item&amp;quot; then id = &amp;quot;Q&amp;quot; .. data[&amp;quot;numeric-id&amp;quot;]&lt;br /&gt;
	elseif data[&amp;quot;entity-type&amp;quot;] == &amp;quot;property&amp;quot; then id = &amp;quot;P&amp;quot; .. data[&amp;quot;numeric-id&amp;quot;]&lt;br /&gt;
	else return printError(&amp;quot;unknown-entity-type&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if parameter then&lt;br /&gt;
		if parameter == &amp;quot;link&amp;quot; then&lt;br /&gt;
			local linkTarget = mw.wikibase.getSitelink(id)&lt;br /&gt;
			local linkName = mw.wikibase.getLabel(id)&lt;br /&gt;
			if linkTarget then&lt;br /&gt;
				-- if there is a local Wikipedia article link to it using the label or the article title&lt;br /&gt;
				return &amp;quot;[[&amp;quot; .. linkTarget .. &amp;quot;|&amp;quot; .. (linkName or linkTarget) .. &amp;quot;]]&amp;quot;&lt;br /&gt;
			else&lt;br /&gt;
				-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label&lt;br /&gt;
				if linkName then return linkName else return &amp;quot;[[:d:&amp;quot; .. id .. &amp;quot;|&amp;quot; .. id .. &amp;quot;]]&amp;quot; end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			return data[parameter]&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return mw.wikibase.getLabel(id) or id&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function printDatavalueTime(data, parameter)&lt;br /&gt;
	-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]&lt;br /&gt;
	--   precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second&lt;br /&gt;
	--   calendarmodel: e.g. http://www.wikidata.org/entity/Q1985727 for the proleptic Gregorian calendar or http://www.wikidata.org/wiki/Q11184 for the Julian calendar]&lt;br /&gt;
	if parameter then&lt;br /&gt;
		if parameter == &amp;quot;calendarmodel&amp;quot; then data.calendarmodel = mw.ustring.match(data.calendarmodel, &amp;quot;Q%d+&amp;quot;) -- extract entity id from the calendar model URI&lt;br /&gt;
		elseif parameter == &amp;quot;time&amp;quot; then data.time = normalizeDate(data.time) end&lt;br /&gt;
		return data[parameter]&lt;br /&gt;
	else&lt;br /&gt;
		return formatDate(data.time, data.precision, data.timezone)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function printDatavalueMonolingualText(data, parameter)&lt;br /&gt;
	-- data fields: language [string], text [string]&lt;br /&gt;
	if parameter then&lt;br /&gt;
		return data[parameter]&lt;br /&gt;
	else&lt;br /&gt;
		local result = mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, &amp;quot;%%language&amp;quot;, data[&amp;quot;language&amp;quot;]), &amp;quot;%%text&amp;quot;, data[&amp;quot;text&amp;quot;])&lt;br /&gt;
		return result&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function findClaims(entity, property)&lt;br /&gt;
	if not property or not entity or not entity.claims then return end&lt;br /&gt;
&lt;br /&gt;
	if mw.ustring.match(property, &amp;quot;^P%d+$&amp;quot;) then&lt;br /&gt;
		-- if the property is given by an id (P..) access the claim list by this id&lt;br /&gt;
		return entity.claims[property]&lt;br /&gt;
	else&lt;br /&gt;
		property = mw.wikibase.resolvePropertyId(property)&lt;br /&gt;
		if not property then return end&lt;br /&gt;
&lt;br /&gt;
		return entity.claims[property]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getSnakValue(snak, parameter)&lt;br /&gt;
	if snak.snaktype == &amp;quot;value&amp;quot; then&lt;br /&gt;
		-- call the respective snak parser&lt;br /&gt;
		if snak.datavalue.type == &amp;quot;string&amp;quot; then return snak.datavalue.value&lt;br /&gt;
		elseif snak.datavalue.type == &amp;quot;globecoordinate&amp;quot; then return printDatavalueCoordinate(snak.datavalue.value, parameter)&lt;br /&gt;
		elseif snak.datavalue.type == &amp;quot;quantity&amp;quot; then return printDatavalueQuantity(snak.datavalue.value, parameter)&lt;br /&gt;
		elseif snak.datavalue.type == &amp;quot;time&amp;quot; then return printDatavalueTime(snak.datavalue.value, parameter)&lt;br /&gt;
		elseif snak.datavalue.type == &amp;quot;wikibase-entityid&amp;quot; then return printDatavalueEntity(snak.datavalue.value, parameter)&lt;br /&gt;
		elseif snak.datavalue.type == &amp;quot;monolingualtext&amp;quot; then return printDatavalueMonolingualText(snak.datavalue.value, parameter)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.wikibase.renderSnak(snak)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getQualifierSnak(claim, qualifierId)&lt;br /&gt;
	-- a &amp;quot;snak&amp;quot; is Wikidata terminology for a typed key/value pair&lt;br /&gt;
	-- a claim consists of a main snak holding the main information of this claim,&lt;br /&gt;
	-- as well as a list of attribute snaks and a list of references snaks&lt;br /&gt;
	if qualifierId then&lt;br /&gt;
		-- search the attribute snak with the given qualifier as key&lt;br /&gt;
		if claim.qualifiers then&lt;br /&gt;
			local qualifier = claim.qualifiers[qualifierId]&lt;br /&gt;
			if qualifier then return qualifier[1] end&lt;br /&gt;
		end&lt;br /&gt;
		return nil, printError(&amp;quot;qualifier-not-found&amp;quot;)&lt;br /&gt;
	else&lt;br /&gt;
		-- otherwise return the main snak&lt;br /&gt;
		return claim.mainsnak&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getValueOfClaim(claim, qualifierId, parameter)&lt;br /&gt;
	local error&lt;br /&gt;
	local snak&lt;br /&gt;
	snak, error = getQualifierSnak(claim, qualifierId)&lt;br /&gt;
	if snak then&lt;br /&gt;
		return getSnakValue(snak, parameter)&lt;br /&gt;
	else&lt;br /&gt;
		return nil, error&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getReferences(frame, claim)&lt;br /&gt;
	local result = &amp;quot;&amp;quot;&lt;br /&gt;
	-- traverse through all references&lt;br /&gt;
	for ref in pairs(claim.references or {}) do&lt;br /&gt;
		local refparts&lt;br /&gt;
		-- traverse through all parts of the current reference&lt;br /&gt;
		for snakkey, snakval in orderedpairs(claim.references[ref].snaks or {}, claim.references[ref][&amp;quot;snaks-order&amp;quot;]) do&lt;br /&gt;
			if refparts then refparts = refparts .. &amp;quot;, &amp;quot; else refparts = &amp;quot;&amp;quot; end&lt;br /&gt;
			-- output the label of the property of the reference part, e.g. &amp;quot;imported from&amp;quot; for P143&lt;br /&gt;
			refparts = refparts .. tostring(mw.wikibase.getLabel(snakkey)) .. &amp;quot;: &amp;quot;&lt;br /&gt;
			-- output all values of this reference part, e.g. &amp;quot;German Wikipedia&amp;quot; and &amp;quot;English Wikipedia&amp;quot; if the referenced claim was imported from both sites&lt;br /&gt;
			for snakidx = 1, #snakval do&lt;br /&gt;
				if snakidx &amp;gt; 1 then refparts = refparts .. &amp;quot;, &amp;quot; end&lt;br /&gt;
				refparts = refparts .. getSnakValue(snakval[snakidx])&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if refparts then result = result .. frame:extensionTag(&amp;quot;ref&amp;quot;, refparts) end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseInput(frame)&lt;br /&gt;
	local qid = frame.args.qid&lt;br /&gt;
	if qid and (#qid == 0) then qid = nil end&lt;br /&gt;
	local propertyID = mw.text.trim(frame.args[1] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local input_parm = mw.text.trim(frame.args[2] or &amp;quot;&amp;quot;)&lt;br /&gt;
	if input_parm ~= &amp;quot;FETCH_WIKIDATA&amp;quot; then&lt;br /&gt;
		return false, input_parm, nil, nil&lt;br /&gt;
	end&lt;br /&gt;
	local entity = mw.wikibase.getEntity(qid)&lt;br /&gt;
	local claims&lt;br /&gt;
	if entity and entity.claims then&lt;br /&gt;
		claims = entity.claims[propertyID]&lt;br /&gt;
		if not claims then&lt;br /&gt;
			return false, &amp;quot;&amp;quot;, nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return false, &amp;quot;&amp;quot;, nil, nil&lt;br /&gt;
	end&lt;br /&gt;
	return true, entity, claims, propertyID&lt;br /&gt;
end&lt;br /&gt;
local function isType(claims, type)&lt;br /&gt;
	return claims[1] and claims[1].mainsnak.snaktype == &amp;quot;value&amp;quot; and claims[1].mainsnak.datavalue.type == type&lt;br /&gt;
end&lt;br /&gt;
local function getValue(entity, claims, propertyID, delim, labelHook) &lt;br /&gt;
	if labelHook == nil then&lt;br /&gt;
		labelHook = function (qnumber)&lt;br /&gt;
			return nil;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if isType(claims, &amp;quot;wikibase-entityid&amp;quot;) then&lt;br /&gt;
		local out = {}&lt;br /&gt;
		for k, v in pairs(claims) do&lt;br /&gt;
			local qnumber = &amp;quot;Q&amp;quot; .. v.mainsnak.datavalue.value[&amp;quot;numeric-id&amp;quot;]&lt;br /&gt;
			local sitelink = mw.wikibase.getSitelink(qnumber)&lt;br /&gt;
			local label = labelHook(qnumber) or mw.wikibase.getLabel(qnumber) or qnumber&lt;br /&gt;
			if sitelink then&lt;br /&gt;
				out[#out + 1] = &amp;quot;[[&amp;quot; .. sitelink .. &amp;quot;|&amp;quot; .. label .. &amp;quot;]]&amp;quot;&lt;br /&gt;
			else&lt;br /&gt;
				out[#out + 1] = &amp;quot;[[:d:&amp;quot; .. qnumber .. &amp;quot;|&amp;quot; .. label .. &amp;quot;]]&amp;lt;abbr title=&#039;&amp;quot; .. i18n[&amp;quot;errors&amp;quot;][&amp;quot;local-article-not-found&amp;quot;] .. &amp;quot;&#039;&amp;gt;[*]&amp;lt;/abbr&amp;gt;&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return table.concat(out, delim)&lt;br /&gt;
	else&lt;br /&gt;
		-- just return best values&lt;br /&gt;
		return entity:formatPropertyValues(propertyID).value&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------&lt;br /&gt;
-- module global functions&lt;br /&gt;
&lt;br /&gt;
if debug then&lt;br /&gt;
	function p.inspectI18n(frame)&lt;br /&gt;
		local val = i18n&lt;br /&gt;
		for _, key in pairs(frame.args) do&lt;br /&gt;
			key = mw.text.trim(key)&lt;br /&gt;
			val = val[key]&lt;br /&gt;
		end&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.descriptionIn(frame)&lt;br /&gt;
	local langcode = frame.args[1]&lt;br /&gt;
	local id = frame.args[2]&lt;br /&gt;
	-- return description of a Wikidata entity in the given language or the default language of this Wikipedia site&lt;br /&gt;
	return mw.wikibase.getEntity(id):getDescription(langcode or wiki.langcode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.labelIn(frame)&lt;br /&gt;
	local langcode = frame.args[1]&lt;br /&gt;
	local id = frame.args[2]&lt;br /&gt;
	-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site&lt;br /&gt;
	return mw.wikibase.getEntity(id):getLabel(langcode or wiki.langcode)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get a value, or a comma separated list of them if multiple values exist&lt;br /&gt;
p.getValue = function(frame)&lt;br /&gt;
	local delimdefault = &amp;quot;, &amp;quot; -- **internationalise later**&lt;br /&gt;
	local delim = frame.args.delimiter or &amp;quot;&amp;quot;&lt;br /&gt;
	delim = string.gsub(delim, &#039;&amp;quot;&#039;, &#039;&#039;)&lt;br /&gt;
	if #delim == 0 then&lt;br /&gt;
		delim = delimdefault&lt;br /&gt;
	end&lt;br /&gt;
	local go, errorOrentity, claims, propertyID = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	return getValue(errorOrentity, claims, propertyID, delim)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Same as above, but uses the short name property for label if available.&lt;br /&gt;
p.getValueShortName = function(frame)&lt;br /&gt;
	local go, errorOrentity, claims, propertyID = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	-- if wiki-linked value output as link if possible&lt;br /&gt;
	local function labelHook (qnumber)&lt;br /&gt;
		local label&lt;br /&gt;
		local claimEntity = mw.wikibase.getEntity(qnumber)&lt;br /&gt;
		if claimEntity ~= nil then&lt;br /&gt;
			if claimEntity.claims.P1813 then&lt;br /&gt;
				for k2, v2 in pairs(claimEntity.claims.P1813) do&lt;br /&gt;
					if v2.mainsnak.datavalue.value.language == &amp;quot;en&amp;quot; then&lt;br /&gt;
						label = v2.mainsnak.datavalue.value.text&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if label == nil or label == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
		return label&lt;br /&gt;
	end&lt;br /&gt;
	return getValue(errorOrentity, claims, propertyID, &amp;quot;, &amp;quot;, labelHook);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get a value, or a comma separated list of them if multiple values exist&lt;br /&gt;
-- from an arbitrary entry by using its QID.&lt;br /&gt;
-- Use : {{#invoke:Wikidata|getValueFromID|&amp;lt;ID&amp;gt;|&amp;lt;Property&amp;gt;|FETCH_WIKIDATA}}&lt;br /&gt;
-- E.g.: {{#invoke:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}} - to fetch value of &#039;spouse&#039; (P26) from &#039;Richard Burton&#039; (Q151973)&lt;br /&gt;
-- Please use sparingly - this is an *expensive call*.&lt;br /&gt;
p.getValueFromID = function(frame)&lt;br /&gt;
	local itemID = mw.text.trim(frame.args[1] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local propertyID = mw.text.trim(frame.args[2] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local input_parm = mw.text.trim(frame.args[3] or &amp;quot;&amp;quot;)&lt;br /&gt;
	if input_parm == &amp;quot;FETCH_WIKIDATA&amp;quot; then&lt;br /&gt;
		local entity = mw.wikibase.getEntity(itemID)&lt;br /&gt;
		local claims&lt;br /&gt;
		if entity and entity.claims then&lt;br /&gt;
			claims = entity.claims[propertyID]&lt;br /&gt;
		end&lt;br /&gt;
		if claims then&lt;br /&gt;
			return getValue(entity, claims, propertyID, &amp;quot;, &amp;quot;)&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;quot;&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return input_parm&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
local function getQualifier(frame, outputHook) &lt;br /&gt;
	local propertyID = mw.text.trim(frame.args[1] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local qualifierID = mw.text.trim(frame.args[2] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local input_parm = mw.text.trim(frame.args[3] or &amp;quot;&amp;quot;)&lt;br /&gt;
	if input_parm == &amp;quot;FETCH_WIKIDATA&amp;quot; then&lt;br /&gt;
		local entity = mw.wikibase.getEntity()&lt;br /&gt;
		if entity.claims[propertyID] ~= nil then&lt;br /&gt;
			local out = {}&lt;br /&gt;
			for k, v in pairs(entity.claims[propertyID]) do&lt;br /&gt;
				for k2, v2 in pairs(v.qualifiers[qualifierID]) do&lt;br /&gt;
					if v2.snaktype == &#039;value&#039; then&lt;br /&gt;
						out[#out + 1] = outputHook(v2);&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return table.concat(out, &amp;quot;, &amp;quot;), true&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;quot;&amp;quot;, false&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return input_parm, false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
p.getQualifierValue = function(frame)&lt;br /&gt;
	local function outputValue(value)&lt;br /&gt;
		local qnumber = &amp;quot;Q&amp;quot; .. value.datavalue.value[&amp;quot;numeric-id&amp;quot;]&lt;br /&gt;
		if (mw.wikibase.getSitelink(qnumber)) then&lt;br /&gt;
			return &amp;quot;[[&amp;quot; .. mw.wikibase.getSitelink(qnumber) .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
			return &amp;quot;[[:d:&amp;quot; .. qnumber .. &amp;quot;|&amp;quot; ..qnumber .. &amp;quot;]]&amp;lt;abbr title=&#039;&amp;quot; .. i18n[&amp;quot;errors&amp;quot;][&amp;quot;local-article-not-found&amp;quot;] .. &amp;quot;&#039;&amp;gt;[*]&amp;lt;/abbr&amp;gt;&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return (getQualifier(frame, outputValue))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get a value like &#039;male&#039; (for property p21) which won&#039;t be linked and numbers without the thousand separators&lt;br /&gt;
p.getRawValue = function(frame)&lt;br /&gt;
	local go, errorOrentity, claims, propertyID = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value&lt;br /&gt;
	-- if number type: remove thousand separators, bounds and units&lt;br /&gt;
	if isType(claims, &amp;quot;quantity&amp;quot;) then&lt;br /&gt;
		result = mw.ustring.gsub(result, &amp;quot;(%d),(%d)&amp;quot;, &amp;quot;%1%2&amp;quot;)&lt;br /&gt;
		result = mw.ustring.gsub(result, &amp;quot;(%d)±.*&amp;quot;, &amp;quot;%1&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get the unit name for the numeric value returned by getRawValue&lt;br /&gt;
p.getUnits = function(frame)&lt;br /&gt;
	local go, errorOrentity, claims, propertyID = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value&lt;br /&gt;
	if isType(claims, &amp;quot;quantity&amp;quot;) then&lt;br /&gt;
		result = mw.ustring.sub(result, mw.ustring.find(result, &amp;quot; &amp;quot;)+1, -1)&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get the unit&#039;s QID to use with the numeric value returned by getRawValue&lt;br /&gt;
p.getUnitID = function(frame)&lt;br /&gt;
	local go, errorOrentity, claims = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	local result&lt;br /&gt;
	if isType(claims, &amp;quot;quantity&amp;quot;) then&lt;br /&gt;
		-- get the url for the unit entry on Wikidata:&lt;br /&gt;
		result = claims[1].mainsnak.datavalue.value.unit&lt;br /&gt;
		-- and just reurn the last bit from &amp;quot;Q&amp;quot; to the end (which is the QID):&lt;br /&gt;
		result = mw.ustring.sub(result, mw.ustring.find(result, &amp;quot;Q&amp;quot;), -1)&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.getRawQualifierValue = function(frame)&lt;br /&gt;
	local function outputHook(value)&lt;br /&gt;
		if value.datavalue.value[&amp;quot;numeric-id&amp;quot;] then&lt;br /&gt;
			return mw.wikibase.getLabel(&amp;quot;Q&amp;quot; .. value.datavalue.value[&amp;quot;numeric-id&amp;quot;])&lt;br /&gt;
		else&lt;br /&gt;
			return value.datavalue.value&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local ret, gotData = getQualifier(frame, outputHook)&lt;br /&gt;
	if gotData then&lt;br /&gt;
		ret = string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2)&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get a date value for date_of_birth (P569), etc. which won&#039;t be linked&lt;br /&gt;
-- Dates and times are stored in ISO 8601 format (sort of).&lt;br /&gt;
-- At present the local formatDate(date, precision, timezone) function doesn&#039;t handle timezone&lt;br /&gt;
-- So I&#039;ll just supply &amp;quot;Z&amp;quot; in the call to formatDate below:&lt;br /&gt;
p.getDateValue = function(frame)&lt;br /&gt;
	local date_format = mw.text.trim(frame.args[3] or i18n[&amp;quot;datetime&amp;quot;][&amp;quot;default-format&amp;quot;])&lt;br /&gt;
	local date_addon = mw.text.trim(frame.args[4] or i18n[&amp;quot;datetime&amp;quot;][&amp;quot;default-addon&amp;quot;])&lt;br /&gt;
	local go, errorOrentity, claims = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	local out = {}&lt;br /&gt;
	for k, v in pairs(claims) do&lt;br /&gt;
		if v.mainsnak.datavalue.type == &#039;time&#039; then&lt;br /&gt;
			local timestamp = v.mainsnak.datavalue.value.time&lt;br /&gt;
			local dateprecision = v.mainsnak.datavalue.value.precision&lt;br /&gt;
			-- A year can be stored like this: &amp;quot;+1872-00-00T00:00:00Z&amp;quot;,&lt;br /&gt;
			-- which is processed here as if it were the day before &amp;quot;+1872-01-01T00:00:00Z&amp;quot;,&lt;br /&gt;
			-- and that&#039;s the last day of 1871, so the year is wrong.&lt;br /&gt;
			-- So fix the month 0, day 0 timestamp to become 1 January instead:&lt;br /&gt;
			timestamp = timestamp:gsub(&amp;quot;%-00%-00T&amp;quot;, &amp;quot;-01-01T&amp;quot;)&lt;br /&gt;
			out[#out + 1] = parseDateFull(timestamp, dateprecision, date_format, date_addon)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(out, &amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
p.getQualifierDateValue = function(frame)&lt;br /&gt;
	local date_format = mw.text.trim(frame.args[4] or i18n[&amp;quot;datetime&amp;quot;][&amp;quot;default-format&amp;quot;])&lt;br /&gt;
	local date_addon = mw.text.trim(frame.args[5] or i18n[&amp;quot;datetime&amp;quot;][&amp;quot;default-addon&amp;quot;])&lt;br /&gt;
	local function outputHook(value)&lt;br /&gt;
		local timestamp = value.datavalue.value.time&lt;br /&gt;
		return parseDateValue(timestamp, date_format, date_addon)&lt;br /&gt;
	end&lt;br /&gt;
	return (getQualifier(frame, outputHook))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to fetch all of the images with a particular property, e.g. image (P18), Gene Atlas Image (P692), etc.&lt;br /&gt;
-- Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=frameless)&lt;br /&gt;
-- It will return a standard wiki-markup [[File:Filename | size]] for each image with a selectable size and separator (which may be html)&lt;br /&gt;
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA}}&lt;br /&gt;
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA|&amp;lt;br&amp;gt;|250px}}&lt;br /&gt;
-- If a property is chosen that is not of type &amp;quot;commonsMedia&amp;quot;, it will return empty text.&lt;br /&gt;
p.getImages = function(frame)&lt;br /&gt;
	local sep = mw.text.trim(frame.args[3] or &amp;quot; &amp;quot;)&lt;br /&gt;
	local imgsize = mw.text.trim(frame.args[4] or &amp;quot;frameless&amp;quot;)&lt;br /&gt;
	local go, errorOrentity, claims = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	if (claims[1] and claims[1].mainsnak.datatype == &amp;quot;commonsMedia&amp;quot;) then&lt;br /&gt;
		local out = {}&lt;br /&gt;
		for k, v in pairs(claims) do&lt;br /&gt;
			local filename = v.mainsnak.datavalue.value&lt;br /&gt;
			out[#out + 1] = &amp;quot;[[File:&amp;quot; .. filename .. &amp;quot;|&amp;quot; .. imgsize .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		return table.concat(out, sep)&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like &#039;A01.1.00.005&#039; (property P1323)&lt;br /&gt;
-- which are then linked to https://ifaa.unifr.ch/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm&lt;br /&gt;
-- uses the newer mw.wikibase calls instead of directly using the snaks&lt;br /&gt;
-- formatPropertyValues returns a table with the P1323 values concatenated with &amp;quot;, &amp;quot; so we have to split them out into a table in order to construct the return string&lt;br /&gt;
p.getTAValue = function(frame)&lt;br /&gt;
	local ent = mw.wikibase.getEntity()&lt;br /&gt;
	local props = ent:formatPropertyValues(&#039;P1323&#039;)&lt;br /&gt;
	local out = {}&lt;br /&gt;
	local t = {}&lt;br /&gt;
	for k, v in pairs(props) do&lt;br /&gt;
		if k == &#039;value&#039; then&lt;br /&gt;
			t = mw.text.split( v, &amp;quot;, &amp;quot;)&lt;br /&gt;
			for k2, v2 in pairs(t) do&lt;br /&gt;
				out[#out + 1] = &amp;quot;[https://ifaa.unifr.ch/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/&amp;quot; .. string.sub(v2, 2) .. &amp;quot;%20Entity%20TA98%20EN.htm &amp;quot; .. v2 .. &amp;quot;]&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local ret = table.concat(out, &amp;quot;&amp;lt;br&amp;gt; &amp;quot;)&lt;br /&gt;
	if #ret == 0 then&lt;br /&gt;
		ret = &amp;quot;Invalid TA&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
This is used to return an image legend from Wikidata&lt;br /&gt;
image is property P18&lt;br /&gt;
image legend is property P2096&lt;br /&gt;
&lt;br /&gt;
Call as {{#invoke:Wikidata |getImageLegend | &amp;lt;PARAMETER&amp;gt; | lang=&amp;lt;ISO-639code&amp;gt; |id=&amp;lt;QID&amp;gt;}}&lt;br /&gt;
Returns PARAMETER, unless it is equal to &amp;quot;FETCH_WIKIDATA&amp;quot;, from Item QID (expensive call)&lt;br /&gt;
If QID is omitted or blank, the current article is used (not an expensive call)&lt;br /&gt;
If lang is omitted, it uses the local wiki language, otherwise it uses the provided ISO-639 language code&lt;br /&gt;
ISO-639: https://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqisocodes.html#wp1252447&lt;br /&gt;
&lt;br /&gt;
Ranks are: &#039;preferred&#039; &amp;gt; &#039;normal&#039;&lt;br /&gt;
This returns the label from the first image with &#039;preferred&#039; rank&lt;br /&gt;
Or the label from the first image with &#039;normal&#039; rank if preferred returns nothing&lt;br /&gt;
Ranks: https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
p.getImageLegend = function(frame)&lt;br /&gt;
	-- look for named parameter id; if it&#039;s blank make it nil&lt;br /&gt;
	local id = frame.args.id&lt;br /&gt;
	if id and (#id == 0) then&lt;br /&gt;
		id = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- look for named parameter lang&lt;br /&gt;
	-- it should contain a two-character ISO-639 language code&lt;br /&gt;
	-- if it&#039;s blank fetch the language of the local wiki&lt;br /&gt;
	local lang = frame.args.lang&lt;br /&gt;
	if (not lang) or (#lang &amp;lt; 2) then&lt;br /&gt;
		lang = mw.language.getContentLanguage().code&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- first unnamed parameter is the local parameter, if supplied&lt;br /&gt;
	local input_parm = mw.text.trim(frame.args[1] or &amp;quot;&amp;quot;)&lt;br /&gt;
	if input_parm == &amp;quot;FETCH_WIKIDATA&amp;quot; then&lt;br /&gt;
		local ent = mw.wikibase.getEntity(id)&lt;br /&gt;
		local imgs&lt;br /&gt;
		if ent and ent.claims then&lt;br /&gt;
			imgs = ent.claims.P18&lt;br /&gt;
		end&lt;br /&gt;
		local imglbl&lt;br /&gt;
		if imgs then&lt;br /&gt;
			-- look for an image with &#039;preferred&#039; rank&lt;br /&gt;
			for k1, v1 in pairs(imgs) do&lt;br /&gt;
				if v1.rank == &amp;quot;preferred&amp;quot; and v1.qualifiers and v1.qualifiers.P2096 then&lt;br /&gt;
					local imglbls = v1.qualifiers.P2096&lt;br /&gt;
					for k2, v2 in pairs(imglbls) do&lt;br /&gt;
						if v2.datavalue.value.language == lang then&lt;br /&gt;
							imglbl = v2.datavalue.value.text&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			-- if we don&#039;t find one, look for an image with &#039;normal&#039; rank&lt;br /&gt;
			if (not imglbl) then&lt;br /&gt;
				for k1, v1 in pairs(imgs) do&lt;br /&gt;
					if v1.rank == &amp;quot;normal&amp;quot; and v1.qualifiers and v1.qualifiers.P2096 then&lt;br /&gt;
						local imglbls = v1.qualifiers.P2096&lt;br /&gt;
						for k2, v2 in pairs(imglbls) do&lt;br /&gt;
							if v2.datavalue.value.language == lang then&lt;br /&gt;
								imglbl = v2.datavalue.value.text&lt;br /&gt;
								break&lt;br /&gt;
							end&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return imglbl&lt;br /&gt;
	else&lt;br /&gt;
		return input_parm&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This is used to get the QIDs of all of the values of a property, as a comma separated list if multiple values exist&lt;br /&gt;
-- Usage: {{#invoke:Wikidata |getPropertyIDs |&amp;lt;PropertyID&amp;gt; |FETCH_WIKIDATA}}&lt;br /&gt;
-- Usage: {{#invoke:Wikidata |getPropertyIDs |&amp;lt;PropertyID&amp;gt; |&amp;lt;InputParameter&amp;gt; |qid=&amp;lt;QID&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
p.getPropertyIDs = function(frame)&lt;br /&gt;
	local go, errorOrentity, propclaims = parseInput(frame)&lt;br /&gt;
	if not go then&lt;br /&gt;
		return errorOrentity&lt;br /&gt;
	end&lt;br /&gt;
	local entity = errorOrentity&lt;br /&gt;
	-- if wiki-linked value collect the QID in a table&lt;br /&gt;
	if (propclaims[1] and propclaims[1].mainsnak.snaktype == &amp;quot;value&amp;quot; and propclaims[1].mainsnak.datavalue.type == &amp;quot;wikibase-entityid&amp;quot;) then&lt;br /&gt;
		local out = {}&lt;br /&gt;
		for k, v in pairs(propclaims) do&lt;br /&gt;
			out[#out + 1] = &amp;quot;Q&amp;quot; .. v.mainsnak.datavalue.value[&amp;quot;numeric-id&amp;quot;]&lt;br /&gt;
		end&lt;br /&gt;
		return table.concat(out, &amp;quot;, &amp;quot;)&lt;br /&gt;
	else&lt;br /&gt;
		-- not a wikibase-entityid, so return empty&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata&lt;br /&gt;
function p.pageId(frame)&lt;br /&gt;
	return mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.claim(frame)&lt;br /&gt;
	local property = frame.args[1] or &amp;quot;&amp;quot;&lt;br /&gt;
	local id = frame.args[&amp;quot;id&amp;quot;]&lt;br /&gt;
	local qualifierId = frame.args[&amp;quot;qualifier&amp;quot;]&lt;br /&gt;
	local parameter = frame.args[&amp;quot;parameter&amp;quot;]&lt;br /&gt;
	local list = frame.args[&amp;quot;list&amp;quot;]&lt;br /&gt;
	local references = frame.args[&amp;quot;references&amp;quot;]&lt;br /&gt;
	local showerrors = frame.args[&amp;quot;showerrors&amp;quot;]&lt;br /&gt;
	local default = frame.args[&amp;quot;default&amp;quot;]&lt;br /&gt;
	if default then showerrors = nil end&lt;br /&gt;
&lt;br /&gt;
	-- get wikidata entity&lt;br /&gt;
	local entity = mw.wikibase.getEntity(id)&lt;br /&gt;
	if not entity then&lt;br /&gt;
		if showerrors then return printError(&amp;quot;entity-not-found&amp;quot;) else return default end&lt;br /&gt;
	end&lt;br /&gt;
	-- fetch the first claim of satisfying the given property&lt;br /&gt;
	local claims = findClaims(entity, property)&lt;br /&gt;
	if not claims or not claims[1] then&lt;br /&gt;
		if showerrors then return printError(&amp;quot;property-not-found&amp;quot;) else return default end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- get initial sort indices&lt;br /&gt;
	local sortindices = {}&lt;br /&gt;
	for idx in pairs(claims) do&lt;br /&gt;
		sortindices[#sortindices + 1] = idx&lt;br /&gt;
	end&lt;br /&gt;
	-- sort by claim rank&lt;br /&gt;
	local comparator = function(a, b)&lt;br /&gt;
		local rankmap = { deprecated = 2, normal = 1, preferred = 0 }&lt;br /&gt;
		local ranka = rankmap[claims[a].rank or &amp;quot;normal&amp;quot;] .. string.format(&amp;quot;%08d&amp;quot;, a)&lt;br /&gt;
		local rankb = rankmap[claims[b].rank or &amp;quot;normal&amp;quot;] .. string.format(&amp;quot;%08d&amp;quot;, b)&lt;br /&gt;
		return ranka &amp;lt; rankb&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(sortindices, comparator)&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
	local error&lt;br /&gt;
	if list then&lt;br /&gt;
		local value&lt;br /&gt;
		-- iterate over all elements and return their value (if existing)&lt;br /&gt;
		result = {}&lt;br /&gt;
		for idx in pairs(claims) do&lt;br /&gt;
			local claim = claims[sortindices[idx]]&lt;br /&gt;
			value, error = getValueOfClaim(claim, qualifierId, parameter)&lt;br /&gt;
			if not value and showerrors then value = error end&lt;br /&gt;
			if value and references then value = value .. getReferences(frame, claim) end&lt;br /&gt;
			result[#result + 1] = value&lt;br /&gt;
		end&lt;br /&gt;
		result = table.concat(result, list)&lt;br /&gt;
	else&lt;br /&gt;
		-- return first element&lt;br /&gt;
		local claim = claims[sortindices[1]]&lt;br /&gt;
		result, error = getValueOfClaim(claim, qualifierId, parameter)&lt;br /&gt;
		if result and references then result = result .. getReferences(frame, claim) end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if result then return result else&lt;br /&gt;
		if showerrors then return error else return default end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- look into entity object&lt;br /&gt;
function p.ViewSomething(frame)&lt;br /&gt;
	local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()&lt;br /&gt;
	local id = f.args.id&lt;br /&gt;
	if id and (#id == 0) then&lt;br /&gt;
		id = nil&lt;br /&gt;
	end&lt;br /&gt;
	local data = mw.wikibase.getEntity(id)&lt;br /&gt;
	if not data then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while true do&lt;br /&gt;
		local index = f.args[i]&lt;br /&gt;
		if not index then&lt;br /&gt;
			if type(data) == &amp;quot;table&amp;quot; then&lt;br /&gt;
				return mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)&lt;br /&gt;
			else&lt;br /&gt;
				return tostring(data)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		data = data[index] or data[tonumber(index)]&lt;br /&gt;
		if not data then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- getting sitelink of a given wiki&lt;br /&gt;
-- get sitelink of current item if qid not supplied&lt;br /&gt;
function p.getSiteLink(frame)&lt;br /&gt;
	local qid = frame.args.qid&lt;br /&gt;
	if qid == &amp;quot;&amp;quot; then qid = nil end&lt;br /&gt;
	local f = mw.text.trim( frame.args[1] or &amp;quot;&amp;quot;)&lt;br /&gt;
	local entity = mw.wikibase.getEntity(qid)&lt;br /&gt;
	if not entity then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local link = entity:getSitelink( f )&lt;br /&gt;
	if not link then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	return link&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.Dump(frame)&lt;br /&gt;
	local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()&lt;br /&gt;
	local data = mw.wikibase.getEntity(f.args.id)&lt;br /&gt;
	if not data then&lt;br /&gt;
		return i18n.warnDump&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while true do&lt;br /&gt;
		local index = f.args[i]&lt;br /&gt;
		if not index then&lt;br /&gt;
			return &amp;quot;&amp;lt;pre&amp;gt;&amp;quot;..mw.dumpObject(data)..&amp;quot;&amp;lt;/pre&amp;gt;&amp;quot;.. i18n.warnDump&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		data = data[index] or data[tonumber(index)]&lt;br /&gt;
		if not data then&lt;br /&gt;
			return i18n.warnDump&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Endplainlist&amp;diff=82</id>
		<title>Template:Endplainlist</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Endplainlist&amp;diff=82"/>
		<updated>2026-06-22T02:05:46Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{documentation|Template:Plainlist/doc}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation|Template:Plainlist/doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Plainlist&amp;diff=81</id>
		<title>Template:Plainlist</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Plainlist&amp;diff=81"/>
		<updated>2026-06-22T02:05:28Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;lt;templatestyles src=&amp;quot;Plainlist/styles.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;plainlist {{{class|}}}&amp;quot; {{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{style|}}}{{{indent|}}}|style=&amp;quot;{{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{indent|}}}|margin-left: {{safesubst&amp;lt;noinclude /&amp;gt;:#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}&amp;quot;}}&amp;gt;{{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{1|}}}| {{{1}}} &amp;lt;/div&amp;gt;}}{{#invoke:Check for unknown parameters|check|unknown={{main other|_VALUE_{{PAGENAME}}}}|prev...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Plainlist/styles.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;plainlist {{{class|}}}&amp;quot; {{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{style|}}}{{{indent|}}}|style=&amp;quot;{{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{indent|}}}|margin-left: {{safesubst&amp;lt;noinclude /&amp;gt;:#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}&amp;quot;}}&amp;gt;{{safesubst&amp;lt;noinclude /&amp;gt;:#if:{{{1|}}}|&lt;br /&gt;
{{{1}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using plainlist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Plainlist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| class | style | indent | 1 }}&amp;lt;noinclude&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Infobox/Columns&amp;diff=80</id>
		<title>Template:Infobox/Columns</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Infobox/Columns&amp;diff=80"/>
		<updated>2026-06-22T02:05:14Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;{{#if:{{{1|}}}{{{2|}}}{{{3|}}}{{{4|}}}|&amp;lt;templatestyles src=&amp;quot;Infobox/Columns/styles.css&amp;quot;/&amp;gt;{{plainlist|class=infobox-columns infobox-columns-{{#if:{{{4|}}}|4|{{#if:{{{3|}}}|3|2}}}} {{#if:{{{centered text|}}}||infobox-columns-text-left}}}} &amp;lt;div&amp;gt; {{{1|}}} &amp;lt;/div&amp;gt; &amp;lt;div&amp;gt; {{{2|}}} &amp;lt;/div&amp;gt;&amp;lt;!--  --&amp;gt;{{#if:{{{3|}}}|&amp;lt;div&amp;gt; {{{3}}} &amp;lt;/div&amp;gt;}}&amp;lt;!--  --&amp;gt;{{#if:{{{4|}}}|&amp;lt;div&amp;gt; {{{4}}} &amp;lt;/div&amp;gt;}} {{endplainlist}}}}&amp;lt;noinclude&amp;gt; {{Documentation}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{1|}}}{{{2|}}}{{{3|}}}{{{4|}}}|&amp;lt;templatestyles src=&amp;quot;Infobox/Columns/styles.css&amp;quot;/&amp;gt;{{plainlist|class=infobox-columns infobox-columns-{{#if:{{{4|}}}|4|{{#if:{{{3|}}}|3|2}}}} {{#if:{{{centered text|}}}||infobox-columns-text-left}}}}&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
{{{1|}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
{{{2|}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;!-- &lt;br /&gt;
--&amp;gt;{{#if:{{{3|}}}|&amp;lt;div&amp;gt;&lt;br /&gt;
{{{3}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;}}&amp;lt;!-- &lt;br /&gt;
--&amp;gt;{{#if:{{{4|}}}|&amp;lt;div&amp;gt;&lt;br /&gt;
{{{4}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;}}&lt;br /&gt;
{{endplainlist}}}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Mapframe&amp;diff=79</id>
		<title>Module:Mapframe</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Mapframe&amp;diff=79"/>
		<updated>2026-06-22T02:04:46Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;-- Note: Originally written on English Wikipedia at https://en.wikipedia.org/wiki/Module:Mapframe  ------------------------------------------------------------------------------  ##### Localisation (L10n) settings #####  Replace values in quotes (&amp;quot;&amp;quot;) with localised values ------------------------------------------------------------------------------ local L10n = {} local wb = mw.wikibase  -- Modue dependencies local parser -- local copy of https://www.mediawiki.org/w...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Note: Originally written on English Wikipedia at https://en.wikipedia.org/wiki/Module:Mapframe&lt;br /&gt;
&lt;br /&gt;
--[[----------------------------------------------------------------------------&lt;br /&gt;
 ##### Localisation (L10n) settings #####&lt;br /&gt;
 Replace values in quotes (&amp;quot;&amp;quot;) with localised values&lt;br /&gt;
----------------------------------------------------------------------------]]--&lt;br /&gt;
local L10n = {}&lt;br /&gt;
local wb = mw.wikibase&lt;br /&gt;
&lt;br /&gt;
-- Modue dependencies&lt;br /&gt;
local parser -- local copy of https://www.mediawiki.org/wiki/Module:WikitextParser loaded lazily&lt;br /&gt;
-- &amp;quot;strict&amp;quot; should not be used, at least until all other modules which require this module are not using globals.&lt;br /&gt;
&lt;br /&gt;
-- Template parameter names (unnumbered versions only)&lt;br /&gt;
--   Specify each as either a single string, or a table of strings (aliases)&lt;br /&gt;
--   Aliases are checked left-to-right, i.e. `{ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot; }` is equivalent to using `{{{one| {{{two|}}} }}}` in a template&lt;br /&gt;
L10n.para = {&lt;br /&gt;
	display			= &amp;quot;display&amp;quot;,&lt;br /&gt;
	type			= &amp;quot;type&amp;quot;,&lt;br /&gt;
	id				= { &amp;quot;id&amp;quot;, &amp;quot;ids&amp;quot; },&lt;br /&gt;
	from			= &amp;quot;from&amp;quot;,&lt;br /&gt;
	raw				= &amp;quot;raw&amp;quot;,&lt;br /&gt;
	title			= &amp;quot;title&amp;quot;,&lt;br /&gt;
	description		= &amp;quot;description&amp;quot;,&lt;br /&gt;
	strokeColor		= { &amp;quot;stroke-color&amp;quot;, &amp;quot;stroke-colour&amp;quot; },&lt;br /&gt;
	strokeWidth		= &amp;quot;stroke-width&amp;quot;,&lt;br /&gt;
	strokeOpacity	= &amp;quot;stroke-opacity&amp;quot;,&lt;br /&gt;
	fill			= &amp;quot;fill&amp;quot;,&lt;br /&gt;
	fillOpacity		= &amp;quot;fill-opacity&amp;quot;,&lt;br /&gt;
	coord			= &amp;quot;coord&amp;quot;,&lt;br /&gt;
	marker			= &amp;quot;marker&amp;quot;,&lt;br /&gt;
	markerColor		= { &amp;quot;marker-color&amp;quot;, &amp;quot;marker-colour&amp;quot; },&lt;br /&gt;
	markerSize		= &amp;quot;marker-size&amp;quot;,&lt;br /&gt;
	radius			= { &amp;quot;radius&amp;quot;, &amp;quot;radius_m&amp;quot; },&lt;br /&gt;
	radiusKm		= &amp;quot;radius_km&amp;quot;,&lt;br /&gt;
	radiusFt		= &amp;quot;radius_ft&amp;quot;,&lt;br /&gt;
	radiusMi		= &amp;quot;radius_mi&amp;quot;,&lt;br /&gt;
	edges			= &amp;quot;edges&amp;quot;,&lt;br /&gt;
	text			= &amp;quot;text&amp;quot;,&lt;br /&gt;
	icon			= &amp;quot;icon&amp;quot;,&lt;br /&gt;
	zoom			= &amp;quot;zoom&amp;quot;,&lt;br /&gt;
	frame			= &amp;quot;frame&amp;quot;,&lt;br /&gt;
	plain			= &amp;quot;plain&amp;quot;,&lt;br /&gt;
	frameWidth		= &amp;quot;frame-width&amp;quot;,&lt;br /&gt;
	frameHeight		= &amp;quot;frame-height&amp;quot;,&lt;br /&gt;
	frameCoordinates= { &amp;quot;frame-coordinates&amp;quot;, &amp;quot;frame-coord&amp;quot; },&lt;br /&gt;
	frameLatitude	= { &amp;quot;frame-lat&amp;quot;, &amp;quot;frame-latitude&amp;quot; },&lt;br /&gt;
	frameLongitude	= { &amp;quot;frame-long&amp;quot;, &amp;quot;frame-longitude&amp;quot; },&lt;br /&gt;
	frameAlign		= &amp;quot;frame-align&amp;quot;,&lt;br /&gt;
	switch			= &amp;quot;switch&amp;quot;,&lt;br /&gt;
	overlay						= &amp;quot;overlay&amp;quot;,&lt;br /&gt;
	overlayBorder				= &amp;quot;overlay-border&amp;quot;,&lt;br /&gt;
	overlayHorizontalAlignment	= &amp;quot;overlay-horizontal-alignment&amp;quot;,&lt;br /&gt;
	overlayVerticalAlignment	= &amp;quot;overlay-vertical-alignment&amp;quot;,&lt;br /&gt;
	overlayHorizontalOffset		= &amp;quot;overlay-horizontal-offset&amp;quot;,&lt;br /&gt;
	overlayVerticalOffset		= &amp;quot;overlay-vertical-offset&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Names of other templates this module can extract coordinates from&lt;br /&gt;
L10n.template = {&lt;br /&gt;
	templates = { -- The coord template, as well as templates with output that contains {{coord}}&lt;br /&gt;
		&amp;quot;Coord&amp;quot;, &amp;quot;Coord/sandbox&amp;quot;,&lt;br /&gt;
		&amp;quot;NRHP row&amp;quot;, &amp;quot;NRHP row/sandbox&amp;quot;,&lt;br /&gt;
		&amp;quot;WikidataCoord&amp;quot;, &amp;quot;WikidataCoord/sandbox&amp;quot;, &amp;quot;Wikidatacoord&amp;quot;, &amp;quot;Wikidata coord&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	modules = { -- The coordinates module, as well as modules with output that contains {{coord}}&lt;br /&gt;
		&amp;quot;Coordinates&amp;quot;, &amp;quot;Coordinates/sandbox&amp;quot;,&lt;br /&gt;
		&amp;quot;WikidataCoord&amp;quot;, &amp;quot;WikidataCoord/sandbox&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Error messages&lt;br /&gt;
L10n.error = {&lt;br /&gt;
	badDisplayPara    = &amp;quot;Invalid display parameter&amp;quot;,&lt;br /&gt;
	noCoords	      = &amp;quot;Coordinates must be specified on Wikidata or in |&amp;quot; .. ( type(L10n.para.coord)== &#039;table&#039; and L10n.para.coord[1] or L10n.para.coord ) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
	wikidataCoords    = &amp;quot;Coordinates not found on Wikidata&amp;quot;,&lt;br /&gt;
	noCircleCoords    = &amp;quot;Circle centre coordinates must be specified, or available via Wikidata&amp;quot;,&lt;br /&gt;
	negativeRadius    = &amp;quot;Circle radius must be a positive number&amp;quot;,&lt;br /&gt;
	noRadius          = &amp;quot;Circle radius must be specified&amp;quot;,&lt;br /&gt;
	negativeEdges     = &amp;quot;Circle edges must be a positive number&amp;quot;,&lt;br /&gt;
	noSwitchPara      = &amp;quot;Found only one switch value in |&amp;quot; .. ( type(L10n.para.switch)== &#039;table&#039; and L10n.para.switch[1] or L10n.para.switch ) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
	oneSwitchLabel    = &amp;quot;Found only one label in |&amp;quot; .. ( type(L10n.para.switch)== &#039;table&#039; and L10n.para.switch[1] or L10n.para.switch ) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
	noSwitchLists     = &amp;quot;At least one parameter must have a SWITCH: list&amp;quot;,&lt;br /&gt;
	switchMismatches  = &amp;quot;All SWITCH: lists must have the same number of values&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
	 -- &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; tokens will be replaced with strings and numbers when used&lt;br /&gt;
	oneSwitchValue    = &amp;quot;Found only one switch value in |%s=&amp;quot;,&lt;br /&gt;
	fewerSwitchLabels = &amp;quot;Found %d switch values but only %d labels in |&amp;quot; .. ( type(L10n.para.switch)== &#039;table&#039; and L10n.para.switch[1] or L10n.para.switch ) .. &amp;quot;=&amp;quot;,&lt;br /&gt;
	noNamedCoords     = &amp;quot;No named coordinates found in %s&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Other strings&lt;br /&gt;
L10n.str = {&lt;br /&gt;
	-- valid values for display parameter, e.g. (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline)&lt;br /&gt;
	inline		= &amp;quot;inline&amp;quot;,&lt;br /&gt;
	title		= &amp;quot;title&amp;quot;,&lt;br /&gt;
	dsep		= &amp;quot;,&amp;quot;,			-- separator between inline and title (comma in the example above)&lt;br /&gt;
&lt;br /&gt;
	-- valid values for type parameter&lt;br /&gt;
	line		= &amp;quot;line&amp;quot;,		-- geoline feature (e.g. a road)&lt;br /&gt;
	shape		= &amp;quot;shape&amp;quot;,		-- geoshape feature (e.g. a state or province)&lt;br /&gt;
	shapeInverse	= &amp;quot;shape-inverse&amp;quot;,	-- geomask feature (the inverse of a geoshape)&lt;br /&gt;
	data		= &amp;quot;data&amp;quot;,		-- geoJSON data page on Commons&lt;br /&gt;
	point		= &amp;quot;point&amp;quot;,		-- single point feature (coordinates)&lt;br /&gt;
	circle      = &amp;quot;circle&amp;quot;,     -- circular area around a point&lt;br /&gt;
	named       = &amp;quot;named&amp;quot;,      -- all named coordinates in an article or section&lt;br /&gt;
&lt;br /&gt;
	-- Keyword to indicate a switch list. Must NOT use the special characters ^$()%.[]*+-?&lt;br /&gt;
	switch = &amp;quot;SWITCH&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
	-- valid values for icon, frame, and plain parameters&lt;br /&gt;
	affirmedWords = &#039; &#039;..table.concat({&lt;br /&gt;
		&amp;quot;add&amp;quot;,&lt;br /&gt;
		&amp;quot;added&amp;quot;,&lt;br /&gt;
		&amp;quot;affirm&amp;quot;,&lt;br /&gt;
		&amp;quot;affirmed&amp;quot;,&lt;br /&gt;
		&amp;quot;include&amp;quot;,&lt;br /&gt;
		&amp;quot;included&amp;quot;,&lt;br /&gt;
		&amp;quot;on&amp;quot;,&lt;br /&gt;
		&amp;quot;true&amp;quot;,&lt;br /&gt;
		&amp;quot;yes&amp;quot;,&lt;br /&gt;
		&amp;quot;y&amp;quot;&lt;br /&gt;
	}, &#039; &#039;)..&#039; &#039;,&lt;br /&gt;
	declinedWords = &#039; &#039;..table.concat({&lt;br /&gt;
		&amp;quot;decline&amp;quot;,&lt;br /&gt;
		&amp;quot;declined&amp;quot;,&lt;br /&gt;
		&amp;quot;exclude&amp;quot;,&lt;br /&gt;
		&amp;quot;excluded&amp;quot;,&lt;br /&gt;
		&amp;quot;false&amp;quot;,&lt;br /&gt;
		&amp;quot;none&amp;quot;,&lt;br /&gt;
		&amp;quot;not&amp;quot;,&lt;br /&gt;
		&amp;quot;no&amp;quot;,&lt;br /&gt;
		&amp;quot;n&amp;quot;,&lt;br /&gt;
		&amp;quot;off&amp;quot;,&lt;br /&gt;
		&amp;quot;omit&amp;quot;,&lt;br /&gt;
		&amp;quot;omitted&amp;quot;,&lt;br /&gt;
		&amp;quot;remove&amp;quot;,&lt;br /&gt;
		&amp;quot;removed&amp;quot;&lt;br /&gt;
	}, &#039; &#039;)..&#039; &#039;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Default values for parameters&lt;br /&gt;
L10n.defaults = {&lt;br /&gt;
	display		= L10n.str.inline,&lt;br /&gt;
	text		= &amp;quot;Map&amp;quot;,&lt;br /&gt;
	frameWidth	= &amp;quot;300&amp;quot;,&lt;br /&gt;
	frameHeight	= &amp;quot;200&amp;quot;,&lt;br /&gt;
	frameAlign  = &amp;quot;right&amp;quot;,&lt;br /&gt;
	markerColor	= &amp;quot;5E74F3&amp;quot;,&lt;br /&gt;
	markerSize	= nil,&lt;br /&gt;
	strokeColor	= &amp;quot;#ff0000&amp;quot;,&lt;br /&gt;
	strokeWidth	= 6,&lt;br /&gt;
	edges = 32, -- number of edges used to approximate a circle&lt;br /&gt;
	overlayBorder = &amp;quot;1px solid white&amp;quot;,&lt;br /&gt;
	overlayHorizontalAlignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
	overlayHorizontalOffset = &amp;quot;0&amp;quot;,&lt;br /&gt;
	overlayVerticalAlignment = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
	overlayVerticalOffset = &amp;quot;0&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- #### End of L10n settings ####&lt;br /&gt;
&lt;br /&gt;
--[[----------------------------------------------------------------------------&lt;br /&gt;
 Utility methods&lt;br /&gt;
----------------------------------------------------------------------------]]--&lt;br /&gt;
local util = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Looks up a parameter value based on the id (a key from the L10n.para table) and&lt;br /&gt;
optionally a suffix, for parameters that can be suffixed (e.g. type2 is type&lt;br /&gt;
with suffix 2).&lt;br /&gt;
@param {table} args  key-value pairs of parameter names and their values&lt;br /&gt;
@param {string} param_id  id for parameter name (key from the L10n.para table)&lt;br /&gt;
@param {string} [suffix]  suffix for parameter name&lt;br /&gt;
@returns {string|nil} parameter value if found, or nil if not found&lt;br /&gt;
]]--&lt;br /&gt;
function util.getParameterValue(args, param_id, suffix)&lt;br /&gt;
	suffix = suffix or &#039;&#039;&lt;br /&gt;
	if type( L10n.para[param_id] ) ~= &#039;table&#039; then&lt;br /&gt;
		return args[L10n.para[param_id]..suffix]&lt;br /&gt;
	end&lt;br /&gt;
	for _i, paramAlias in ipairs(L10n.para[param_id]) do&lt;br /&gt;
		if args[paramAlias..suffix] then&lt;br /&gt;
			return args[paramAlias..suffix]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Trim whitespace from args, and remove empty args. Also fix control characters.&lt;br /&gt;
@param {table} argsTable&lt;br /&gt;
@returns {table} trimmed args table&lt;br /&gt;
]]--&lt;br /&gt;
function util.trimArgs(argsTable)&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for key, val in pairs(argsTable) do&lt;br /&gt;
		if type(key) == &#039;string&#039;  and type(val) == &#039;string&#039; then&lt;br /&gt;
			val = val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
			if val ~= &#039;&#039; then&lt;br /&gt;
				-- control characters inside json need to be escaped, but stripping them is simpler&lt;br /&gt;
				-- See also T214984&lt;br /&gt;
				-- However, *don&#039;t* strip control characters from wikitext (text or description parameters) or you&#039;ll break strip markers&lt;br /&gt;
				-- Alternatively it might be better to only strip control char from raw parameter content&lt;br /&gt;
				if util.matchesParam(&#039;text&#039;, key) or util.matchesParam(&#039;description&#039;, key, key:gsub(&#039;^%D+(%d+)$&#039;, &#039;%1&#039;) ) then&lt;br /&gt;
					cleanArgs[key] = val&lt;br /&gt;
				else&lt;br /&gt;
					cleanArgs[key] = val:gsub(&#039;%c&#039;,&#039; &#039;)&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			cleanArgs[key] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return cleanArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Check if a parameter name matches an unlocalized parameter key&lt;br /&gt;
@param {string} key - the unlocalized parameter name to search through&lt;br /&gt;
@param {string} name - the localized parameter name to check&lt;br /&gt;
@param {string|nil} - an optional suffix to apply to the value(s) from the localization key&lt;br /&gt;
@returns {boolean} true if the name matches the parameter, false otherwise&lt;br /&gt;
]]--&lt;br /&gt;
function util.matchesParam(key, name, suffix)&lt;br /&gt;
	local param = L10n.para[key]&lt;br /&gt;
	suffix = suffix or &#039;&#039;&lt;br /&gt;
	if type(param) == &#039;table&#039; then&lt;br /&gt;
		for _, v in pairs(param) do&lt;br /&gt;
			if (v .. suffix) == name then return true end&lt;br /&gt;
		end&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return ((param .. suffix) == name)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Check if a value is affirmed (one of the values in L10n.str.affirmedWords)&lt;br /&gt;
@param {string} val  Value to be checked&lt;br /&gt;
@returns {boolean} true if affirmed, false otherwise&lt;br /&gt;
]]--&lt;br /&gt;
function util.isAffirmed(val)&lt;br /&gt;
	if not(val) then return false end&lt;br /&gt;
	return string.find(L10n.str.affirmedWords, &#039; &#039;..val..&#039; &#039;, 1, true ) and true or false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Check if a value is declined (one of the values in L10n.str.declinedWords)&lt;br /&gt;
@param {string} val  Value to be checked&lt;br /&gt;
@returns {boolean} true if declined, false otherwise&lt;br /&gt;
]]--&lt;br /&gt;
function util.isDeclined(val)&lt;br /&gt;
	if not(val) then return false end&lt;br /&gt;
	return string.find(L10n.str.declinedWords , &#039; &#039;..val..&#039; &#039;, 1, true ) and true or false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Check if the name of a template matches the known coord templates or wrappers&lt;br /&gt;
(in L10n.template.templates and L10n.template.modules). The name is normalised&lt;br /&gt;
when checked, so e.g. the names &amp;quot;Coord&amp;quot;, &amp;quot;coord&amp;quot;, and &amp;quot;  Coord&amp;quot; all return true.&lt;br /&gt;
@param {string} name&lt;br /&gt;
@returns {boolean} true if it is a coord template or wrapper, false otherwise&lt;br /&gt;
]]--&lt;br /&gt;
function util.isCoordTemplateOrWrapper(name)&lt;br /&gt;
	name = mw.text.trim(name)&lt;br /&gt;
	local modName = mw.ustring.gsub(name, &#039;#invoke:&#039;, &#039;&#039;)&lt;br /&gt;
	local inputTitle = mw.title.new(modName, (name ~= modName) and &#039;Module&#039; or &#039;Template&#039;)&lt;br /&gt;
	if not inputTitle then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create (or reuse) mw.title objects for each known coord template/wrapper.&lt;br /&gt;
	-- Stored in L10n.template.title so that they don&#039;t need to be recreated&lt;br /&gt;
	-- each time this function is called&lt;br /&gt;
	if not L10n.template.titles then&lt;br /&gt;
		L10n.template.titles = {}&lt;br /&gt;
		for _, v in pairs(L10n.template.templates) do&lt;br /&gt;
			table.insert(L10n.template.titles, mw.title.new(v, &#039;Template&#039;))&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in pairs(L10n.template.modules) do&lt;br /&gt;
			table.insert(L10n.template.titles, mw.title.new(v, &#039;Module&#039;))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for _, templateTitle in pairs(L10n.template.titles) do&lt;br /&gt;
		if mw.title.equals(inputTitle, templateTitle) then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Recursively extract coord templates which have a name parameter.&lt;br /&gt;
@param {string} wikitext&lt;br /&gt;
@returns {table} table sequence of coord templates&lt;br /&gt;
]]--&lt;br /&gt;
function util.extractCoordTemplates(wikitext)&lt;br /&gt;
	local output = {}&lt;br /&gt;
	local templates = mw.ustring.gmatch(wikitext, &#039;{%b{}}&#039;)&lt;br /&gt;
	for template in templates do&lt;br /&gt;
		local templateName = mw.ustring.match(template, &#039;{{([^}|]+)&#039;)&lt;br /&gt;
		local nameParam = mw.ustring.match(template, &amp;quot;|%s*name%s*=%s*[^}|]+&amp;quot;)&lt;br /&gt;
		if util.isCoordTemplateOrWrapper(templateName) then&lt;br /&gt;
			if nameParam then table.insert(output, template) end&lt;br /&gt;
		elseif mw.ustring.find(mw.ustring.sub(template, 2), &amp;quot;{{&amp;quot;) then&lt;br /&gt;
			local subOutput = util.extractCoordTemplates(mw.ustring.sub(template, 2))&lt;br /&gt;
			for _, t in pairs(subOutput) do&lt;br /&gt;
				table.insert(output, t)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- ensure coords are not using title display&lt;br /&gt;
	for k, v in pairs(output) do&lt;br /&gt;
		output[k] = mw.ustring.gsub(v, &amp;quot;|%s*display%s*=[^|}]+&amp;quot;, &amp;quot;|display=inline&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	return output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Gets all named coordiates from a page or a section of a page.&lt;br /&gt;
@param {string|nil} page  Page name, or name#section, to get named coordinates&lt;br /&gt;
  from. If the name is omitted, i.e. #section or nil or empty string, then&lt;br /&gt;
  the current page will be used.&lt;br /&gt;
@returns {table} sequence of {coord, name, description} tables where coord is&lt;br /&gt;
  the coordinates in a format suitable for #util.parseCoords, name is a string,&lt;br /&gt;
  and description is a string (coordinates in a format suitable for displaying&lt;br /&gt;
  to the reader). If for some reason the name can&#039;t be found, the description&lt;br /&gt;
  is nil and the name contains display-format coordinates.&lt;br /&gt;
@throws {L10n.error.noNamedCoords} if no named coordinates are found.&lt;br /&gt;
]]--&lt;br /&gt;
function util.getNamedCoords(page)&lt;br /&gt;
	local parts = mw.text.split(page or &amp;quot;&amp;quot;, &amp;quot;#&amp;quot;, true)&lt;br /&gt;
	local name = parts[1] == &amp;quot;&amp;quot; and mw.title.getCurrentTitle().prefixedText or parts[1]&lt;br /&gt;
	local section = parts[2]&lt;br /&gt;
	local title = mw.title.new(name)&lt;br /&gt;
	if title.isRedirect then&lt;br /&gt;
		title = title.redirectTarget&lt;br /&gt;
	end&lt;br /&gt;
	local pageWikitext = title:getContent()&lt;br /&gt;
	if section then&lt;br /&gt;
		if parser == nil then&lt;br /&gt;
			-- load [[Module:WikitextParser]] lazily so it is only transcluded on pages that use it&lt;br /&gt;
			parser = require(&amp;quot;Module:WikitextParser&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
		pageWikitext = parser.getSection(pageWikitext, section) or &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local coordTemplates = util.extractCoordTemplates(pageWikitext)&lt;br /&gt;
	if #coordTemplates == 0 then error(string.format(L10n.error.noNamedCoords, page or name), 0) end&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local sep = &amp;quot;________&amp;quot;&lt;br /&gt;
	local expandedContent = frame:preprocess(table.concat(coordTemplates, sep))&lt;br /&gt;
	local expandedTemplates = mw.text.split(expandedContent, sep)&lt;br /&gt;
	local namedCoords = {}&lt;br /&gt;
	for _, expandedTemplate in pairs(expandedTemplates) do&lt;br /&gt;
		local coord = mw.ustring.match(expandedTemplate, &amp;quot;&amp;lt;span class=\&amp;quot;geo%-dec\&amp;quot;.-&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;quot;)&lt;br /&gt;
		if coord then&lt;br /&gt;
			local coordname = (&lt;br /&gt;
				-- name specified by a wrapper template, e.g [[Article|Name]]&lt;br /&gt;
				mw.ustring.match(expandedTemplate, &amp;quot;&amp;lt;span class=\&amp;quot;mapframe%-coord%-name\&amp;quot;&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;quot;) or&lt;br /&gt;
				-- name passed into coord template&lt;br /&gt;
				mw.ustring.match(expandedTemplate, &amp;quot;&amp;lt;span class=\&amp;quot;fn org\&amp;quot;&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;quot;) or&lt;br /&gt;
				-- default to the coordinates if the name can&#039;t be retrieved&lt;br /&gt;
				coord&lt;br /&gt;
			)&lt;br /&gt;
			local description = coordname ~= coord and coord&lt;br /&gt;
			table.insert(namedCoords, {&lt;br /&gt;
					coord=mw.ustring.gsub(coord, &amp;quot;[° ]&amp;quot;, &amp;quot;_&amp;quot;),&lt;br /&gt;
					name=coordname, description=description&lt;br /&gt;
			})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if #namedCoords == 0 then error(string.format(L10n.error.noNamedCoords, page or name), 0) end&lt;br /&gt;
	return namedCoords&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Parse coordinate values from the params passed in a GeoHack url (such as&lt;br /&gt;
//tools.wmflabs.org/geohack/geohack.php?pagename=Example&amp;amp;params=1_2_N_3_4_W_ or&lt;br /&gt;
//tools.wmflabs.org/geohack/geohack.php?pagename=Example&amp;amp;params=1.23_S_4.56_E_ )&lt;br /&gt;
or non-url string in the same format (such as `1_2_N_3_4_W_` or `1.23_S_4.56_E_`)&lt;br /&gt;
@param {string} coords  string containing coordinates&lt;br /&gt;
@returns {number, number} latitude, longitude&lt;br /&gt;
]]--&lt;br /&gt;
function util.parseCoords(coords)&lt;br /&gt;
	local coordsPatt&lt;br /&gt;
	if mw.ustring.find(coords, &amp;quot;params=&amp;quot;, 1, true) then&lt;br /&gt;
		-- prevent false matches from page name, e.g. ?pagename=Lorem_S._Ipsum&lt;br /&gt;
		coordsPatt = &#039;params=([_%.%d]+[NS][_%.%d]+[EW])&#039;&lt;br /&gt;
	else&lt;br /&gt;
		-- not actually a geohack url, just the same format&lt;br /&gt;
		coordsPatt = &#039;[_%.%d]+[NS][_%.%d]+[EW]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local parts = mw.text.split((mw.ustring.match(coords, coordsPatt) or &#039;&#039;), &#039;_&#039;)&lt;br /&gt;
&lt;br /&gt;
	local lat_d = tonumber(parts[1])&lt;br /&gt;
	assert(lat_d, &amp;quot;Unable to get latitude from input &#039;&amp;quot;..coords..&amp;quot;&#039;.&amp;quot;)&lt;br /&gt;
	local lat_m = tonumber(parts[2]) -- nil if coords are in decimal format&lt;br /&gt;
	local lat_s = lat_m and tonumber(parts[3]) -- nil if coords are either in decimal format or degrees and minutes only&lt;br /&gt;
	local lat = lat_d + (lat_m or 0)/60 + (lat_s or 0)/3600&lt;br /&gt;
	if parts[#parts/2] == &#039;S&#039; then&lt;br /&gt;
		lat = lat * -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local long_d = tonumber(parts[1+#parts/2])&lt;br /&gt;
	assert(long_d, &amp;quot;Unable to get longitude from input &#039;&amp;quot;..coords..&amp;quot;&#039;.&amp;quot;)&lt;br /&gt;
	local long_m = tonumber(parts[2+#parts/2]) -- nil if coords are in decimal format&lt;br /&gt;
	local long_s = long_m and tonumber(parts[3+#parts/2]) -- nil if coords are either in decimal format or degrees and minutes only&lt;br /&gt;
	local long = long_d + (long_m or 0)/60 + (long_s or 0)/3600&lt;br /&gt;
	if parts[#parts] == &#039;W&#039; then&lt;br /&gt;
		long = long * -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return lat, long&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Get coordinates from a Wikidata item&lt;br /&gt;
@param {string} item_id  Wikidata item id (Q number)&lt;br /&gt;
@returns {number, number} latitude, longitude&lt;br /&gt;
@throws {L10n.error.noCoords} if item_id is invalid or the item does not exist&lt;br /&gt;
@throws {L10n.error.wikidataCoords} if the the item does not have a P625&lt;br /&gt;
  statement (coordinates), or it is set to &amp;quot;no value&amp;quot;&lt;br /&gt;
]]--&lt;br /&gt;
function util.wikidataCoords(item_id)&lt;br /&gt;
	if not (item_id and wb.isValidEntityId(item_id) and wb.entityExists(item_id)) then&lt;br /&gt;
		error(L10n.error.noCoords, 0)&lt;br /&gt;
	end&lt;br /&gt;
	local coordStatements = wb.getBestStatements(item_id, &#039;P625&#039;)&lt;br /&gt;
	if not coordStatements or #coordStatements == 0 then&lt;br /&gt;
		error(L10n.error.wikidataCoords, 0)&lt;br /&gt;
	end&lt;br /&gt;
	local hasNoValue = ( coordStatements[1].mainsnak and (coordStatements[1].mainsnak.snaktype == &#039;novalue&#039; or coordStatements[1].mainsnak.snaktype == &#039;somevalue&#039;) )&lt;br /&gt;
	if hasNoValue then&lt;br /&gt;
		error(L10n.error.wikidataCoords, 0)&lt;br /&gt;
	end&lt;br /&gt;
	local wdCoords = coordStatements[1][&#039;mainsnak&#039;][&#039;datavalue&#039;][&#039;value&#039;]&lt;br /&gt;
	return tonumber(wdCoords[&#039;latitude&#039;]), tonumber(wdCoords[&#039;longitude&#039;])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Creates a polygon that approximates a circle&lt;br /&gt;
@param {number} lat  Latitude&lt;br /&gt;
@param {number} long  Longitude&lt;br /&gt;
@param {number} radius  Radius in metres&lt;br /&gt;
@param {number} n  Number of edges for the polygon&lt;br /&gt;
@returns {table} sequence of {latitude, longitude} table sequences, where&lt;br /&gt;
  latitude and longitude are both numbers&lt;br /&gt;
]]--&lt;br /&gt;
function util.circleToPolygon(lat, long, radius, n) -- n is number of edges&lt;br /&gt;
	-- Based on https://github.com/gabzim/circle-to-polygon, ISC licence&lt;br /&gt;
&lt;br /&gt;
	local function offset(cLat, cLon, distance, bearing)&lt;br /&gt;
		local lat1 = math.rad(cLat)&lt;br /&gt;
		local lon1 = math.rad(cLon)&lt;br /&gt;
		local dByR = distance / 6378137 -- distance divided by 6378137 (radius of the earth) wgs84&lt;br /&gt;
		local offet_lat = math.asin(&lt;br /&gt;
			math.sin(lat1) * math.cos(dByR) +&lt;br /&gt;
			math.cos(lat1) * math.sin(dByR) * math.cos(bearing)&lt;br /&gt;
		)&lt;br /&gt;
		local offet_lon = lon1 + math.atan2(&lt;br /&gt;
			math.sin(bearing) * math.sin(dByR) * math.cos(lat1),&lt;br /&gt;
			math.cos(dByR) - math.sin(lat1) * math.sin(offet_lat)&lt;br /&gt;
		)&lt;br /&gt;
		return {math.deg(offet_lon), math.deg(offet_lat)}&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local coordinates = {};&lt;br /&gt;
	local i = 0;&lt;br /&gt;
	while i &amp;lt; n do&lt;br /&gt;
		table.insert(coordinates,&lt;br /&gt;
			offset(lat, long, radius, (2*math.pi*i*-1)/n)&lt;br /&gt;
		)&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(coordinates, offset(lat, long, radius, 0))&lt;br /&gt;
	return coordinates&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Get the number of key-value pairs in a table, which might not be a sequence.&lt;br /&gt;
@param {table} t&lt;br /&gt;
@returns {number} count of key-value pairs&lt;br /&gt;
]]--&lt;br /&gt;
function util.tableCount(t)&lt;br /&gt;
	local count = 0&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		count = count + 1&lt;br /&gt;
	end&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
For a table where the values are all tables, returns either the util.tableCount&lt;br /&gt;
of the subtables if they are all the same, or nil if they are not all the same.&lt;br /&gt;
@param {table} t&lt;br /&gt;
@returns {number|nil} count of key-value pairs of subtable, or nil if subtables&lt;br /&gt;
  have different counts&lt;br /&gt;
]]--&lt;br /&gt;
function util.subTablesCount(t)&lt;br /&gt;
	local count = nil&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if count == nil then&lt;br /&gt;
			count = util.tableCount(v)&lt;br /&gt;
		elseif count ~= util.tableCount(v) then&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Splits a list into a table sequence. The items in the list may be separated by&lt;br /&gt;
commas, or by semicolons (if items may contain commas), or by &amp;quot;###&amp;quot; (if items&lt;br /&gt;
may contain semicolons).&lt;br /&gt;
@param {string} listString&lt;br /&gt;
@returns {table} sequence of list items&lt;br /&gt;
]]--&lt;br /&gt;
function util.tableFromList(listString)&lt;br /&gt;
	if type(listString) ~= &amp;quot;string&amp;quot; or listString == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
	local separator = (mw.ustring.find(listString, &amp;quot;###&amp;quot;, 0, true ) and &amp;quot;###&amp;quot;) or&lt;br /&gt;
		(mw.ustring.find(listString, &amp;quot;;&amp;quot;, 0, true ) and &amp;quot;;&amp;quot;) or &amp;quot;,&amp;quot;&lt;br /&gt;
	local pattern = &amp;quot;%s*&amp;quot;..separator..&amp;quot;%s*&amp;quot;&lt;br /&gt;
	return mw.text.split(listString, pattern)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Boolean in outer scope indicating if Kartographer should be able to&lt;br /&gt;
-- automatically calculate coordinates (see phab:T227402)&lt;br /&gt;
local coordsDerivedFromFeatures = false;&lt;br /&gt;
&lt;br /&gt;
--[[----------------------------------------------------------------------------&lt;br /&gt;
 Make methods: These take in a table of arguments, and return either a string&lt;br /&gt;
 or a table to be used in the eventual output.&lt;br /&gt;
----------------------------------------------------------------------------]]--&lt;br /&gt;
local make = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes content to go inside the maplink or mapframe tag.&lt;br /&gt;
&lt;br /&gt;
@param {table} args&lt;br /&gt;
@returns {string} tag content&lt;br /&gt;
]]--&lt;br /&gt;
function make.content(args)&lt;br /&gt;
	if util.getParameterValue(args, &#039;raw&#039;) then&lt;br /&gt;
		coordsDerivedFromFeatures = true -- Kartographer should be able to automatically calculate coords from raw geoJSON&lt;br /&gt;
		return util.getParameterValue(args, &#039;raw&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local content = {}&lt;br /&gt;
&lt;br /&gt;
    local argsExpanded = {}&lt;br /&gt;
    for k, v in pairs(args) do&lt;br /&gt;
		local index = string.match( k, &#039;^[^0-9]+([0-9]*)$&#039; )&lt;br /&gt;
		if index ~= nil then&lt;br /&gt;
			local indexNumber&lt;br /&gt;
			if index ~= &#039;&#039; then&lt;br /&gt;
				indexNumber = tonumber(index)&lt;br /&gt;
			else&lt;br /&gt;
				indexNumber = 1&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if argsExpanded[indexNumber] == nil then&lt;br /&gt;
				argsExpanded[indexNumber] = {}&lt;br /&gt;
			end&lt;br /&gt;
			argsExpanded[indexNumber][ string.gsub(k, index, &#039;&#039;) ] = v&lt;br /&gt;
		end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
	for contentIndex, contentArgs in pairs(argsExpanded) do&lt;br /&gt;
		local argType = util.getParameterValue(contentArgs, &amp;quot;type&amp;quot;)&lt;br /&gt;
		-- Kartographer automatically calculates coords if geolines/shapes are used (T227402)&lt;br /&gt;
		if not coordsDerivedFromFeatures then&lt;br /&gt;
			coordsDerivedFromFeatures = ( argType == L10n.str.line or argType == L10n.str.shape ) and true or false&lt;br /&gt;
		end&lt;br /&gt;
		if argType == L10n.str.named then&lt;br /&gt;
			local namedCoords = util.getNamedCoords(util.getParameterValue(contentArgs, &amp;quot;from&amp;quot;))&lt;br /&gt;
			local typeKey = type(L10n.para.type) == &amp;quot;table&amp;quot; and L10n.para.type[1] or L10n.para.type&lt;br /&gt;
			local coordKey = type(L10n.para.coord) == &amp;quot;table&amp;quot; and L10n.para.coord[1] or L10n.para.coord&lt;br /&gt;
			local titleKey = type(L10n.para.title) == &amp;quot;table&amp;quot; and L10n.para.title[1] or L10n.para.title&lt;br /&gt;
			local descKey = type(L10n.para.description) == &amp;quot;table&amp;quot; and L10n.para.description[1] or L10n.para.description&lt;br /&gt;
			for _, namedCoord in pairs(namedCoords) do&lt;br /&gt;
				contentArgs[typeKey] = &amp;quot;point&amp;quot;&lt;br /&gt;
				contentArgs[coordKey]  = namedCoord.coord&lt;br /&gt;
				contentArgs[titleKey]  = namedCoord.name&lt;br /&gt;
				contentArgs[descKey]  = namedCoord.description&lt;br /&gt;
				content[#content+1] = make.contentJson(contentArgs)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			content[#content + 1] = make.contentJson(contentArgs)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--Single item, no array needed&lt;br /&gt;
	if #content==1 then return content[1] end&lt;br /&gt;
&lt;br /&gt;
	--Multiple items get placed in a FeatureCollection&lt;br /&gt;
	local contentArray = &#039;[\n&#039; .. table.concat( content, &#039;,\n&#039;) .. &#039;\n]&#039;&lt;br /&gt;
	return contentArray&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Make coordinates from the coord arg, or the id arg, or the current page&#039;s&lt;br /&gt;
Wikidata item.&lt;br /&gt;
@param {table} args&lt;br /&gt;
@param {boolean} [plainOutput]&lt;br /&gt;
@returns {Mixed} Either:&lt;br /&gt;
  {number, number} latitude, longitude  if plainOutput is true; or&lt;br /&gt;
  {table} table sequence of longitude, then latitude (gives the required format&lt;br /&gt;
   for GeoJSON when encoded)&lt;br /&gt;
]]--&lt;br /&gt;
function make.coords(args, plainOutput)&lt;br /&gt;
	local coords, lat, long&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	if util.getParameterValue(args, &#039;coord&#039;) then&lt;br /&gt;
		coords = frame:preprocess( util.getParameterValue(args, &#039;coord&#039;) )&lt;br /&gt;
		lat, long = util.parseCoords(coords)&lt;br /&gt;
	else&lt;br /&gt;
		lat, long = util.wikidataCoords(util.getParameterValue(args, &#039;id&#039;) or wb.getEntityIdForCurrentPage())&lt;br /&gt;
	end&lt;br /&gt;
	if plainOutput then&lt;br /&gt;
		return lat, long&lt;br /&gt;
	end&lt;br /&gt;
	return {[0] = long, [1] = lat}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes a table of coordinates that approximate a circle.&lt;br /&gt;
@param {table} args&lt;br /&gt;
@returns {table} sequence of {latitude, longitude} table sequences, where&lt;br /&gt;
  latitude and longitude are both numbers&lt;br /&gt;
@throws {L10n.error.noCircleCoords} if centre coordinates are not specified&lt;br /&gt;
@throws {L10n.error.noRadius} if radius is not specified&lt;br /&gt;
@throws {L10n.error.negativeRadius} if radius is negative or zero&lt;br /&gt;
@throws {L10n.error.negativeEdges} if edges is negative or zero&lt;br /&gt;
]]--&lt;br /&gt;
function make.circleCoords(args)&lt;br /&gt;
	local lat, long = make.coords(args, true)&lt;br /&gt;
	local radius = util.getParameterValue(args, &#039;radius&#039;)&lt;br /&gt;
	if not radius then&lt;br /&gt;
		radius = util.getParameterValue(args, &#039;radiusKm&#039;) and tonumber(util.getParameterValue(args, &#039;radiusKm&#039;))*1000&lt;br /&gt;
		if not radius then&lt;br /&gt;
			radius = util.getParameterValue(args, &#039;radiusMi&#039;) and tonumber(util.getParameterValue(args, &#039;radiusMi&#039;))*1609.344&lt;br /&gt;
			if not radius then&lt;br /&gt;
				radius = util.getParameterValue(args, &#039;radiusFt&#039;) and tonumber(util.getParameterValue(args, &#039;radiusFt&#039;))*0.3048&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local edges = util.getParameterValue(args, &#039;edges&#039;) or L10n.defaults.edges&lt;br /&gt;
	if not lat or not long then&lt;br /&gt;
		error(L10n.error.noCircleCoords, 0)&lt;br /&gt;
	elseif not radius then&lt;br /&gt;
		error(L10n.error.noRadius, 0)&lt;br /&gt;
	elseif tonumber(radius) &amp;lt;= 0 then&lt;br /&gt;
		error(L10n.error.negativeRadius, 0)&lt;br /&gt;
	elseif tonumber(edges) &amp;lt;= 0 then&lt;br /&gt;
		error(L10n.error.negativeEdges, 0)&lt;br /&gt;
	end&lt;br /&gt;
	return util.circleToPolygon(lat, long, radius, tonumber(edges))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes JSON data for a feature&lt;br /&gt;
@param contentArgs  args for this feature. Keys must be the non-suffixed version&lt;br /&gt;
  of the parameter names, i.e. use type, stroke, fill,... rather than type3,&lt;br /&gt;
  stroke3, fill3,...&lt;br /&gt;
@returns {string} JSON encoded data&lt;br /&gt;
]]--&lt;br /&gt;
function make.contentJson(contentArgs)&lt;br /&gt;
	local data = {}&lt;br /&gt;
&lt;br /&gt;
	if util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.point or util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.circle then&lt;br /&gt;
		local isCircle = util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.circle&lt;br /&gt;
		data.type = &amp;quot;Feature&amp;quot;&lt;br /&gt;
		data.geometry = {&lt;br /&gt;
			type = isCircle and &amp;quot;LineString&amp;quot; or &amp;quot;Point&amp;quot;,&lt;br /&gt;
			coordinates = isCircle and make.circleCoords(contentArgs) or make.coords(contentArgs)&lt;br /&gt;
		}&lt;br /&gt;
		data.properties = {&lt;br /&gt;
			title = util.getParameterValue(contentArgs, &#039;title&#039;) or mw.getCurrentFrame():getParent():getTitle()&lt;br /&gt;
		}&lt;br /&gt;
		if isCircle then&lt;br /&gt;
			-- TODO: This is very similar to below, should be extracted into a function&lt;br /&gt;
			data.properties.stroke = util.getParameterValue(contentArgs, &#039;strokeColor&#039;) or L10n.defaults.strokeColor&lt;br /&gt;
			data.properties[&amp;quot;stroke-width&amp;quot;] = tonumber(util.getParameterValue(contentArgs, &#039;strokeWidth&#039;)) or L10n.defaults.strokeWidth&lt;br /&gt;
			local strokeOpacity = util.getParameterValue(contentArgs, &#039;strokeOpacity&#039;)&lt;br /&gt;
			if strokeOpacity then&lt;br /&gt;
				data.properties[&#039;stroke-opacity&#039;] = tonumber(strokeOpacity)&lt;br /&gt;
			end&lt;br /&gt;
			local fill = util.getParameterValue(contentArgs, &#039;fill&#039;)&lt;br /&gt;
			if fill then&lt;br /&gt;
				data.properties.fill = fill&lt;br /&gt;
				local fillOpacity = util.getParameterValue(contentArgs, &#039;fillOpacity&#039;)&lt;br /&gt;
				data.properties[&#039;fill-opacity&#039;] = fillOpacity and tonumber(fillOpacity) or 0.6&lt;br /&gt;
			end&lt;br /&gt;
		else -- is a point&lt;br /&gt;
			local markerSymbol = util.getParameterValue(contentArgs, &#039;marker&#039;) or L10n.defaults.marker&lt;br /&gt;
			-- allow blank to be explicitly specified, for overriding infoboxes or other templates with a default value&lt;br /&gt;
			if markerSymbol ~= &amp;quot;blank&amp;quot; then&lt;br /&gt;
				data.properties[&amp;quot;marker-symbol&amp;quot;] = markerSymbol&lt;br /&gt;
			end&lt;br /&gt;
			data.properties[&amp;quot;marker-color&amp;quot;] = util.getParameterValue(contentArgs, &#039;markerColor&#039;) or L10n.defaults.markerColor&lt;br /&gt;
			data.properties[&amp;quot;marker-size&amp;quot;] = util.getParameterValue(contentArgs, &#039;markerSize&#039;) or L10n.defaults.markerSize&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		data.type = &amp;quot;ExternalData&amp;quot;&lt;br /&gt;
&lt;br /&gt;
		if util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.data or util.getParameterValue(contentArgs, &#039;from&#039;) then&lt;br /&gt;
			data.service = &amp;quot;page&amp;quot;&lt;br /&gt;
		elseif util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.line then&lt;br /&gt;
			data.service = &amp;quot;geoline&amp;quot;&lt;br /&gt;
		elseif util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.shape then&lt;br /&gt;
			data.service = &amp;quot;geoshape&amp;quot;&lt;br /&gt;
		elseif util.getParameterValue(contentArgs, &#039;type&#039;) == L10n.str.shapeInverse then&lt;br /&gt;
			data.service = &amp;quot;geomask&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if util.getParameterValue(contentArgs, &#039;id&#039;) or (not (util.getParameterValue(contentArgs, &#039;from&#039;)) and wb.getEntityIdForCurrentPage()) then&lt;br /&gt;
			data.ids = util.getParameterValue(contentArgs, &#039;id&#039;) or wb.getEntityIdForCurrentPage()&lt;br /&gt;
		else&lt;br /&gt;
			data.title = util.getParameterValue(contentArgs, &#039;from&#039;)&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		data.properties = {&lt;br /&gt;
			stroke = util.getParameterValue(contentArgs, &#039;strokeColor&#039;) or L10n.defaults.strokeColor,&lt;br /&gt;
			[&amp;quot;stroke-width&amp;quot;] = tonumber(util.getParameterValue(contentArgs, &#039;strokeWidth&#039;)) or L10n.defaults.strokeWidth&lt;br /&gt;
		}&lt;br /&gt;
		local strokeOpacity = util.getParameterValue(contentArgs, &#039;strokeOpacity&#039;)&lt;br /&gt;
		if strokeOpacity then&lt;br /&gt;
			data.properties[&#039;stroke-opacity&#039;] = tonumber(strokeOpacity)&lt;br /&gt;
		end&lt;br /&gt;
		local fill = util.getParameterValue(contentArgs, &#039;fill&#039;)&lt;br /&gt;
		if fill and (data.service == &amp;quot;geoshape&amp;quot; or data.service == &amp;quot;geomask&amp;quot;) then&lt;br /&gt;
			data.properties.fill = fill&lt;br /&gt;
			local fillOpacity = util.getParameterValue(contentArgs, &#039;fillOpacity&#039;)&lt;br /&gt;
			if fillOpacity then&lt;br /&gt;
				data.properties[&#039;fill-opacity&#039;] = tonumber(fillOpacity)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	data.properties.title = util.getParameterValue(contentArgs, &#039;title&#039;) or mw.title.getCurrentTitle().text&lt;br /&gt;
	if util.getParameterValue(contentArgs, &#039;description&#039;) then&lt;br /&gt;
		data.properties.description = util.getParameterValue(contentArgs, &#039;description&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.text.jsonEncode(data)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes attributes for the maplink or mapframe tag.&lt;br /&gt;
@param {table} args&lt;br /&gt;
@param {boolean} [isTitle]  Tag is to be displayed in the title of page rather&lt;br /&gt;
  than inline&lt;br /&gt;
@returns {table&amp;lt;string,string&amp;gt;} key-value pairs of attribute names and values&lt;br /&gt;
]]--&lt;br /&gt;
function make.tagAttribs(args, isTitle)&lt;br /&gt;
	local attribs = {}&lt;br /&gt;
	if util.getParameterValue(args, &#039;zoom&#039;) then&lt;br /&gt;
		attribs.zoom = util.getParameterValue(args, &#039;zoom&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if util.isDeclined(util.getParameterValue(args, &#039;icon&#039;)) then&lt;br /&gt;
		attribs.class = &amp;quot;no-icon&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if util.getParameterValue(args, &#039;type&#039;) == L10n.str.point and not coordsDerivedFromFeatures then&lt;br /&gt;
		local lat, long = make.coords(args, &#039;plainOutput&#039;)&lt;br /&gt;
		attribs.latitude = tostring(lat)&lt;br /&gt;
		attribs.longitude = tostring(long)&lt;br /&gt;
	end&lt;br /&gt;
	if util.isAffirmed(util.getParameterValue(args, &#039;frame&#039;)) and not(isTitle) then&lt;br /&gt;
		attribs.width = util.getParameterValue(args, &#039;frameWidth&#039;) or L10n.defaults.frameWidth&lt;br /&gt;
		attribs.height = util.getParameterValue(args, &#039;frameHeight&#039;) or L10n.defaults.frameHeight&lt;br /&gt;
		if util.getParameterValue(args, &#039;frameCoordinates&#039;) then&lt;br /&gt;
			local frameLat, frameLong = util.parseCoords(util.getParameterValue(args, &#039;frameCoordinates&#039;))&lt;br /&gt;
			attribs.latitude = frameLat&lt;br /&gt;
			attribs.longitude = frameLong&lt;br /&gt;
		else&lt;br /&gt;
			if util.getParameterValue(args, &#039;frameLatitude&#039;) then&lt;br /&gt;
				attribs.latitude = util.getParameterValue(args, &#039;frameLatitude&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			if util.getParameterValue(args, &#039;frameLongitude&#039;) then&lt;br /&gt;
				attribs.longitude = util.getParameterValue(args, &#039;frameLongitude&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if not attribs.latitude and not attribs.longitude and not coordsDerivedFromFeatures then&lt;br /&gt;
			local success, lat, long = pcall(util.wikidataCoords, util.getParameterValue(args, &#039;id&#039;) or wb.getEntityIdForCurrentPage())&lt;br /&gt;
			if success then&lt;br /&gt;
				attribs.latitude = tostring(lat)&lt;br /&gt;
				attribs.longitude = tostring(long)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if util.getParameterValue(args, &#039;frameAlign&#039;) then&lt;br /&gt;
			attribs.align = util.getParameterValue(args, &#039;frameAlign&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if util.isAffirmed(util.getParameterValue(args, &#039;plain&#039;)) then&lt;br /&gt;
			attribs.frameless = &amp;quot;1&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
			attribs.text = util.getParameterValue(args, &#039;text&#039;) or L10n.defaults.text&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		attribs.text = util.getParameterValue(args, &#039;text&#039;) or L10n.defaults.text&lt;br /&gt;
	end&lt;br /&gt;
	return attribs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes maplink wikitext that will be located in the top-right of the title of the&lt;br /&gt;
page (the same place where coords with |display=title are positioned).&lt;br /&gt;
@param {table} args&lt;br /&gt;
@param {string} tagContent  Content for the maplink tag&lt;br /&gt;
@returns {string}&lt;br /&gt;
]]--&lt;br /&gt;
function make.titleOutput(args, tagContent)&lt;br /&gt;
	local titleTag = mw.text.tag(&#039;maplink&#039;, make.tagAttribs(args, true), tagContent)&lt;br /&gt;
	local spanAttribs = {&lt;br /&gt;
		style = &amp;quot;font-size: small;&amp;quot;,&lt;br /&gt;
		id = &amp;quot;mapframe-coordinates&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
	local indicatorContent = mw.text.tag(&#039;span&#039;, spanAttribs, titleTag)&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag {&lt;br /&gt;
		name = &amp;quot;indicator&amp;quot;,&lt;br /&gt;
		content = indicatorContent,&lt;br /&gt;
		args = {&lt;br /&gt;
			name = &amp;quot;zzz-mapframe&amp;quot; --zzz: show as last indicator&lt;br /&gt;
		}&lt;br /&gt;
	} &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes maplink or mapframe wikitext that will be located inline.&lt;br /&gt;
@param {table} args&lt;br /&gt;
@param {string} tagContent  Content for the maplink tag&lt;br /&gt;
@returns {string}&lt;br /&gt;
]]--&lt;br /&gt;
function make.inlineOutput(args, tagContent)&lt;br /&gt;
	local tagName = &#039;maplink&#039;&lt;br /&gt;
	if util.getParameterValue(args, &#039;frame&#039;) then&lt;br /&gt;
		tagName = &#039;mapframe&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.text.tag(tagName, make.tagAttribs(args), tagContent)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes the HTML required for the swicther to work, including the templatestyles&lt;br /&gt;
tag.&lt;br /&gt;
@param {table} params  table sequence of {map, label} tables&lt;br /&gt;
  @param {string} params{}.map  Wikitext for mapframe map&lt;br /&gt;
  @param {string} params{}.label  Label text for swicther option&lt;br /&gt;
@param {table} options&lt;br /&gt;
  @param {string} options.alignment  &amp;quot;left&amp;quot; or &amp;quot;center&amp;quot; or &amp;quot;right&amp;quot;&lt;br /&gt;
  @param {boolean} options.isThumbnail  Display in a thumbnail&lt;br /&gt;
  @param {string} options.width  Width of frame, e.g. &amp;quot;200&amp;quot;&lt;br /&gt;
  @param {string} [options.caption]  Caption wikitext for thumnail&lt;br /&gt;
@retruns {string} swicther HTML&lt;br /&gt;
]]--&lt;br /&gt;
function make.switcherHtml(params, options)&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local styles = frame:extensionTag{&lt;br /&gt;
		name = &amp;quot;templatestyles&amp;quot;,&lt;br /&gt;
		args = {src = &amp;quot;Template:Maplink/styles-multi.css&amp;quot;}&lt;br /&gt;
	}&lt;br /&gt;
	local container = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;switcher-container&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mapframe-multi-container&amp;quot;)&lt;br /&gt;
	if options.alignment == &amp;quot;left&amp;quot; or options.alignment == &amp;quot;right&amp;quot; then&lt;br /&gt;
		container:addClass(&amp;quot;float&amp;quot;..options.alignment)&lt;br /&gt;
	else -- alignment is &amp;quot;center&amp;quot;&lt;br /&gt;
		container:addClass(&amp;quot;center&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, #params do&lt;br /&gt;
		container&lt;br /&gt;
			:tag(&amp;quot;div&amp;quot;)&lt;br /&gt;
				:wikitext(params[i].map)&lt;br /&gt;
				:tag(&amp;quot;span&amp;quot;)&lt;br /&gt;
					:addClass(&amp;quot;switcher-label&amp;quot;)&lt;br /&gt;
					:css(&amp;quot;display&amp;quot;, &amp;quot;none&amp;quot;)&lt;br /&gt;
					:wikitext(mw.text.trim(params[i].label))&lt;br /&gt;
	end&lt;br /&gt;
	if not options.isThumbnail then&lt;br /&gt;
		return styles .. tostring(container)&lt;br /&gt;
	end&lt;br /&gt;
	local classlist = container:getAttr(&amp;quot;class&amp;quot;)&lt;br /&gt;
	classlist = mw.ustring.gsub(classlist, &amp;quot;%a*&amp;quot;..options.alignment, &amp;quot;&amp;quot;)&lt;br /&gt;
	container:attr(&amp;quot;class&amp;quot;, classlist)&lt;br /&gt;
	local outerCountainer = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mapframe-multi-outer-container&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mw-kartographer-container&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;thumb&amp;quot;)&lt;br /&gt;
	if options.alignment == &amp;quot;left&amp;quot; or options.alignment == &amp;quot;right&amp;quot; then&lt;br /&gt;
		outerCountainer:addClass(&amp;quot;float&amp;quot;..options.alignment)&lt;br /&gt;
	else -- alignment is &amp;quot;center&amp;quot;&lt;br /&gt;
		outerCountainer&lt;br /&gt;
			:addClass(&amp;quot;tnone&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;center&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	outerCountainer&lt;br /&gt;
		:tag(&amp;quot;div&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;thumbinner&amp;quot;)&lt;br /&gt;
			:css(&amp;quot;width&amp;quot;, options.width..&amp;quot;px&amp;quot;)&lt;br /&gt;
			:node(container)&lt;br /&gt;
			:node(options.caption and mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
				:addClass(&amp;quot;thumbcaption&amp;quot;)&lt;br /&gt;
				:wikitext(options.caption)&lt;br /&gt;
			)&lt;br /&gt;
	return styles .. tostring(outerCountainer)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Makes the HTML required for an overlay map to work&lt;br /&gt;
tag.&lt;br /&gt;
@param {string} overlayMap  wikitext for the overlay map&lt;br /&gt;
@param {string} baseMap  wikitext for the base map&lt;br /&gt;
@param {table} options  various styling/display options&lt;br /&gt;
  @param {string} options.align  &amp;quot;left&amp;quot; or &amp;quot;center&amp;quot; or &amp;quot;right&amp;quot;&lt;br /&gt;
  @param {string|number} options.width  Width of the base map, e.g. &amp;quot;300&amp;quot;&lt;br /&gt;
  @param {string|number} options.width  Height of the base map, e.g. &amp;quot;200&amp;quot;&lt;br /&gt;
  @param {string} options.border  Border style for the overlayed map, e.g. &amp;quot;1px solid white&amp;quot;&lt;br /&gt;
  @param {string} options.horizontalAlignment  Horizontal alignment for overlay map, &amp;quot;left&amp;quot; or &amp;quot;right&amp;quot;&lt;br /&gt;
  @param {string|number} options.horizontalOffset  Horizontal offset in pixels from the alignment edge, e.g &amp;quot;10&amp;quot;&lt;br /&gt;
  @param {string} options.verticalAlignment  Vertical alignment for overlay map, &amp;quot;top&amp;quot; or &amp;quot;bottom&amp;quot;&lt;br /&gt;
  @param {string|number} options.verticalOffset  Vertical offset in pixels from the alignment edge, e.g. is &amp;quot;10&amp;quot;&lt;br /&gt;
  @param {boolean} options.isThumbnail  Display in a thumbnail&lt;br /&gt;
  @param {string} [options.caption]  Caption wikitext for thumnail&lt;br /&gt;
@retruns {string} HTML for basemap with overlay&lt;br /&gt;
]]--&lt;br /&gt;
function make.overlayHtml(overlayMap, baseMap, options)&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	local containerFloatClass = &amp;quot;float&amp;quot;..(options.align or &amp;quot;none&amp;quot;)&lt;br /&gt;
	if options.align == &amp;quot;center&amp;quot; then&lt;br /&gt;
		containerFloatClass = &amp;quot;center&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	local containerStyle = {&lt;br /&gt;
		position = &amp;quot;relative&amp;quot;,&lt;br /&gt;
		width = options.width .. &amp;quot;px&amp;quot;,&lt;br /&gt;
		height = options.height .. &amp;quot;px&amp;quot;,&lt;br /&gt;
		overflow = &amp;quot;hidden&amp;quot; -- mobile/minerva tends to add scrollbars for a couple of pixels&lt;br /&gt;
	}&lt;br /&gt;
	if options.align == &amp;quot;center&amp;quot; then&lt;br /&gt;
		containerStyle[&amp;quot;margin-left&amp;quot;] = &amp;quot;auto&amp;quot;&lt;br /&gt;
		containerStyle[&amp;quot;margin-right&amp;quot;] = &amp;quot;auto&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	local container = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mapframe-withOverlay-container&amp;quot;)&lt;br /&gt;
		:addClass(containerFloatClass)&lt;br /&gt;
		:addClass(&amp;quot;noresize&amp;quot;)&lt;br /&gt;
		:css(containerStyle)&lt;br /&gt;
&lt;br /&gt;
	local overlayStyle = {&lt;br /&gt;
		position = &amp;quot;absolute&amp;quot;,&lt;br /&gt;
		[&amp;quot;z-index&amp;quot;] = &amp;quot;1&amp;quot;,&lt;br /&gt;
		border = options.border or &amp;quot;1px solid white&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
	if options.horizontalAlignment == &amp;quot;right&amp;quot; then&lt;br /&gt;
		overlayStyle.right = options.horizontalOffset .. &amp;quot;px&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		overlayStyle.left = options.horizontalOffset .. &amp;quot;px&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if options.verticalAlignment == &amp;quot;bottom&amp;quot; then&lt;br /&gt;
		overlayStyle.bottom = options.verticalOffset .. &amp;quot;px&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		overlayStyle.top = options.verticalOffset .. &amp;quot;px&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	local overlayDiv = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
		:css(overlayStyle)&lt;br /&gt;
		:wikitext(overlayMap)&lt;br /&gt;
&lt;br /&gt;
	container&lt;br /&gt;
		:node(overlayDiv)&lt;br /&gt;
		:wikitext(baseMap)&lt;br /&gt;
&lt;br /&gt;
	if not options.isThumbnail then&lt;br /&gt;
		return tostring(container)&lt;br /&gt;
	end&lt;br /&gt;
	local classlist = container:getAttr(&amp;quot;class&amp;quot;)&lt;br /&gt;
	classlist = mw.ustring.gsub(classlist, &amp;quot;%a*&amp;quot;..options.align, &amp;quot;&amp;quot;)&lt;br /&gt;
	container:attr(&amp;quot;class&amp;quot;, classlist)&lt;br /&gt;
	local outerCountainer = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mapframe-withOverlay-outerContainer&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;mw-kartographer-container&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;thumb&amp;quot;)&lt;br /&gt;
	if options.align == &amp;quot;left&amp;quot; or options.align == &amp;quot;right&amp;quot; then&lt;br /&gt;
		outerCountainer:addClass(&amp;quot;t&amp;quot;..options.align)&lt;br /&gt;
	else -- alignment is &amp;quot;center&amp;quot;&lt;br /&gt;
		outerCountainer&lt;br /&gt;
			:addClass(&amp;quot;tnone&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;center&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	outerCountainer&lt;br /&gt;
		:tag(&amp;quot;div&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;thumbinner&amp;quot;)&lt;br /&gt;
			:css(&amp;quot;width&amp;quot;, options.width..&amp;quot;px&amp;quot;)&lt;br /&gt;
			:node(container)&lt;br /&gt;
			:node(options.caption and mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
				:addClass(&amp;quot;thumbcaption&amp;quot;)&lt;br /&gt;
				:wikitext(options.caption)&lt;br /&gt;
			)&lt;br /&gt;
	return tostring(outerCountainer)&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[----------------------------------------------------------------------------&lt;br /&gt;
 Package to be exported, i.e. methods which will available to templates and&lt;br /&gt;
 other modules.&lt;br /&gt;
----------------------------------------------------------------------------]]--&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Entry point for templates&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local parent = frame.getParent(frame)&lt;br /&gt;
	-- Check for overlay option&lt;br /&gt;
	local overlay = util.getParameterValue(parent.args, &#039;overlay&#039;)&lt;br /&gt;
	local hasOverlay = overlay and mw.text.trim(overlay) ~= &amp;quot;&amp;quot;&lt;br /&gt;
	-- Check for switch option&lt;br /&gt;
	local switch = util.getParameterValue(parent.args, &#039;switch&#039;)&lt;br /&gt;
	local isMulti = switch and mw.text.trim(switch) ~= &amp;quot;&amp;quot;&lt;br /&gt;
	-- Create output by choosing method to suit options&lt;br /&gt;
	local output&lt;br /&gt;
	if hasOverlay then&lt;br /&gt;
		output = p.withOverlay(parent.args)&lt;br /&gt;
	elseif isMulti then&lt;br /&gt;
		output = p.multi(parent.args)&lt;br /&gt;
	else&lt;br /&gt;
		output = p._main(parent.args)&lt;br /&gt;
	end&lt;br /&gt;
	-- Preprocess output before returning it&lt;br /&gt;
	return frame:preprocess(output)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Entry points for modules&lt;br /&gt;
function p._main(_args)&lt;br /&gt;
	local args = util.trimArgs(_args)&lt;br /&gt;
&lt;br /&gt;
	local tagContent = make.content(args)&lt;br /&gt;
&lt;br /&gt;
	local display = mw.text.split(util.getParameterValue(args, &#039;display&#039;) or L10n.defaults.display, &#039;%s*&#039; .. L10n.str.dsep .. &#039;%s*&#039;)&lt;br /&gt;
	local displayInTitle = display[1] ==  L10n.str.title or display[2] ==  L10n.str.title&lt;br /&gt;
	local displayInline = display[1] ==  L10n.str.inline or display[2] ==  L10n.str.inline&lt;br /&gt;
&lt;br /&gt;
	local output&lt;br /&gt;
	if displayInTitle and displayInline then&lt;br /&gt;
		output = make.titleOutput(args, tagContent) .. make.inlineOutput(args, tagContent)&lt;br /&gt;
	elseif displayInTitle then&lt;br /&gt;
		output = make.titleOutput(args, tagContent)&lt;br /&gt;
	elseif displayInline then&lt;br /&gt;
		output = make.inlineOutput(args, tagContent)&lt;br /&gt;
	else&lt;br /&gt;
		error(L10n.error.badDisplayPara)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.multi(_args)&lt;br /&gt;
	local args = util.trimArgs(_args)&lt;br /&gt;
	if not args[L10n.para.switch] then error(L10n.error.noSwitchPara, 0) end&lt;br /&gt;
	local switchParamValue = util.getParameterValue(args, &#039;switch&#039;)&lt;br /&gt;
	local switchLabels = util.tableFromList(switchParamValue)&lt;br /&gt;
	if #switchLabels == 1 then error(L10n.error.oneSwitchLabel, 0) end&lt;br /&gt;
&lt;br /&gt;
	local mapframeArgs = {}&lt;br /&gt;
	local switchParams = {}&lt;br /&gt;
	for name, val in pairs(args) do&lt;br /&gt;
		-- Copy to mapframeArgs, if not the switch labels or a switch parameter&lt;br /&gt;
		if val ~= switchParamValue and not string.match(val, &amp;quot;^&amp;quot;..L10n.str.switch..&amp;quot;:&amp;quot;) then&lt;br /&gt;
			mapframeArgs[name] = val&lt;br /&gt;
		end&lt;br /&gt;
		-- Check if this is a param to switch. If so, store the name and switch&lt;br /&gt;
		-- values in switchParams table.&lt;br /&gt;
		local switchList = string.match(val, &amp;quot;^&amp;quot;..L10n.str.switch..&amp;quot;:(.+)&amp;quot;)&lt;br /&gt;
		if switchList ~= nil then&lt;br /&gt;
			local values = util.tableFromList(switchList)&lt;br /&gt;
			if #values == 1 then&lt;br /&gt;
				error(string.format(L10n.error.oneSwitchValue, name), 0)&lt;br /&gt;
			end&lt;br /&gt;
			switchParams[name] = values&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if util.tableCount(switchParams) == 0 then&lt;br /&gt;
		error(L10n.error.noSwitchLists, 0)&lt;br /&gt;
	end&lt;br /&gt;
	local switchCount = util.subTablesCount(switchParams)&lt;br /&gt;
	if not switchCount then&lt;br /&gt;
		error(L10n.error.switchMismatches, 0)&lt;br /&gt;
	elseif switchCount &amp;gt; #switchLabels then&lt;br /&gt;
		error(string.format(L10n.error.fewerSwitchLabels, switchCount, #switchLabels), 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Ensure a plain frame will be used (thumbnail will be built by the&lt;br /&gt;
	-- make.switcherHtml function if required, so that switcher options are&lt;br /&gt;
	-- inside the thumnail)&lt;br /&gt;
	mapframeArgs.plain = &amp;quot;yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local switcher = {}&lt;br /&gt;
	for i = 1, switchCount do&lt;br /&gt;
		local label = switchLabels[i]&lt;br /&gt;
		for name, values in pairs(switchParams) do&lt;br /&gt;
			mapframeArgs[name] = values[i]&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(switcher, {&lt;br /&gt;
			map = p._main(mapframeArgs),&lt;br /&gt;
			label = &amp;quot;Show &amp;quot;..label&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	return make.switcherHtml(switcher, {&lt;br /&gt;
		alignment = args[&amp;quot;frame-align&amp;quot;] or &amp;quot;right&amp;quot;,&lt;br /&gt;
		isThumbnail = (args.frame and not args.plain) and true or false,&lt;br /&gt;
		width = args[&amp;quot;frame-width&amp;quot;] or L10n.defaults.frameWidth,&lt;br /&gt;
		caption = args.text&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.withOverlay(_args)&lt;br /&gt;
	-- Get and trim wikitext for overlay map&lt;br /&gt;
	local overlayMap = _args.overlay&lt;br /&gt;
	if type(overlayMap) == &#039;string&#039; then&lt;br /&gt;
		overlayMap = overlayMap:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local isThumbnail = (util.getParameterValue(_args, &amp;quot;frame&amp;quot;) and not util.getParameterValue(_args, &amp;quot;plain&amp;quot;)) and true or false&lt;br /&gt;
	-- Get base map using the _main function, as a plain map&lt;br /&gt;
	local args = util.trimArgs(_args)&lt;br /&gt;
	args.plain = &amp;quot;yes&amp;quot;&lt;br /&gt;
	local basemap = p._main(args)&lt;br /&gt;
	-- Extract overlay options from args&lt;br /&gt;
	local overlayOptions = {&lt;br /&gt;
		width = util.getParameterValue(args, &amp;quot;frameWidth&amp;quot;) or L10n.defaults.frameWidth,&lt;br /&gt;
		height = util.getParameterValue(args, &amp;quot;frameHeight&amp;quot;) or L10n.defaults.frameHeight,&lt;br /&gt;
		align = util.getParameterValue(args, &amp;quot;frameAlign&amp;quot;) or L10n.defaults.frameAlign,&lt;br /&gt;
		border = util.getParameterValue(args, &amp;quot;overlayBorder&amp;quot;) or L10n.defaults.overlayBorder,&lt;br /&gt;
		horizontalAlignment = util.getParameterValue(args, &amp;quot;overlayHorizontalAlignment&amp;quot;) or L10n.defaults.overlayHorizontalAlignment,&lt;br /&gt;
		horizontalOffset = util.getParameterValue(args, &amp;quot;overlayHorizontalOffset&amp;quot;) or L10n.defaults.overlayHorizontalOffset,&lt;br /&gt;
		verticalAlignment = util.getParameterValue(args, &amp;quot;overlayVerticalAlignment&amp;quot;) or L10n.defaults.overlayVerticalAlignment,&lt;br /&gt;
		verticalOffset = util.getParameterValue(args, &amp;quot;overlayVerticalOffset&amp;quot;) or L10n.defaults.overlayVerticalOffset,&lt;br /&gt;
		isThumbnail = isThumbnail,&lt;br /&gt;
		caption = util.getParameterValue(args, &amp;quot;text&amp;quot;) or L10n.defaults.text&lt;br /&gt;
	}&lt;br /&gt;
	-- Make the HTML for the overlaying maps&lt;br /&gt;
	return make.overlayHtml(overlayMap, basemap, overlayOptions)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Entry point for testcase tests&lt;br /&gt;
p.test = util&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:TableTools&amp;diff=78</id>
		<title>Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:TableTools&amp;diff=78"/>
		<updated>2026-06-22T02:04:11Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;------------------------------------------------------------------------------------ --                                   TableTools                                   -- --                                                                                -- -- This module includes a number of functions for dealing with Lua tables.        -- -- It is a meta-module, meant to be called from other Lua modules, and should not -- -- be called directly from #invoke....&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;------------------------------------------------------------------------------------&lt;br /&gt;
--                                   TableTools                                   --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.        --&lt;br /&gt;
-- It is a meta-module, meant to be called from other Lua modules, and should not --&lt;br /&gt;
-- be called directly from #invoke.                                               --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeMulti = libraryUtil.checkTypeMulti&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isPositiveInteger&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given value is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn&#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isPositiveInteger(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and v &amp;gt;= 1 and floor(v) == v and v &amp;lt; infinity&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isNan&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given number is a NaN value, and false if&lt;br /&gt;
-- not. Although it doesn&#039;t operate on tables, it is included here as it is useful&lt;br /&gt;
-- for determining whether a value can be a valid table key. Lua will generate an&lt;br /&gt;
-- error if a NaN is used as a table key.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isNan(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and v ~= v&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- shallowClone&lt;br /&gt;
--&lt;br /&gt;
-- This returns a clone of a table. The value returned is a new table, but all&lt;br /&gt;
-- subtables and functions are shared. Metamethods are respected, but the returned&lt;br /&gt;
-- table will have no metatable of its own.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.shallowClone(t)&lt;br /&gt;
	checkType(&#039;shallowClone&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		ret[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- removeDuplicates&lt;br /&gt;
--&lt;br /&gt;
-- This removes duplicate values from an array. Non-positive-integer keys are&lt;br /&gt;
-- ignored. The earliest value is kept, and all subsequent duplicate values are&lt;br /&gt;
-- removed, but otherwise the array order is unchanged.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.removeDuplicates(arr)&lt;br /&gt;
	checkType(&#039;removeDuplicates&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for _, v in ipairs(arr) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs can&#039;t be table keys, and they are also unique, so we don&#039;t need to check existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		elseif not exists[v] then&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
			exists[v] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numKeys&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType(&#039;numKeys&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- affixNums&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = &#039;foo&#039;, a3 = &#039;bar&#039;, a6 = &#039;baz&#039;} and the prefix &amp;quot;a&amp;quot;, affixNums will return&lt;br /&gt;
-- {1, 3, 6}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 3, suffix, &#039;string&#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local function cleanPattern(s)&lt;br /&gt;
		-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.&lt;br /&gt;
		return s:gsub(&#039;([%(%)%%%.%[%]%*%+%-%?%^%$])&#039;, &#039;%%%1&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	prefix = prefix or &#039;&#039;&lt;br /&gt;
	suffix = suffix or &#039;&#039;&lt;br /&gt;
	prefix = cleanPattern(prefix)&lt;br /&gt;
	suffix = cleanPattern(suffix)&lt;br /&gt;
	local pattern = &#039;^&#039; .. prefix .. &#039;([1-9]%d*)&#039; .. suffix .. &#039;$&#039;&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		if type(k) == &#039;string&#039; then&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numData&lt;br /&gt;
--&lt;br /&gt;
-- Given a table with keys like {&amp;quot;foo1&amp;quot;, &amp;quot;bar1&amp;quot;, &amp;quot;foo2&amp;quot;, &amp;quot;baz2&amp;quot;}, returns a table&lt;br /&gt;
-- of subtables in the format&lt;br /&gt;
-- {[1] = {foo = &#039;text&#039;, bar = &#039;text&#039;}, [2] = {foo = &#039;text&#039;, baz = &#039;text&#039;}}.&lt;br /&gt;
-- Keys that don&#039;t end with an integer are stored in a subtable named &amp;quot;other&amp;quot;. The&lt;br /&gt;
-- compress option compresses the table so that it can be iterated over with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numData(t, compress)&lt;br /&gt;
	checkType(&#039;numData&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;numData&#039;, 2, compress, &#039;boolean&#039;, true)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		local prefix, num = mw.ustring.match(tostring(k), &#039;^([^0-9]*)([1-9][0-9]*)$&#039;)&lt;br /&gt;
		if num then&lt;br /&gt;
			num = tonumber(num)&lt;br /&gt;
			local subtable = ret[num] or {}&lt;br /&gt;
			if prefix == &#039;&#039; then&lt;br /&gt;
				-- Positional parameters match the blank string; put them at the start of the subtable instead.&lt;br /&gt;
				prefix = 1&lt;br /&gt;
			end&lt;br /&gt;
			subtable[prefix] = v&lt;br /&gt;
			ret[num] = subtable&lt;br /&gt;
		else&lt;br /&gt;
			local subtable = ret.other or {}&lt;br /&gt;
			subtable[k] = v&lt;br /&gt;
			ret.other = subtable&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if compress then&lt;br /&gt;
		local other = ret.other&lt;br /&gt;
		ret = p.compressSparseArray(ret)&lt;br /&gt;
		ret.other = other&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- compressSparseArray&lt;br /&gt;
--&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType(&#039;compressSparseArray&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseIpairs&lt;br /&gt;
--&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType(&#039;sparseIpairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- size&lt;br /&gt;
--&lt;br /&gt;
-- This returns the size of a key/value pair table. It will also work on arrays,&lt;br /&gt;
-- but for arrays it is more efficient to use the # operator.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.size(t)&lt;br /&gt;
	checkType(&#039;size&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function defaultKeySort(item1, item2)&lt;br /&gt;
	-- &amp;quot;number&amp;quot; &amp;lt; &amp;quot;string&amp;quot;, so numbers will be sorted before strings.&lt;br /&gt;
	local type1, type2 = type(item1), type(item2)&lt;br /&gt;
	if type1 ~= type2 then&lt;br /&gt;
		return type1 &amp;lt; type2&lt;br /&gt;
	elseif type1 == &#039;table&#039; or type1 == &#039;boolean&#039; or type1 == &#039;function&#039; then&lt;br /&gt;
		return tostring(item1) &amp;lt; tostring(item2)&lt;br /&gt;
	else&lt;br /&gt;
		return item1 &amp;lt; item2&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- keysToList&lt;br /&gt;
--&lt;br /&gt;
-- Returns an array of the keys in a table, sorted using either a default&lt;br /&gt;
-- comparison function or a custom keySort function.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.keysToList(t, keySort, checked)&lt;br /&gt;
	if not checked then&lt;br /&gt;
		checkType(&#039;keysToList&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
		checkTypeMulti(&#039;keysToList&#039;, 2, keySort, {&#039;function&#039;, &#039;boolean&#039;, &#039;nil&#039;})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local arr = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		arr[index] = k&lt;br /&gt;
		index = index + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if keySort ~= false then&lt;br /&gt;
		keySort = type(keySort) == &#039;function&#039; and keySort or defaultKeySort&lt;br /&gt;
		table.sort(arr, keySort)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return arr&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sortedPairs&lt;br /&gt;
--&lt;br /&gt;
-- Iterates through a table, with the keys sorted using the keysToList function.&lt;br /&gt;
-- If there are only numerical keys, sparseIpairs is probably more efficient.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sortedPairs(t, keySort)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 2, keySort, &#039;function&#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local arr = p.keysToList(t, keySort, true)&lt;br /&gt;
&lt;br /&gt;
	local i = 0&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		local key = arr[i]&lt;br /&gt;
		if key ~= nil then&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isArray&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if the given value is a table and all keys are consecutive&lt;br /&gt;
-- integers starting at 1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isArray(v)&lt;br /&gt;
	if type(v) ~= &#039;table&#039; then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(v) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if v[i] == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isArrayLike&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if the given value is iterable and all keys are consecutive&lt;br /&gt;
-- integers starting at 1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isArrayLike(v)&lt;br /&gt;
	if not pcall(pairs, v) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(v) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if v[i] == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- invert&lt;br /&gt;
--&lt;br /&gt;
-- Transposes the keys and values in an array. For example, {&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;} -&amp;gt;&lt;br /&gt;
-- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to&lt;br /&gt;
-- the index of the last duplicate) and NaN values are ignored.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.invert(arr)&lt;br /&gt;
	checkType(&amp;quot;invert&amp;quot;, 1, arr, &amp;quot;table&amp;quot;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local map = {}&lt;br /&gt;
	for i, v in ipairs(arr) do&lt;br /&gt;
		if not isNan(v) then&lt;br /&gt;
			map[v] = i&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return map&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- listToSet&lt;br /&gt;
--&lt;br /&gt;
-- Creates a set from the array part of the table. Indexing the set by any of the&lt;br /&gt;
-- values of the array returns true. For example, {&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;} -&amp;gt;&lt;br /&gt;
-- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them&lt;br /&gt;
-- never equal to any value (including other NaNs or even themselves).&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.listToSet(arr)&lt;br /&gt;
	checkType(&amp;quot;listToSet&amp;quot;, 1, arr, &amp;quot;table&amp;quot;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local set = {}&lt;br /&gt;
	for _, v in ipairs(arr) do&lt;br /&gt;
		if not isNan(v) then&lt;br /&gt;
			set[v] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return set&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- deepCopy&lt;br /&gt;
--&lt;br /&gt;
-- Recursive deep copy function. Preserves identities of subtables.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
local function _deepCopy(orig, includeMetatable, already_seen)&lt;br /&gt;
	if type(orig) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
		return orig&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- already_seen stores copies of tables indexed by the original table.&lt;br /&gt;
	local copy = already_seen[orig]&lt;br /&gt;
	if copy ~= nil then&lt;br /&gt;
		return copy&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	copy = {}&lt;br /&gt;
	already_seen[orig] = copy -- memoize before any recursion, to avoid infinite loops&lt;br /&gt;
	&lt;br /&gt;
	for orig_key, orig_value in pairs(orig) do&lt;br /&gt;
		copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if includeMetatable then&lt;br /&gt;
		local mt = getmetatable(orig)&lt;br /&gt;
		if mt ~= nil then&lt;br /&gt;
			setmetatable(copy, _deepCopy(mt, true, already_seen))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return copy&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.deepCopy(orig, noMetatable, already_seen)&lt;br /&gt;
	checkType(&amp;quot;deepCopy&amp;quot;, 3, already_seen, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	return _deepCopy(orig, not noMetatable, already_seen or {})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseConcat&lt;br /&gt;
--&lt;br /&gt;
-- Concatenates all values in the table that are indexed by a number, in order.&lt;br /&gt;
-- sparseConcat{a, nil, c, d}  =&amp;gt;  &amp;quot;acd&amp;quot;&lt;br /&gt;
-- sparseConcat{nil, b, c, d}  =&amp;gt;  &amp;quot;bcd&amp;quot;&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sparseConcat(t, sep, i, j)&lt;br /&gt;
	local arr = {}&lt;br /&gt;
&lt;br /&gt;
	local arr_i = 0&lt;br /&gt;
	for _, v in p.sparseIpairs(t) do&lt;br /&gt;
		arr_i = arr_i + 1&lt;br /&gt;
		arr[arr_i] = v&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat(arr, sep, i, j)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- length&lt;br /&gt;
--&lt;br /&gt;
-- Finds the length of an array, or of a quasi-array with keys such as &amp;quot;data1&amp;quot;,&lt;br /&gt;
-- &amp;quot;data2&amp;quot;, etc., using an exponential search algorithm. It is similar to the&lt;br /&gt;
-- operator #, but may return a different value when there are gaps in the array&lt;br /&gt;
-- portion of the table. Intended to be used on data loaded with mw.loadData. For&lt;br /&gt;
-- other tables, use #.&lt;br /&gt;
-- Note: #frame.args in frame object always be set to 0, regardless of  the number&lt;br /&gt;
-- of unnamed template parameters, so use this function for frame.args.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.length(t, prefix)&lt;br /&gt;
	-- requiring module inline so that [[Module:Exponential search]] which is&lt;br /&gt;
	-- only needed by this one function doesn&#039;t get millions of transclusions&lt;br /&gt;
	local expSearch = require(&amp;quot;Module:Exponential search&amp;quot;)&lt;br /&gt;
	checkType(&#039;length&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;length&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	return expSearch(function (i)&lt;br /&gt;
		local key&lt;br /&gt;
		if prefix then&lt;br /&gt;
			key = prefix .. tostring(i)&lt;br /&gt;
		else&lt;br /&gt;
			key = i&lt;br /&gt;
		end&lt;br /&gt;
		return t[key] ~= nil&lt;br /&gt;
	end) or 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- inArray&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if searchElement is a member of the array, and false otherwise.&lt;br /&gt;
-- Equivalent to JavaScript array.includes(searchElement) or&lt;br /&gt;
-- array.includes(searchElement, fromIndex), except fromIndex is 1 indexed&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.inArray(array, searchElement, fromIndex)&lt;br /&gt;
	checkType(&amp;quot;inArray&amp;quot;, 1, array, &amp;quot;table&amp;quot;)&lt;br /&gt;
	-- if searchElement is nil, error?&lt;br /&gt;
&lt;br /&gt;
	fromIndex = tonumber(fromIndex)&lt;br /&gt;
	if fromIndex then&lt;br /&gt;
		if (fromIndex &amp;lt; 0) then&lt;br /&gt;
			fromIndex = #array + fromIndex + 1&lt;br /&gt;
		end&lt;br /&gt;
		if fromIndex &amp;lt; 1 then fromIndex = 1 end&lt;br /&gt;
		for _, v in ipairs({unpack(array, fromIndex)}) do&lt;br /&gt;
			if v == searchElement then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		for _, v in pairs(array) do&lt;br /&gt;
			if v == searchElement then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- merge&lt;br /&gt;
--&lt;br /&gt;
-- Given the arrays, returns an array containing the elements of each input array&lt;br /&gt;
-- in sequence.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.merge(...)&lt;br /&gt;
	local arrays = {...}&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, arr in ipairs(arrays) do&lt;br /&gt;
		checkType(&#039;merge&#039;, i, arr, &#039;table&#039;)&lt;br /&gt;
		for _, v in ipairs(arr) do&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- extend&lt;br /&gt;
--&lt;br /&gt;
-- Extends the first array in place by appending all elements from the second&lt;br /&gt;
-- array.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.extend(arr1, arr2)&lt;br /&gt;
	checkType(&#039;extend&#039;, 1, arr1, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;extend&#039;, 2, arr2, &#039;table&#039;)&lt;br /&gt;
&lt;br /&gt;
	for _, v in ipairs(arr2) do&lt;br /&gt;
		arr1[#arr1 + 1] = v&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Separated_entries&amp;diff=77</id>
		<title>Module:Separated entries</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Separated_entries&amp;diff=77"/>
		<updated>2026-06-22T02:03:44Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;-- This module takes positional parameters as input and concatenates them with -- an optional separator. The final separator (the &amp;quot;conjunction&amp;quot;) can be -- specified independently, enabling natural-language lists like -- &amp;quot;foo, bar, baz and qux&amp;quot;. The starting parameter can also be specified.  local compressSparseArray = require(&amp;#039;Module:TableTools&amp;#039;).compressSparseArray local p = {}  function p._main(args) 	local dataPlural = args.dataPlural 	local separator = args.separator...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module takes positional parameters as input and concatenates them with&lt;br /&gt;
-- an optional separator. The final separator (the &amp;quot;conjunction&amp;quot;) can be&lt;br /&gt;
-- specified independently, enabling natural-language lists like&lt;br /&gt;
-- &amp;quot;foo, bar, baz and qux&amp;quot;. The starting parameter can also be specified.&lt;br /&gt;
&lt;br /&gt;
local compressSparseArray = require(&#039;Module:TableTools&#039;).compressSparseArray&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local dataPlural = args.dataPlural&lt;br /&gt;
	local separator = args.separator&lt;br /&gt;
		-- Decode (convert to Unicode) HTML escape sequences, such as &amp;quot;&amp;amp;#32;&amp;quot; for space.&lt;br /&gt;
		and mw.text.decode(args.separator) or &#039;&#039;&lt;br /&gt;
	local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator&lt;br /&gt;
	-- Discard values before the starting parameter.&lt;br /&gt;
	local start = tonumber(args.start)&lt;br /&gt;
	if start then&lt;br /&gt;
		for i = 1, start - 1 do args[i] = nil end&lt;br /&gt;
	end&lt;br /&gt;
	-- Discard named parameters.&lt;br /&gt;
	local values = compressSparseArray(args)&lt;br /&gt;
	local result = mw.text.listToText(values, separator, conjunction)&lt;br /&gt;
	if dataPlural and #values &amp;gt; 0 and (#separator &amp;gt; 0 or #conjunction &amp;gt; 0) then&lt;br /&gt;
		-- flag to [[Module:Detect singular]] whether this is a list with &amp;gt;1 element&lt;br /&gt;
		result = result..&#039;&amp;lt;span style=&amp;quot;display:none&amp;quot; data-plural=&amp;quot;&#039;..(#values &amp;gt; 1 and &#039;1&#039; or &#039;0&#039;)..&#039;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeInvokeFunction(separator, conjunction, first)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {frameOnly = (frame.args.frameOnly or &#039;&#039;) ~= &#039;&#039;})&lt;br /&gt;
		args.separator = separator or args.separator&lt;br /&gt;
		args.conjunction = conjunction or args.conjunction&lt;br /&gt;
		args.first = first or args.first&lt;br /&gt;
		return p._main(args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.main = makeInvokeFunction()&lt;br /&gt;
p.br = makeInvokeFunction(&#039;&amp;lt;br /&amp;gt;&#039;)&lt;br /&gt;
p.comma = makeInvokeFunction(mw.message.new(&#039;comma-separator&#039;):plain())&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Br_separated_entries&amp;diff=76</id>
		<title>Template:Br separated entries</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Br_separated_entries&amp;diff=76"/>
		<updated>2026-06-22T02:03:20Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Separated entries|br|dataPlural=1}}&amp;lt;noinclude&amp;gt; {{documentation}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Separated entries|br|dataPlural=1}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:InfoboxImage&amp;diff=75</id>
		<title>Module:InfoboxImage</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:InfoboxImage&amp;diff=75"/>
		<updated>2026-06-22T02:02:54Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;-- Inputs: --    image - Can either be a bare filename (with or without the File:/Image: prefix) or a fully formatted image link --    page - page to display for multipage images (DjVu) --    size - size to display the image --    maxsize - maximum size for image --    sizedefault - default size to display the image if size param is blank --    alt - alt text for image --    title - title text for image --    border - set to yes if border --    center - set to yes, if th...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Inputs:&lt;br /&gt;
--    image - Can either be a bare filename (with or without the File:/Image: prefix) or a fully formatted image link&lt;br /&gt;
--    page - page to display for multipage images (DjVu)&lt;br /&gt;
--    size - size to display the image&lt;br /&gt;
--    maxsize - maximum size for image&lt;br /&gt;
--    sizedefault - default size to display the image if size param is blank&lt;br /&gt;
--    alt - alt text for image&lt;br /&gt;
--    title - title text for image&lt;br /&gt;
--    border - set to yes if border&lt;br /&gt;
--    center - set to yes, if the image has to be centered&lt;br /&gt;
--    upright - upright image param&lt;br /&gt;
--    suppressplaceholder - if yes then checks to see if image is a placeholder and suppresses it&lt;br /&gt;
--    link - page to visit when clicking on image&lt;br /&gt;
--    class - HTML classes to add to the image&lt;br /&gt;
-- Outputs:&lt;br /&gt;
--    Formatted image.&lt;br /&gt;
-- More details available at the &amp;quot;Module:InfoboxImage/doc&amp;quot; page&lt;br /&gt;
&lt;br /&gt;
local i = {}&lt;br /&gt;
&lt;br /&gt;
-- List of placeholder images and tracking categories stored in [[Module:InfoboxImage/data]]&lt;br /&gt;
-- Other constants:&lt;br /&gt;
--   the system-wide default thumbnail size (in px)&lt;br /&gt;
local defaultThumbnailSize = 250&lt;br /&gt;
&lt;br /&gt;
-- If page is not a user page, return tracking category. Else return empty.&lt;br /&gt;
local function trackingCat(cat)&lt;br /&gt;
	local ns = mw.title.getCurrentTitle().nsText:lower()&lt;br /&gt;
    local categories = mw.loadData(&#039;Module:InfoboxImage/data&#039;).categories&lt;br /&gt;
	return (ns ~= &#039;user&#039; and ns ~= &#039;user talk&#039; and categories[cat]) or &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Determine whether image is a placeholder&lt;br /&gt;
function i.IsPlaceholder(image)&lt;br /&gt;
    -- change underscores to spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &amp;quot;_&amp;quot;, &amp;quot; &amp;quot;);&lt;br /&gt;
    assert(image ~= nil, &#039;mw.ustring.gsub(image, &amp;quot;_&amp;quot;, &amp;quot; &amp;quot;) must not return nil&#039;)&lt;br /&gt;
    -- if image starts with [[ then remove that and anything after |&lt;br /&gt;
    if mw.ustring.sub(image,1,2) == &amp;quot;[[&amp;quot; then&lt;br /&gt;
        image = mw.ustring.sub(image,3);&lt;br /&gt;
        image = mw.ustring.gsub(image, &amp;quot;([^|]*)|.*&amp;quot;, &amp;quot;%1&amp;quot;);&lt;br /&gt;
        assert(image ~= nil, &#039;mw.ustring.gsub(image, &amp;quot;([^|]*)|.*&amp;quot;, &amp;quot;%1&amp;quot;) must not return nil&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    -- Trim spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;);&lt;br /&gt;
    assert(image ~= nil, &amp;quot;mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;) must not return nil&amp;quot;)&lt;br /&gt;
    -- remove prefix if exists&lt;br /&gt;
    local allNames = mw.site.namespaces[6].aliases&lt;br /&gt;
    allNames[#allNames + 1] = mw.site.namespaces[6].name&lt;br /&gt;
    allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName&lt;br /&gt;
    for i, name in ipairs(allNames) do&lt;br /&gt;
        if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. &amp;quot;:&amp;quot;) then&lt;br /&gt;
            image = mw.ustring.sub(image, mw.ustring.len(name) + 2);&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Trim spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;);&lt;br /&gt;
    -- capitalise first letter&lt;br /&gt;
    image = mw.ustring.upper(mw.ustring.sub(image,1,1)) .. mw.ustring.sub(image,2);&lt;br /&gt;
&lt;br /&gt;
    local placeholder_image = mw.loadData(&#039;Module:InfoboxImage/data&#039;).placeholder_image&lt;br /&gt;
    return placeholder_image[image]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isempty(x)&lt;br /&gt;
    return (not x) or x == &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Main entry point&lt;br /&gt;
function i.InfoboxImage(frame)&lt;br /&gt;
    local image = frame.args[&amp;quot;image&amp;quot;];&lt;br /&gt;
    &lt;br /&gt;
    if isempty(image) then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if image == &amp;quot;&amp;amp;nbsp;&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    end&lt;br /&gt;
    if frame.args[&amp;quot;suppressplaceholder&amp;quot;] ~= &amp;quot;no&amp;quot; then&lt;br /&gt;
        if i.IsPlaceholder(image) == true then&lt;br /&gt;
            return &amp;quot;&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if string.find(image, &amp;quot;^%[*https?:&amp;quot;) then&lt;br /&gt;
		-- Error category.&lt;br /&gt;
		return trackingCat(&amp;quot;url_image_links&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    if mw.ustring.sub(image,1,2) == &amp;quot;[[&amp;quot; then&lt;br /&gt;
        -- search for thumbnail images and add to tracking cat if found&lt;br /&gt;
        local cat = &amp;quot;&amp;quot;;&lt;br /&gt;
        if mw.title.getCurrentTitle().namespace == 0 and (mw.ustring.find(image, &amp;quot;|%s*thumb%s*[|%]]&amp;quot;) or mw.ustring.find(image, &amp;quot;|%s*thumbnail%s*[|%]]&amp;quot;)) then&lt;br /&gt;
            cat = trackingCat(&amp;quot;thumbnail_images&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        return image .. cat;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,2) == &amp;quot;{{&amp;quot; and mw.ustring.sub(image,1,3) ~= &amp;quot;{{{&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,1) == &amp;quot;&amp;lt;&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,8) == mw.ustring.char(127)..&amp;quot;&#039;\&amp;quot;`UNIQ&amp;quot; then&lt;br /&gt;
        -- Found strip marker at begining, so pass don&#039;t process at all&lt;br /&gt;
        return image;&lt;br /&gt;
    else&lt;br /&gt;
        local result = &amp;quot;&amp;quot;;&lt;br /&gt;
        local page = frame.args[&amp;quot;page&amp;quot;];&lt;br /&gt;
        local upright = frame.args[&amp;quot;upright&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
        local size = frame.args[&amp;quot;size&amp;quot;];&lt;br /&gt;
        local maxsize = frame.args[&amp;quot;maxsize&amp;quot;];&lt;br /&gt;
        local sizedefault = frame.args[&amp;quot;sizedefault&amp;quot;];&lt;br /&gt;
        local alt = frame.args[&amp;quot;alt&amp;quot;];&lt;br /&gt;
        local link = frame.args[&amp;quot;link&amp;quot;];&lt;br /&gt;
        local title = frame.args[&amp;quot;title&amp;quot;];&lt;br /&gt;
        local border = frame.args[&amp;quot;border&amp;quot;];&lt;br /&gt;
        local thumbtime = frame.args[&amp;quot;thumbtime&amp;quot;] or &amp;quot;&amp;quot;;&lt;br /&gt;
        local center = frame.args[&amp;quot;center&amp;quot;];&lt;br /&gt;
        local class = frame.args[&amp;quot;class&amp;quot;];&lt;br /&gt;
        &lt;br /&gt;
        -- remove prefix if exists&lt;br /&gt;
        local allNames = mw.site.namespaces[6].aliases&lt;br /&gt;
        allNames[#allNames + 1] = mw.site.namespaces[6].name&lt;br /&gt;
        allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName&lt;br /&gt;
        for i, name in ipairs(allNames) do&lt;br /&gt;
            if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. &amp;quot;:&amp;quot;) then&lt;br /&gt;
                image = mw.ustring.sub(image, mw.ustring.len(name) + 2);&lt;br /&gt;
                break&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        if not isempty(maxsize) then&lt;br /&gt;
            -- if no sizedefault nor upright, then set to maxsize&lt;br /&gt;
            if isempty(sizedefault) and isempty(upright) then&lt;br /&gt;
                sizedefault = maxsize&lt;br /&gt;
            end&lt;br /&gt;
            -- check to see if size bigger than maxsize&lt;br /&gt;
            local maxsizenumber = tonumber(mw.ustring.match(maxsize,&amp;quot;%d*&amp;quot;)) or 0;&lt;br /&gt;
            if not isempty(size) then&lt;br /&gt;
                local sizenumber = tonumber(mw.ustring.match(size,&amp;quot;%d*&amp;quot;)) or 0;&lt;br /&gt;
                if sizenumber &amp;gt; maxsizenumber and maxsizenumber &amp;gt; 0 then&lt;br /&gt;
                    size = maxsize;&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            -- check to see if upright bigger than maxsize (at default preferred size)&lt;br /&gt;
            if not isempty(upright) then&lt;br /&gt;
                local uprightnumber = tonumber(upright) or (upright == &amp;quot;yes&amp;quot; and 0.75) or 0&lt;br /&gt;
                if uprightnumber*defaultThumbnailSize &amp;gt; maxsizenumber and maxsizenumber &amp;gt; 0 then&lt;br /&gt;
                    upright = tostring(maxsizenumber/defaultThumbnailSize)&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- add px to size if just a number&lt;br /&gt;
        if (tonumber(size) or 0) &amp;gt; 0 then&lt;br /&gt;
            size = size .. &amp;quot;px&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        -- add px to sizedefault if just a number&lt;br /&gt;
        if (tonumber(sizedefault) or 0) &amp;gt; 0 then&lt;br /&gt;
            sizedefault = sizedefault .. &amp;quot;px&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        result = &amp;quot;[[File:&amp;quot; .. image;&lt;br /&gt;
        if not isempty(page) then&lt;br /&gt;
            result = result .. &amp;quot;|page=&amp;quot; .. page;&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(size) then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. size;&lt;br /&gt;
        elseif not isempty(sizedefault) and isempty(upright) then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. sizedefault;&lt;br /&gt;
        else&lt;br /&gt;
            result = result .. &amp;quot;|frameless&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        if center == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|center&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(alt) then&lt;br /&gt;
            result = result .. &amp;quot;|alt=&amp;quot; .. alt;&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(link) then&lt;br /&gt;
            result = result .. &amp;quot;|link=&amp;quot; .. link;&lt;br /&gt;
        end&lt;br /&gt;
        if border == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|border&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        if upright == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|upright&amp;quot;;&lt;br /&gt;
        elseif upright ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|upright=&amp;quot; .. upright;&lt;br /&gt;
        end&lt;br /&gt;
        if thumbtime ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|thumbtime=&amp;quot; .. thumbtime;&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(class) then&lt;br /&gt;
            result = result .. &amp;quot;|class=&amp;quot; .. class;&lt;br /&gt;
        end&lt;br /&gt;
        -- if alt value is a keyword then do not use as a description&lt;br /&gt;
        if alt == &amp;quot;thumbnail&amp;quot; or alt == &amp;quot;thumb&amp;quot; or alt == &amp;quot;frameless&amp;quot; or alt == &amp;quot;left&amp;quot; or alt == &amp;quot;center&amp;quot; or alt == &amp;quot;right&amp;quot; or alt == &amp;quot;upright&amp;quot; or alt == &amp;quot;border&amp;quot; or mw.ustring.match(alt or &amp;quot;&amp;quot;, &#039;^[0-9]*px$&#039;, 1) ~= nil then&lt;br /&gt;
            alt = nil;&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(title) then&lt;br /&gt;
            -- does title param contain any templatestyles? If yes then set to blank.&lt;br /&gt;
            if mw.ustring.match(frame:preprocess(title), &#039;UNIQ%-%-templatestyles&#039;, 1) ~= nil then&lt;br /&gt;
                title = nil;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if not isempty(title) then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. title;&lt;br /&gt;
        end&lt;br /&gt;
        result = result .. &amp;quot;]]&amp;quot;;&lt;br /&gt;
        &lt;br /&gt;
        return result;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return i;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Module:Infobox_mapframe&amp;diff=74</id>
		<title>Module:Infobox mapframe</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Module:Infobox_mapframe&amp;diff=74"/>
		<updated>2026-06-22T02:01:22Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;local mf = require(&amp;#039;Module:Mapframe&amp;#039;) local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs local yesno = require(&amp;#039;Module:Yesno&amp;#039;) local infoboxImage = require(&amp;#039;Module:InfoboxImage&amp;#039;).InfoboxImage  -- Defaults local DEFAULT_FRAME_WIDTH = &amp;quot;270&amp;quot; local DEFAULT_FRAME_HEIGHT = &amp;quot;200&amp;quot; local DEFAULT_ZOOM = 10 local DEFAULT_GEOMASK_STROKE_WIDTH = &amp;quot;1&amp;quot; local DEFAULT_GEOMASK_STROKE_COLOR = &amp;quot;#777777&amp;quot; local DEFAULT_GEOMASK_FILL = &amp;quot;#888888&amp;quot; local DEFAULT_GEOMASK_FILL_OPACITY = &amp;quot;0.25&amp;quot; local...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local mf = require(&#039;Module:Mapframe&#039;)&lt;br /&gt;
local getArgs = require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
local infoboxImage = require(&#039;Module:InfoboxImage&#039;).InfoboxImage&lt;br /&gt;
&lt;br /&gt;
-- Defaults&lt;br /&gt;
local DEFAULT_FRAME_WIDTH = &amp;quot;270&amp;quot;&lt;br /&gt;
local DEFAULT_FRAME_HEIGHT = &amp;quot;200&amp;quot;&lt;br /&gt;
local DEFAULT_ZOOM = 10&lt;br /&gt;
local DEFAULT_GEOMASK_STROKE_WIDTH = &amp;quot;1&amp;quot;&lt;br /&gt;
local DEFAULT_GEOMASK_STROKE_COLOR = &amp;quot;#777777&amp;quot;&lt;br /&gt;
local DEFAULT_GEOMASK_FILL = &amp;quot;#888888&amp;quot;&lt;br /&gt;
local DEFAULT_GEOMASK_FILL_OPACITY = &amp;quot;0.25&amp;quot;&lt;br /&gt;
local DEFAULT_SHAPE_STROKE_WIDTH = &amp;quot;2&amp;quot;&lt;br /&gt;
local DEFAULT_SHAPE_STROKE_COLOR = &amp;quot;#FF0000&amp;quot;&lt;br /&gt;
local DEFAULT_SHAPE_FILL = &amp;quot;#606060&amp;quot;&lt;br /&gt;
local DEFAULT_SHAPE_FILL_OPACITY = &amp;quot;0.1&amp;quot;&lt;br /&gt;
local DEFAULT_LINE_STROKE_WIDTH = &amp;quot;5&amp;quot;&lt;br /&gt;
local DEFAULT_LINE_STROKE_COLOR = &amp;quot;#FF0000&amp;quot;&lt;br /&gt;
local DEFAULT_MARKER_COLOR = &amp;quot;#5E74F3&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local util = {}&lt;br /&gt;
&lt;br /&gt;
function util.noop(info)&lt;br /&gt;
	local DEFAULT_NOOP_OUTPUT = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	-- uncomment this when debugging&lt;br /&gt;
	-- DEFAULT_NOOP_OUTPUT = &amp;quot;debug: mapframe no-op: &amp;quot; .. info&lt;br /&gt;
	-- mw.log(DEFAULT_NOOP_OUTPUT)&lt;br /&gt;
&lt;br /&gt;
	return DEFAULT_NOOP_OUTPUT&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Trim whitespace from args, and remove empty args&lt;br /&gt;
function util.trimArgs(argsTable)&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for key, val in pairs(argsTable) do&lt;br /&gt;
		if type(val) == &#039;string&#039; then&lt;br /&gt;
			val = val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
			if val ~= &#039;&#039; then&lt;br /&gt;
				cleanArgs[key] = val&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			cleanArgs[key] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return cleanArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.getBestStatement(item_id, property_id)&lt;br /&gt;
	if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local statements = mw.wikibase.getBestStatements(item_id, property_id)&lt;br /&gt;
	if not statements or #statements == 0 then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == &#039;novalue&#039; )&lt;br /&gt;
	if hasNoValue then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return statements[1]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.hasWikidataProperty(item_id, property_id)&lt;br /&gt;
	return util.getBestStatement(item_id, property_id) and true or false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.getStatementValue(statement)&lt;br /&gt;
	return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.relatedEntity(item_id, property_id)&lt;br /&gt;
	local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )&lt;br /&gt;
	return value and value.id or false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.idType(id)&lt;br /&gt;
	if not id then &lt;br /&gt;
		return nil&lt;br /&gt;
	elseif mw.ustring.match(id, &amp;quot;[Pp]%d+&amp;quot;) then&lt;br /&gt;
		return &amp;quot;property&amp;quot;&lt;br /&gt;
	elseif mw.ustring.match(id, &amp;quot;[Qq]%d+&amp;quot;) then&lt;br /&gt;
		return &amp;quot;item&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.shouldAutoRun(frame)&lt;br /&gt;
	-- Check if should be running&lt;br /&gt;
	local pargs = frame.getParent(frame).args&lt;br /&gt;
	local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or &amp;quot;&amp;quot;)) -- true of false or nil&lt;br /&gt;
	if pargs.coordinates == &amp;quot;&amp;amp;#123;&amp;amp;#123;&amp;amp;#123;coordinates&amp;amp;#125;&amp;amp;#125;&amp;amp;#125;&amp;quot; then explicitlyOn = false end&lt;br /&gt;
	local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or &amp;quot;&amp;quot;), false) -- true or false&lt;br /&gt;
	return explicitlyOn or onByDefault&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.argsFromAuto(frame)&lt;br /&gt;
	-- Get args from the frame (invoke call) and the parent (template call).&lt;br /&gt;
	-- Frame arguments are default values which are overridden by parent values&lt;br /&gt;
	-- when both are present&lt;br /&gt;
	local args = getArgs(frame, {parentFirst = true})&lt;br /&gt;
&lt;br /&gt;
	-- Discard args not prefixed with &amp;quot;mapframe-&amp;quot;, remove that prefix from those that remain&lt;br /&gt;
	local fixedArgs = {}&lt;br /&gt;
	for name, val in pairs(args) do&lt;br /&gt;
		local fixedName = string.match(name, &amp;quot;^mapframe%-(.+)$&amp;quot; )&lt;br /&gt;
		if fixedName then&lt;br /&gt;
			fixedArgs[fixedName] = val&lt;br /&gt;
		-- allow coord, coordinates, etc to be unprefixed&lt;br /&gt;
		elseif name == &amp;quot;coordinates&amp;quot; or name == &amp;quot;coord&amp;quot; or name == &amp;quot;coordinate&amp;quot; and not fixedArgs.coord then&lt;br /&gt;
			fixedArgs.coord = val&lt;br /&gt;
		-- allow id, qid to be unprefixed, map to id (if not already present)&lt;br /&gt;
		elseif name == &amp;quot;id&amp;quot; or name == &amp;quot;qid&amp;quot; and not fixedArgs.id then&lt;br /&gt;
			fixedArgs.id = val&lt;br /&gt;
        -- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]&lt;br /&gt;
        elseif name == &amp;quot;captionstyle&amp;quot; and not fixedArgs.captionstyle then&lt;br /&gt;
            fixedArgs.captionstyle = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return fixedArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function util.parseCustomWikitext(customWikitext)&lt;br /&gt;
	-- infoboxImage will format an image if given wikitext containing an&lt;br /&gt;
	-- image, or else pass through the wikitext unmodified&lt;br /&gt;
	return infoboxImage({&lt;br /&gt;
		args = {&lt;br /&gt;
			image = customWikitext&lt;br /&gt;
		}&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function util.trackAndWarn(trackingCat, warning)&lt;br /&gt;
    local title = mw.title.getCurrentTitle()&lt;br /&gt;
    local results = title and title.namespace == 0 and trackingCat and &#039;[[Category:&#039;..trackingCat..&#039;]]&#039; or &#039;&#039;&lt;br /&gt;
    if warning then&lt;br /&gt;
        local warn = require(&#039;Module:If preview&#039;)._warning&lt;br /&gt;
        results = results..warn({warning})&lt;br /&gt;
    end&lt;br /&gt;
    return results&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function util.ternary(flag, other)&lt;br /&gt;
    other = other or &#039;other&#039;&lt;br /&gt;
    flag = flag == &#039;none&#039; and &#039;no&#039; or flag&lt;br /&gt;
    local yesNoOut = yesno(flag,other)&lt;br /&gt;
    local yes = (yesNoOut == true)&lt;br /&gt;
    local no = (yesNoOut == false)&lt;br /&gt;
    return yes, no&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p._caption = function(args)&lt;br /&gt;
	if args.caption then&lt;br /&gt;
		return args.caption&lt;br /&gt;
	elseif args.switcher then &lt;br /&gt;
		return util.noop(&amp;quot;no caption or switcher&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local maskItem&lt;br /&gt;
	local maskType = util.idType(args.geomask)&lt;br /&gt;
	if maskType == &#039;item&#039; then&lt;br /&gt;
		maskItem = args.geomask&lt;br /&gt;
	elseif maskType == &amp;quot;property&amp;quot; then&lt;br /&gt;
		maskItem = util.relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)&lt;br /&gt;
	end&lt;br /&gt;
	local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )&lt;br /&gt;
	return maskItemLabel and &amp;quot;Location in &amp;quot;..maskItemLabel&lt;br /&gt;
		or util.noop(&amp;quot;missing maskItemLabel with type &amp;quot; .. (maskType or &amp;quot;nil&amp;quot;) .. &amp;quot; and item &amp;quot; .. (maskItem or &amp;quot;nil&amp;quot;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--A list of types for objects that are too small to allow Kartographer to take over zoom&lt;br /&gt;
local tinyType = {&lt;br /&gt;
    landmark=true,&lt;br /&gt;
    railwaystation=true,&lt;br /&gt;
    edu=true,&lt;br /&gt;
    pass=true,&lt;br /&gt;
    camera=true&lt;br /&gt;
}                 &lt;br /&gt;
&lt;br /&gt;
p._main = function(_config)&lt;br /&gt;
    -- accumulate tracking cats&lt;br /&gt;
    local tracking = &#039;&#039;&lt;br /&gt;
	-- `config` is the args passed to this module&lt;br /&gt;
	local config = util.trimArgs(_config)&lt;br /&gt;
	&lt;br /&gt;
    -- allow alias for config.coord&lt;br /&gt;
    config.coord = config.coord or config.coordinates&lt;br /&gt;
&lt;br /&gt;
	-- Require wikidata item, or specified coords&lt;br /&gt;
	local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	if not(wikidataId) and not(config.coord) then&lt;br /&gt;
		return false, util.trackAndWarn(&#039;Pages using infobox mapframe with missing coordinates&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Require coords (specified or from wikidata), so that map will be centred somewhere&lt;br /&gt;
	-- (P625 = coordinate location)&lt;br /&gt;
    local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, &#039;P625&#039;))&lt;br /&gt;
    if not (config.coord or wdCoordinates) then&lt;br /&gt;
		return false, util.trackAndWarn(&#039;Pages using infobox mapframe with missing coordinates&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- `args` is the arguments which will be passed to the mapframe module&lt;br /&gt;
	local args = {}&lt;br /&gt;
&lt;br /&gt;
	-- Some defaults/overrides for infobox presentation&lt;br /&gt;
	args.display = &amp;quot;inline&amp;quot;&lt;br /&gt;
	args.frame = &amp;quot;yes&amp;quot;&lt;br /&gt;
	args.plain = &amp;quot;yes&amp;quot;&lt;br /&gt;
	args[&amp;quot;frame-width&amp;quot;]  = config[&amp;quot;frame-width&amp;quot;] or config.width or DEFAULT_FRAME_WIDTH&lt;br /&gt;
	args[&amp;quot;frame-height&amp;quot;] = config[&amp;quot;frame-height&amp;quot;] or config.height or DEFAULT_FRAME_HEIGHT&lt;br /&gt;
	args[&amp;quot;frame-align&amp;quot;]  = &amp;quot;center&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	args[&amp;quot;frame-coord&amp;quot;] = config[&amp;quot;frame-coordinates&amp;quot;] or config[&amp;quot;frame-coord&amp;quot;]&lt;br /&gt;
	-- Note: config[&amp;quot;coordinates&amp;quot;] or config[&amp;quot;coord&amp;quot;] should not be used for the alignment of the frame;&lt;br /&gt;
	-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )&lt;br /&gt;
&lt;br /&gt;
	-- deprecated lat and long parameters&lt;br /&gt;
	args[&amp;quot;frame-lat&amp;quot;]    = config[&amp;quot;frame-lat&amp;quot;] or config[&amp;quot;frame-latitude&amp;quot;]&lt;br /&gt;
	args[&amp;quot;frame-long&amp;quot;]   = config[&amp;quot;frame-long&amp;quot;] or config[&amp;quot;frame-longitude&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
    -- if zoom isn&#039;t specified from config, first check wikidata&lt;br /&gt;
    local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, &#039;P6592&#039;))&lt;br /&gt;
    if not zoom then&lt;br /&gt;
	    -- Calculate zoom from length or area (converted to km or km2)&lt;br /&gt;
	    -- Zoom so that length or area is completely included in mapframe&lt;br /&gt;
	    local getZoom = require(&#039;Module:Infobox dim&#039;)._zoom&lt;br /&gt;
	    zoom = getZoom({length_km=config.length_km, length_mi=config.length_mi,&lt;br /&gt;
                        width_km=config.width_km, width_mi=config.width_mi,&lt;br /&gt;
		                area_km2=config.area_km2, area_mi2=config.area_mi2,&lt;br /&gt;
                        area_ha=config.area_ha, area_acre=config.area_acre,&lt;br /&gt;
                        type=config.type, population=config.population,&lt;br /&gt;
		                viewport_px=math.min(args[&amp;quot;frame-width&amp;quot;],args[&amp;quot;frame-height&amp;quot;]),&lt;br /&gt;
                        latitude=wdCoordinates and wdCoordinates.latitude})&lt;br /&gt;
    end&lt;br /&gt;
    args.zoom = zoom or DEFAULT_ZOOM&lt;br /&gt;
&lt;br /&gt;
	-- Use OSM relation ID if available; otherwise use geoshape if that is available&lt;br /&gt;
	-- (geoshape is required for defunct entities, which are outside OSM&#039;s scope)&lt;br /&gt;
	local hasOsmRelationId = util.hasWikidataProperty(wikidataId, &#039;P402&#039;) -- P402 is OSM relation ID&lt;br /&gt;
	local hasGeoshape = util.hasWikidataProperty(wikidataId, &#039;P3896&#039;) -- P3896 is geoshape&lt;br /&gt;
	local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape&lt;br /&gt;
&lt;br /&gt;
    -- determine marker argument value, determine whether to show marker&lt;br /&gt;
    local forcePoint, suppressPoint = util.ternary(config.point)&lt;br /&gt;
    local forceMarker, suppressMarker = util.ternary(config.marker,true)&lt;br /&gt;
&lt;br /&gt;
    forcePoint = forcePoint or forceMarker&lt;br /&gt;
    suppressPoint = suppressPoint or suppressMarker&lt;br /&gt;
&lt;br /&gt;
    local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)&lt;br /&gt;
    &lt;br /&gt;
    -- wikidata = &amp;quot;yes&amp;quot; turns on both shape and line&lt;br /&gt;
    -- wikidata = &amp;quot;no&amp;quot; turns off both shape and line&lt;br /&gt;
    -- otherwise show both if wikidata provides geo&lt;br /&gt;
    local forceWikidata, suppressWikidata = util.ternary(config.wikidata)&lt;br /&gt;
    local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)&lt;br /&gt;
    local showLine = showShape&lt;br /&gt;
&lt;br /&gt;
    -- determine shape parameter value, determine whether to show or suppress shape&lt;br /&gt;
    -- also determine whether to invert shape&lt;br /&gt;
    local forceShape, suppressShape = util.ternary(config.shape)&lt;br /&gt;
    showShape = wikidataId and not suppressShape and (forceShape or showShape)&lt;br /&gt;
	local shapeType = config.shape == &#039;inverse&#039; and &#039;shape-inverse&#039; or &#039;shape&#039;&lt;br /&gt;
&lt;br /&gt;
    -- determine line parameter value, determine whether to show or suppress line&lt;br /&gt;
    local forceLine, suppressLine = util.ternary(config.line)&lt;br /&gt;
    showLine = wikidataId and not suppressLine and (forceLine or showLine)&lt;br /&gt;
&lt;br /&gt;
    local maskItem&lt;br /&gt;
	-- Switcher&lt;br /&gt;
	if config.switcher == &amp;quot;zooms&amp;quot; then&lt;br /&gt;
		-- switching between zoom levels&lt;br /&gt;
		local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)&lt;br /&gt;
		local minZoom = 1 -- completely zoomed out&lt;br /&gt;
		local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min&lt;br /&gt;
		args.switch = &amp;quot;zoomed in, zoomed midway, zoomed out&amp;quot;&lt;br /&gt;
		args.zoom = string.format(&amp;quot;SWITCH:%d,%d,%d&amp;quot;, maxZoom, midZoom, minZoom)&lt;br /&gt;
	elseif config.switcher == &amp;quot;auto&amp;quot; then&lt;br /&gt;
		-- switching between P276 and P131 areas with recursive lookup, e.g. item&#039;s city,&lt;br /&gt;
		-- that city&#039;s state, and that state&#039;s country&lt;br /&gt;
		args.zoom = nil -- let kartographer determine the zoom&lt;br /&gt;
		local maskLabels = {}&lt;br /&gt;
		local maskItems = {}&lt;br /&gt;
		local maskItemId = util.relatedEntity(wikidataId, &amp;quot;P276&amp;quot;) or  util.relatedEntity(wikidataId, &amp;quot;P131&amp;quot;) &lt;br /&gt;
		local maskLabel = mw.wikibase.getLabel(maskItemId)&lt;br /&gt;
		while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= &amp;quot;&amp;quot; do&lt;br /&gt;
			table.insert(maskLabels, maskLabel)&lt;br /&gt;
			table.insert(maskItems, maskItemId)&lt;br /&gt;
			maskItemId = maskItemId and util.relatedEntity(maskItemId, &amp;quot;P131&amp;quot;)&lt;br /&gt;
			maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)&lt;br /&gt;
		end&lt;br /&gt;
		if #maskLabels &amp;gt; 1 then&lt;br /&gt;
			args.switch = table.concat(maskLabels, &amp;quot;###&amp;quot;)&lt;br /&gt;
			maskItem = &amp;quot;SWITCH:&amp;quot; .. table.concat(maskItems, &amp;quot;,&amp;quot;)&lt;br /&gt;
		elseif #maskLabels == 1 then&lt;br /&gt;
			maskItem = maskItemId[1]&lt;br /&gt;
		end&lt;br /&gt;
	elseif config.switcher == &amp;quot;geomasks&amp;quot; and config.geomask then&lt;br /&gt;
		-- switching between items in geomask parameter&lt;br /&gt;
		args.zoom = nil -- let kartographer determine the zoom&lt;br /&gt;
		local separator = (mw.ustring.find(config.geomask, &amp;quot;###&amp;quot;, 0, true ) and &amp;quot;###&amp;quot;) or&lt;br /&gt;
			(mw.ustring.find(config.geomask, &amp;quot;;&amp;quot;, 0, true ) and &amp;quot;;&amp;quot;) or &amp;quot;,&amp;quot;&lt;br /&gt;
		local pattern = &amp;quot;%s*&amp;quot;..separator..&amp;quot;%s*&amp;quot;&lt;br /&gt;
		local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, &amp;quot;SWITCH:&amp;quot;, &amp;quot;&amp;quot;), pattern)&lt;br /&gt;
		local maskLabels = {}&lt;br /&gt;
		if #maskItems &amp;gt; 1 then&lt;br /&gt;
			for i, item in ipairs(maskItems) do&lt;br /&gt;
				table.insert(maskLabels, mw.wikibase.getLabel(item))&lt;br /&gt;
			end&lt;br /&gt;
			args.switch = table.concat(maskLabels, &amp;quot;###&amp;quot;)&lt;br /&gt;
			maskItem = &amp;quot;SWITCH:&amp;quot; .. table.concat(maskItems, &amp;quot;,&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- resolve geomask item id (if not using geomask switcher)&lt;br /&gt;
	if not maskItem then --  &lt;br /&gt;
		local maskType = util.idType(config.geomask)&lt;br /&gt;
		if maskType == &#039;item&#039; then&lt;br /&gt;
			maskItem = config.geomask&lt;br /&gt;
		elseif maskType == &amp;quot;property&amp;quot; then&lt;br /&gt;
			maskItem = util.relatedEntity(wikidataId, config.geomask)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    -- if asking for shape or line from Wikidata&lt;br /&gt;
    -- and if Wikidata actually has shape/line data (wikidataProvidesGeo=true)&lt;br /&gt;
    -- and if no geomask&lt;br /&gt;
    -- and if zoom not explicitly set&lt;br /&gt;
    -- and if the object size inferred from its type is not too small&lt;br /&gt;
    -- then let Kartographer &amp;quot;take over&amp;quot; zoom&lt;br /&gt;
    if (showLine or showShape) and wikidataProvidesGeo and not maskItem&lt;br /&gt;
       and not config.zoom and not (config.type and tinyType[config.type]) then&lt;br /&gt;
	    args.zoom = nil&lt;br /&gt;
    end	&lt;br /&gt;
&lt;br /&gt;
    if not maskItem and not showShape and not showLine and not showMarker then&lt;br /&gt;
        return false, util.trackAndWarn(&#039;Pages using infobox mapframe with no geometry&#039;,&#039;No geometry specified for mapframe&#039;)&lt;br /&gt;
    end&lt;br /&gt;
	&lt;br /&gt;
	-- Keep track of arg numbering&lt;br /&gt;
	local argNumber = &#039;&#039;&lt;br /&gt;
	local function incrementArgNumber()&lt;br /&gt;
		if argNumber == &#039;&#039; then&lt;br /&gt;
			argNumber = 2&lt;br /&gt;
		else&lt;br /&gt;
			argNumber = argNumber + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Geomask&lt;br /&gt;
	if maskItem then&lt;br /&gt;
		args[&amp;quot;type&amp;quot;..argNumber] = &amp;quot;shape-inverse&amp;quot;&lt;br /&gt;
		args[&amp;quot;id&amp;quot;..argNumber] = maskItem&lt;br /&gt;
		args[&amp;quot;stroke-width&amp;quot;..argNumber] = config[&amp;quot;geomask-stroke-width&amp;quot;] or DEFAULT_GEOMASK_STROKE_WIDTH&lt;br /&gt;
		args[&amp;quot;stroke-color&amp;quot;..argNumber] = config[&amp;quot;geomask-stroke-color&amp;quot;] or config[&amp;quot;geomask-stroke-colour&amp;quot;] or DEFAULT_GEOMASK_STROKE_COLOR&lt;br /&gt;
		args[&amp;quot;fill&amp;quot;..argNumber] = config[&amp;quot;geomask-fill&amp;quot;] or DEFAULT_GEOMASK_FILL&lt;br /&gt;
		args[&amp;quot;fill-opacity&amp;quot;..argNumber] = config[&amp;quot;geomask-fill-opacity&amp;quot;] or DEFAULT_SHAPE_FILL_OPACITY&lt;br /&gt;
		-- Let kartographer determine zoom and position, unless it is explicitly set in config&lt;br /&gt;
		if not config.zoom and not config.switcher then&lt;br /&gt;
			args.zoom = nil&lt;br /&gt;
			args[&amp;quot;frame-coord&amp;quot;] = nil&lt;br /&gt;
			args[&amp;quot;frame-lat&amp;quot;] = nil&lt;br /&gt;
			args[&amp;quot;frame-long&amp;quot;] = nil 	&lt;br /&gt;
			local maskArea = util.getStatementValue( util.getBestStatement(maskItem, &#039;P2046&#039;) )&lt;br /&gt;
		end&lt;br /&gt;
		incrementArgNumber()&lt;br /&gt;
		-- Hack to fix phab:T255932&lt;br /&gt;
		if not args.zoom then&lt;br /&gt;
			args[&amp;quot;type&amp;quot;..argNumber] = &amp;quot;line&amp;quot;&lt;br /&gt;
			args[&amp;quot;id&amp;quot;..argNumber] = maskItem&lt;br /&gt;
			args[&amp;quot;stroke-width&amp;quot;..argNumber] = 0&lt;br /&gt;
			incrementArgNumber()&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Shape (or shape-inverse)&lt;br /&gt;
	if showShape then&lt;br /&gt;
		args[&amp;quot;type&amp;quot;..argNumber] = shapeType&lt;br /&gt;
		if hasGeoshape and not hasOsmRelationId then&lt;br /&gt;
			args[&amp;quot;from&amp;quot;..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, &#039;P3896&#039;) ), 6)&lt;br /&gt;
		elseif config.id then &lt;br /&gt;
			args[&amp;quot;id&amp;quot;..argNumber] = config.id&lt;br /&gt;
		end&lt;br /&gt;
		args[&amp;quot;stroke-width&amp;quot;..argNumber] = config[&amp;quot;shape-stroke-width&amp;quot;] or config[&amp;quot;stroke-width&amp;quot;] or DEFAULT_SHAPE_STROKE_WIDTH&lt;br /&gt;
		args[&amp;quot;stroke-color&amp;quot;..argNumber] = config[&amp;quot;shape-stroke-color&amp;quot;] or config[&amp;quot;shape-stroke-colour&amp;quot;] or config[&amp;quot;stroke-color&amp;quot;] or config[&amp;quot;stroke-colour&amp;quot;] or DEFAULT_SHAPE_STROKE_COLOR&lt;br /&gt;
		args[&amp;quot;fill&amp;quot;..argNumber] = config[&amp;quot;shape-fill&amp;quot;] or DEFAULT_SHAPE_FILL&lt;br /&gt;
		args[&amp;quot;fill-opacity&amp;quot;..argNumber] = config[&amp;quot;shape-fill-opacity&amp;quot;] or DEFAULT_SHAPE_FILL_OPACITY&lt;br /&gt;
		incrementArgNumber()&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Line&lt;br /&gt;
	if showLine then&lt;br /&gt;
		args[&amp;quot;type&amp;quot;..argNumber] = &amp;quot;line&amp;quot;&lt;br /&gt;
		if hasGeoshape and not hasOsmRelationId then&lt;br /&gt;
			args[&amp;quot;from&amp;quot;..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, &#039;P3896&#039;) ), 6)&lt;br /&gt;
		elseif config.id then &lt;br /&gt;
			args[&amp;quot;id&amp;quot;..argNumber] = config.id&lt;br /&gt;
		end&lt;br /&gt;
		args[&amp;quot;stroke-width&amp;quot;..argNumber] = config[&amp;quot;line-stroke-width&amp;quot;] or config[&amp;quot;stroke-width&amp;quot;] or DEFAULT_LINE_STROKE_WIDTH&lt;br /&gt;
		args[&amp;quot;stroke-color&amp;quot;..argNumber] = config[&amp;quot;line-stroke-color&amp;quot;] or config[&amp;quot;line-stroke-colour&amp;quot;] or config[&amp;quot;stroke-color&amp;quot;] or config[&amp;quot;stroke-colour&amp;quot;] or DEFAULT_LINE_STROKE_COLOR&lt;br /&gt;
		incrementArgNumber()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Point marker&lt;br /&gt;
	if showMarker then&lt;br /&gt;
		args[&amp;quot;type&amp;quot;..argNumber] = &amp;quot;point&amp;quot;&lt;br /&gt;
		if config.id then args[&amp;quot;id&amp;quot;..argNumber] = config.id end&lt;br /&gt;
		if config.coord then args[&amp;quot;coord&amp;quot;..argNumber] = config.coord end&lt;br /&gt;
		if config.marker then args[&amp;quot;marker&amp;quot;..argNumber] = config.marker end&lt;br /&gt;
		args[&amp;quot;marker-color&amp;quot;..argNumber] = config[&amp;quot;marker-color&amp;quot;] or config[&amp;quot;marker-colour&amp;quot;] or DEFAULT_MARKER_COLOR&lt;br /&gt;
		incrementArgNumber()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    -- if Wikidata doesn&#039;t link to OSM and the map has no mask or point,&lt;br /&gt;
    -- then center the map on the coordinates either from the infobox or from wikidata&lt;br /&gt;
    if not maskItem and not showMarker and not wikidataProvidesGeo then&lt;br /&gt;
        if config.coord then&lt;br /&gt;
            args[&amp;quot;frame-coord&amp;quot;] = args[&amp;quot;frame-coord&amp;quot;] or config.coord&lt;br /&gt;
        else&lt;br /&gt;
            args[&amp;quot;frame-lat&amp;quot;] = args[&amp;quot;frame-lat&amp;quot;] or wdCoordinates.latitude&lt;br /&gt;
            args[&amp;quot;frame-long&amp;quot;] = args[&amp;quot;frame-long&amp;quot;] or wdCoordinates.longitude&lt;br /&gt;
        end&lt;br /&gt;
        tracking = tracking..util.trackAndWarn(&#039;Pages using infobox mapframe with forced centering&#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- protect against nil frame arguments&lt;br /&gt;
    args[&amp;quot;frame-coord&amp;quot;] = args[&amp;quot;frame-coord&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
    args[&amp;quot;frame-lat&amp;quot;] = args[&amp;quot;frame-lat&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
    args[&amp;quot;frame-long&amp;quot;] = args[&amp;quot;frame-long&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local mapframe = args.switch and mf.multi(args) or mf._main(args)&lt;br /&gt;
	tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo &lt;br /&gt;
                          and util.trackAndWarn(&#039;Pages using infobox mapframe without shape links in Wikidata&#039;)&lt;br /&gt;
                          or &#039;&#039;)&lt;br /&gt;
	return true, mapframe.. tracking&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Entry points&lt;br /&gt;
&lt;br /&gt;
p.main = function(frame)&lt;br /&gt;
	local parent = frame.getParent(frame)&lt;br /&gt;
	local parentArgs = parent.args&lt;br /&gt;
	local _, mapframe = p._main(parentArgs)&lt;br /&gt;
	return frame:preprocess(mapframe)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.auto = function(frame)&lt;br /&gt;
	if not util.shouldAutoRun(frame) then&lt;br /&gt;
		return util.noop(&amp;quot;auto should not autorun&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local args = util.argsFromAuto(frame)&lt;br /&gt;
	if args.custom then&lt;br /&gt;
		return frame:preprocess(util.parseCustomWikitext(args.custom))&lt;br /&gt;
	end&lt;br /&gt;
	local _, mapframe = p._main(args)&lt;br /&gt;
	return frame:preprocess(mapframe)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.autocaption = function(frame)&lt;br /&gt;
	if not util.shouldAutoRun(frame) then&lt;br /&gt;
		return util.noop(&amp;quot;autocaption should not autorun&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local args = util.argsFromAuto(frame)&lt;br /&gt;
    local caption = p._caption(args)&lt;br /&gt;
    return caption&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.autoWithCaption = function(frame)&lt;br /&gt;
	if not util.shouldAutoRun(frame) then&lt;br /&gt;
		return util.noop(&amp;quot;autoWithCaption should not autorun&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local args = util.argsFromAuto(frame)&lt;br /&gt;
    local wikitext&lt;br /&gt;
    local caption&lt;br /&gt;
    local ok&lt;br /&gt;
    if args.custom then&lt;br /&gt;
        ok = true&lt;br /&gt;
        wikitext = util.parseCustomWikitext(args.custom)&lt;br /&gt;
    else&lt;br /&gt;
        ok, wikitext = p._main(args)&lt;br /&gt;
    end&lt;br /&gt;
    if not ok then return wikitext end&lt;br /&gt;
    wikitext = frame:preprocess(wikitext)&lt;br /&gt;
    caption = p._caption(args)&lt;br /&gt;
    local data = mw.html.create():wikitext(wikitext)&lt;br /&gt;
    data:tag(&#039;div&#039;)&lt;br /&gt;
	    :addClass(&#039;infobox-caption&#039;)&lt;br /&gt;
		:cssText(args.captionstyle)&lt;br /&gt;
		:wikitext(caption)&lt;br /&gt;
    return tostring(data)&lt;br /&gt;
end&lt;br /&gt;
    &lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Stack_end&amp;diff=73</id>
		<title>Template:Stack end</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Stack_end&amp;diff=73"/>
		<updated>2026-06-22T02:00:46Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;{{#invoke:Check for unknown parameters|check|unknown=_VALUE_{{PAGENAME}}|preview=Page using Template:Stack end with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{documentation}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;{{#invoke:Check for unknown parameters|check|unknown=[[Category:Pages using stack with unknown parameters|_VALUE_{{PAGENAME}}]]|preview=Page using [[Template:Stack end]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
	<entry>
		<id>https://austenasia.wiki/index.php?title=Template:Stack_begin&amp;diff=72</id>
		<title>Template:Stack begin</title>
		<link rel="alternate" type="text/html" href="https://austenasia.wiki/index.php?title=Template:Stack_begin&amp;diff=72"/>
		<updated>2026-06-22T02:00:31Z</updated>

		<summary type="html">&lt;p&gt;Austenasia: Created page with &amp;quot;&amp;lt;templatestyles src=&amp;quot;Stack/styles.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;stack mw-stack {{#switch:{{{float|right}}}|left=stack-{{#switch:{{{margin|}}}|1|true|y|yes=margin-}}{{#switch:{{{clear|}}}|left|true=clear-}}left|right=stack-{{#switch:{{{margin|}}}|1|true|y|yes=margin-}}{{#switch:{{{clear|}}}|right|true=clear-}}right}}&amp;quot;&amp;gt;&amp;lt;!-- --&amp;gt;&amp;lt;div {{#if:{{{cellspacing|}}}|style=&amp;quot;margin: {{{cellspacing}}}px&amp;quot;}}&amp;gt;&amp;lt;!-- --&amp;gt;{{#invoke:Check for unknown parameters|check|unknown=Category:Pages using stack wi...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Stack/styles.css&amp;quot;/&amp;gt;&amp;lt;div class=&amp;quot;stack mw-stack {{#switch:{{{float|right}}}|left=stack-{{#switch:{{{margin|}}}|1|true|y|yes=margin-}}{{#switch:{{{clear|}}}|left|true=clear-}}left|right=stack-{{#switch:{{{margin|}}}|1|true|y|yes=margin-}}{{#switch:{{{clear|}}}|right|true=clear-}}right}}&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div {{#if:{{{cellspacing|}}}|style=&amp;quot;margin: {{{cellspacing}}}px&amp;quot;}}&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#invoke:Check for unknown parameters|check|unknown=[[Category:Pages using stack with unknown parameters|_VALUE_{{PAGENAME}}]]|preview=Page using [[Template:Stack begin]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| cellspacing | clear | float | margin }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{stack end}}&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Austenasia</name></author>
	</entry>
</feed>