Wikipidiya
bolwiki
https://bol.wikipedia.org/wiki/Peji_In_Siri
MediaWiki 1.47.0-wmf.16
first-letter
Media
Inmusamman
Mossa
Ruta
Rutta mossa
Wikipidiya
Wikipidiya mossa
Fayil
Fayil mossa
MediaWiki
MediaWiki mossa
Tempilet
Tempilet mossa
Taimako
Taimako mossa
Panni
Panni mossa
TimedText
TimedText talk
Module
Module talk
Event
Event talk
Peji In Siri
0
1
9157
8813
2026-08-22T23:51:34Z
RAPTOR7762
18
9157
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
{{Protection padlock|small=yes}}
<div style="text-align:center;">
<!--{{Clickable button|Special:Purge/Peji In Siri|Purge this page|class=mw-ui-progressive}}-->
</div>
<templatestyles src="Main page/Styles.css" />
<div style="position:relative; text-align:center; padding:3em 1em; background:#fff; overflow:hidden;">
<div style="position:absolute; top:-50px; left:0; right:0; text-align:center; opacity:0.1; z-index:0;">
[[File:Wikipedia-logo-v2.svg|600px|center|class=notpageimage|link=]]
</div>
<div style="position:relative; z-index:1;">
<div style="font-variant:small-caps; font-family:'Linux Libertine','Georgia',serif;"><div style="font-size:180%;">U'se ga nako</div>
<div style="font-size:270%; line-height:1;">[[Wikipidiya|<span style="display: inline-block; letter-spacing: -0.35em; margin-right: 0.2em; font-family: serif;">V<span style="margin-left: -0.1em;">V</span></span>ikipidiya]] in bòo pìkkà</div>
</div>
<div style="font-size:120%; line-height:1.2;"> Wikipidiya ensakulopidiya in lelo in [[Harshe Bole]] la lemalo agita ina ramayi.</div>
<div style="font-size:120%; line-height:1.2;"> Honsene Andi makaloli '''[[Special:AllPages|{{NUMBEROFARTICLES}}]]''' ga harshe Bole</div>
</div>
</div>
<div style="margin:10px 0px 10px 0px; -moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); -webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); background-color:#FFFFFF;">
{| style="border-spacing: 1px; border-collapse: separate; width:100%; text-align:center; font-size:0.85em; padding:2px 3px 2px 3px;" class="hp-portalen"
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Atiimala|<span style="color:#000000;">Atiimala</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Annoba|<span style="color:#000000;">Annoba</span>]]
| style="background-color:#F0F4F9; border-top:5px solid; border-color:#336699; padding:3px 0.15em; width:6.6%;" | [[:Category:Fasaha|<span style="color:#000000;">Fasaha</span>]]
| style="background-color:#F9F0F0; border-top:5px solid; border-color:#993333; padding:3px 0.15em; width:6.6%;" | [[:Category:Ilimi|<span style="color:#000000;">Ilimi</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Lamba|<span style="color:#000000;">Lamba</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Miyya|<span style="color:#000000;">Miyya</span>]]
| style="background-color:#F9F9F0; border-top:5px solid; border-color:#999933; padding:3px 0.15em; width:6.6%;" | [[:Category:Makami|<span style="color:#000000;">Makami</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Malunwa|<span style="color:#000000;">Malunwa</span>]]
| style="background-color:#F0F9F0; border-top:5px solid; border-color:#339933; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii|<span style="color:#000000;">Olii</span>]]
| style="background-color:#F9F0F4; border-top:5px solid; border-color:#993366; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii pewe|<span style="color:#000000;">Olii pewe</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Tarihi|<span style="color:#000000;">Tarihi</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Goma|<span style="color:#000000;">Goma</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Kimiyya|<span style="color:#000000;">Kimiyya</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Zane|<span style="color:#000000;">Zane</span>]]
|}
</div>
<templatestyles src="Main page/Styles.css" />
<div style="flex:1; min-width:300px; overflow:hidden; border-radius:4px; margin:8px 4px 4px 4px; box-shadow:0 0 8px rgba(0,0,0,0.15);">
<div class="image-carousel">
<ul>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Star-alt-icon.png|20px|link=]] Featured Article</div>
</div>
<div class="carousel-image">
[[File:The City Gate of Abuja.jpg|center|class=carousel-image-wrapper|link=Nijeriya|Nijeriya]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Nijeriya ko Nijeriya da (turanci: Nigeria): A Gwamanatance Tarayyar Najeriya, woli la ga take ga Africa ko zoni ita ji tetteke woli niger koga Arewa. Ga Chadi koga zoni koga aushi jam aji dar ga teku Atlantika.</div>
<div class="carousel-slide-title">[[Nijeriya]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat sign-question.svg|20px|link=]] Kamontuwo?</div>
</div>
<div class="carousel-image">
[[File:Gooya mountain.jpg|center|class=carousel-image-wrapper|link=Gooya mountain]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Gooya kam zoi wuro la tudu ga arewa [[Nijeriya]], inda Bòo pikka ye kam la yare miyya aji magana da yawa ga yankin da ke kewaye.
</div>
<div class="carousel-slide-title">[[Potiskum]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat file-picture.svg|20px|link=]] Featured Picture</div>
</div>
<div class="carousel-image">
[[File:Daniski Festival 04.jpg|center|class=carousel-image-wrapper|link=File:Daniski Festival 04.jpg]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Daniski Hills Annual Festival kam zoi tarayya la al’ada, ba Bòo pikka ga Fika Emirate ga Yobe State, [[Nijeriya]].
</div>
<div class="carousel-slide-title">[[:File:Daniski Festival 04.jpg|Daniski Festival Picture]]</div>
</div>
</div>
</li>
</ul>
</div>
</div>
<div style="display:flex; flex-wrap:wrap;">
{{Box
|header=[[File:Paomedia small-n-flat sign-info.svg|20px|link=]] Elle Wikipidiya?
|content=<span style="float: left; margin: 6px 12px 6px 0px; display: inline-block;">[[File:Wikipedia-logo-v2-bol.svg|100px]]</span>Wikipidiya shafi ji in Yana gizonla ona gudumawa inko rubutu mukalai kala aji gidan ga goggo gozi ilmi do ramu-ramu ga messesu. Gabo turanci ga unda shap Maddi la ramu ramu do gede ga ilmi ga shafuka Wikipedia ga sun Wikipedia, wikipidiya aji tattira ga harsuna GA duniya ga godon shafuka lemalo aji kirkira do ramu mukalai gabo kyauta inko taimako beyi wena ilmi bo kyauta, emeyye aji Wikipedia ga zarrar a shap ga duniya beyi wena ilmi koga asali beyi ilmi fetengo.
}}
{{Box
|header=[[File:Paomedia small-n-flat pencil.svg|20px|link=]] Kirkiru Foyo Article
|content=Kaji kume Harshe Bole? Kagita ina taimako beyi Bunƙasa kunsu eme Mona (ensakulopidiya) ko goggo kirkire foyo makaloli do fadada la aji Andi ga fatan aji doffa ka'idoji Al'umma lokaci ona ga gundumawa.<br><small><i></i></small>
<div style="margin-top:1em;">
<inputbox>
type=create
width=30
default=
buttonlabel=Kirkiru Foyo Makala
</inputbox>
</div>
}}
</div>
{{Box
|header=English speakers
|content=If you speak English, but you don't know anything about the Bole Language, you are also welcome to edit and assist in technical support, such as maintaining Templates or Modules. Your role is vital to the smooth running of the Bole Wikipedia!
}}
{{Box
|header=[[File:Wikimedia-logo.svg|20px|link=]] Project Modi
|content={{SisterProjects}}
}}
hskfpk3pq5va34egtb52iq3hy0s0ffy
9158
9157
2026-08-22T23:52:03Z
RAPTOR7762
18
9158
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
<!--{{Protection padlock|small=yes}}-->
<div style="text-align:center;">
<!--{{Clickable button|Special:Purge/Peji In Siri|Purge this page|class=mw-ui-progressive}}-->
</div>
<templatestyles src="Main page/Styles.css" />
<div style="position:relative; text-align:center; padding:3em 1em; background:#fff; overflow:hidden;">
<div style="position:absolute; top:-50px; left:0; right:0; text-align:center; opacity:0.1; z-index:0;">
[[File:Wikipedia-logo-v2.svg|600px|center|class=notpageimage|link=]]
</div>
<div style="position:relative; z-index:1;">
<div style="font-variant:small-caps; font-family:'Linux Libertine','Georgia',serif;"><div style="font-size:180%;">U'se ga nako</div>
<div style="font-size:270%; line-height:1;">[[Wikipidiya|<span style="display: inline-block; letter-spacing: -0.35em; margin-right: 0.2em; font-family: serif;">V<span style="margin-left: -0.1em;">V</span></span>ikipidiya]] in bòo pìkkà</div>
</div>
<div style="font-size:120%; line-height:1.2;"> Wikipidiya ensakulopidiya in lelo in [[Harshe Bole]] la lemalo agita ina ramayi.</div>
<div style="font-size:120%; line-height:1.2;"> Honsene Andi makaloli '''[[Special:AllPages|{{NUMBEROFARTICLES}}]]''' ga harshe Bole</div>
</div>
</div>
<div style="margin:10px 0px 10px 0px; -moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); -webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); background-color:#FFFFFF;">
{| style="border-spacing: 1px; border-collapse: separate; width:100%; text-align:center; font-size:0.85em; padding:2px 3px 2px 3px;" class="hp-portalen"
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Atiimala|<span style="color:#000000;">Atiimala</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Annoba|<span style="color:#000000;">Annoba</span>]]
| style="background-color:#F0F4F9; border-top:5px solid; border-color:#336699; padding:3px 0.15em; width:6.6%;" | [[:Category:Fasaha|<span style="color:#000000;">Fasaha</span>]]
| style="background-color:#F9F0F0; border-top:5px solid; border-color:#993333; padding:3px 0.15em; width:6.6%;" | [[:Category:Ilimi|<span style="color:#000000;">Ilimi</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Lamba|<span style="color:#000000;">Lamba</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Miyya|<span style="color:#000000;">Miyya</span>]]
| style="background-color:#F9F9F0; border-top:5px solid; border-color:#999933; padding:3px 0.15em; width:6.6%;" | [[:Category:Makami|<span style="color:#000000;">Makami</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Malunwa|<span style="color:#000000;">Malunwa</span>]]
| style="background-color:#F0F9F0; border-top:5px solid; border-color:#339933; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii|<span style="color:#000000;">Olii</span>]]
| style="background-color:#F9F0F4; border-top:5px solid; border-color:#993366; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii pewe|<span style="color:#000000;">Olii pewe</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Tarihi|<span style="color:#000000;">Tarihi</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Goma|<span style="color:#000000;">Goma</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Kimiyya|<span style="color:#000000;">Kimiyya</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Zane|<span style="color:#000000;">Zane</span>]]
|}
</div>
<templatestyles src="Main page/Styles.css" />
<div style="flex:1; min-width:300px; overflow:hidden; border-radius:4px; margin:8px 4px 4px 4px; box-shadow:0 0 8px rgba(0,0,0,0.15);">
<div class="image-carousel">
<ul>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Star-alt-icon.png|20px|link=]] Featured Article</div>
</div>
<div class="carousel-image">
[[File:The City Gate of Abuja.jpg|center|class=carousel-image-wrapper|link=Nijeriya|Nijeriya]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Nijeriya ko Nijeriya da (turanci: Nigeria): A Gwamanatance Tarayyar Najeriya, woli la ga take ga Africa ko zoni ita ji tetteke woli niger koga Arewa. Ga Chadi koga zoni koga aushi jam aji dar ga teku Atlantika.</div>
<div class="carousel-slide-title">[[Nijeriya]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat sign-question.svg|20px|link=]] Kamontuwo?</div>
</div>
<div class="carousel-image">
[[File:Gooya mountain.jpg|center|class=carousel-image-wrapper|link=Gooya mountain]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Gooya kam zoi wuro la tudu ga arewa [[Nijeriya]], inda Bòo pikka ye kam la yare miyya aji magana da yawa ga yankin da ke kewaye.
</div>
<div class="carousel-slide-title">[[Potiskum]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat file-picture.svg|20px|link=]] Featured Picture</div>
</div>
<div class="carousel-image">
[[File:Daniski Festival 04.jpg|center|class=carousel-image-wrapper|link=File:Daniski Festival 04.jpg]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Daniski Hills Annual Festival kam zoi tarayya la al’ada, ba Bòo pikka ga Fika Emirate ga Yobe State, [[Nijeriya]].
</div>
<div class="carousel-slide-title">[[:File:Daniski Festival 04.jpg|Daniski Festival Picture]]</div>
</div>
</div>
</li>
</ul>
</div>
</div>
<div style="display:flex; flex-wrap:wrap;">
{{Box
|header=[[File:Paomedia small-n-flat sign-info.svg|20px|link=]] Elle Wikipidiya?
|content=<span style="float: left; margin: 6px 12px 6px 0px; display: inline-block;">[[File:Wikipedia-logo-v2-bol.svg|100px]]</span>Wikipidiya shafi ji in Yana gizonla ona gudumawa inko rubutu mukalai kala aji gidan ga goggo gozi ilmi do ramu-ramu ga messesu. Gabo turanci ga unda shap Maddi la ramu ramu do gede ga ilmi ga shafuka Wikipedia ga sun Wikipedia, wikipidiya aji tattira ga harsuna GA duniya ga godon shafuka lemalo aji kirkira do ramu mukalai gabo kyauta inko taimako beyi wena ilmi bo kyauta, emeyye aji Wikipedia ga zarrar a shap ga duniya beyi wena ilmi koga asali beyi ilmi fetengo.
}}
{{Box
|header=[[File:Paomedia small-n-flat pencil.svg|20px|link=]] Kirkiru Foyo Article
|content=Kaji kume Harshe Bole? Kagita ina taimako beyi Bunƙasa kunsu eme Mona (ensakulopidiya) ko goggo kirkire foyo makaloli do fadada la aji Andi ga fatan aji doffa ka'idoji Al'umma lokaci ona ga gundumawa.<br><small><i></i></small>
<div style="margin-top:1em;">
<inputbox>
type=create
width=30
default=
buttonlabel=Kirkiru Foyo Makala
</inputbox>
</div>
}}
</div>
{{Box
|header=English speakers
|content=If you speak English, but you don't know anything about the Bole Language, you are also welcome to edit and assist in technical support, such as maintaining Templates or Modules. Your role is vital to the smooth running of the Bole Wikipedia!
}}
{{Box
|header=[[File:Wikimedia-logo.svg|20px|link=]] Project Modi
|content={{SisterProjects}}
}}
sjqv31r9u27s4t0bq3v2o3743u10zie
9294
9158
2026-08-23T04:41:31Z
RAPTOR7762
18
RAPTOR7762 moved page [[Peji Unsiri]] to [[Peji In Siri]]
9158
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
<!--{{Protection padlock|small=yes}}-->
<div style="text-align:center;">
<!--{{Clickable button|Special:Purge/Peji In Siri|Purge this page|class=mw-ui-progressive}}-->
</div>
<templatestyles src="Main page/Styles.css" />
<div style="position:relative; text-align:center; padding:3em 1em; background:#fff; overflow:hidden;">
<div style="position:absolute; top:-50px; left:0; right:0; text-align:center; opacity:0.1; z-index:0;">
[[File:Wikipedia-logo-v2.svg|600px|center|class=notpageimage|link=]]
</div>
<div style="position:relative; z-index:1;">
<div style="font-variant:small-caps; font-family:'Linux Libertine','Georgia',serif;"><div style="font-size:180%;">U'se ga nako</div>
<div style="font-size:270%; line-height:1;">[[Wikipidiya|<span style="display: inline-block; letter-spacing: -0.35em; margin-right: 0.2em; font-family: serif;">V<span style="margin-left: -0.1em;">V</span></span>ikipidiya]] in bòo pìkkà</div>
</div>
<div style="font-size:120%; line-height:1.2;"> Wikipidiya ensakulopidiya in lelo in [[Harshe Bole]] la lemalo agita ina ramayi.</div>
<div style="font-size:120%; line-height:1.2;"> Honsene Andi makaloli '''[[Special:AllPages|{{NUMBEROFARTICLES}}]]''' ga harshe Bole</div>
</div>
</div>
<div style="margin:10px 0px 10px 0px; -moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); -webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); background-color:#FFFFFF;">
{| style="border-spacing: 1px; border-collapse: separate; width:100%; text-align:center; font-size:0.85em; padding:2px 3px 2px 3px;" class="hp-portalen"
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Atiimala|<span style="color:#000000;">Atiimala</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Annoba|<span style="color:#000000;">Annoba</span>]]
| style="background-color:#F0F4F9; border-top:5px solid; border-color:#336699; padding:3px 0.15em; width:6.6%;" | [[:Category:Fasaha|<span style="color:#000000;">Fasaha</span>]]
| style="background-color:#F9F0F0; border-top:5px solid; border-color:#993333; padding:3px 0.15em; width:6.6%;" | [[:Category:Ilimi|<span style="color:#000000;">Ilimi</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Lamba|<span style="color:#000000;">Lamba</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Miyya|<span style="color:#000000;">Miyya</span>]]
| style="background-color:#F9F9F0; border-top:5px solid; border-color:#999933; padding:3px 0.15em; width:6.6%;" | [[:Category:Makami|<span style="color:#000000;">Makami</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Malunwa|<span style="color:#000000;">Malunwa</span>]]
| style="background-color:#F0F9F0; border-top:5px solid; border-color:#339933; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii|<span style="color:#000000;">Olii</span>]]
| style="background-color:#F9F0F4; border-top:5px solid; border-color:#993366; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii pewe|<span style="color:#000000;">Olii pewe</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Tarihi|<span style="color:#000000;">Tarihi</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Goma|<span style="color:#000000;">Goma</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Kimiyya|<span style="color:#000000;">Kimiyya</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Zane|<span style="color:#000000;">Zane</span>]]
|}
</div>
<templatestyles src="Main page/Styles.css" />
<div style="flex:1; min-width:300px; overflow:hidden; border-radius:4px; margin:8px 4px 4px 4px; box-shadow:0 0 8px rgba(0,0,0,0.15);">
<div class="image-carousel">
<ul>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Star-alt-icon.png|20px|link=]] Featured Article</div>
</div>
<div class="carousel-image">
[[File:The City Gate of Abuja.jpg|center|class=carousel-image-wrapper|link=Nijeriya|Nijeriya]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Nijeriya ko Nijeriya da (turanci: Nigeria): A Gwamanatance Tarayyar Najeriya, woli la ga take ga Africa ko zoni ita ji tetteke woli niger koga Arewa. Ga Chadi koga zoni koga aushi jam aji dar ga teku Atlantika.</div>
<div class="carousel-slide-title">[[Nijeriya]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat sign-question.svg|20px|link=]] Kamontuwo?</div>
</div>
<div class="carousel-image">
[[File:Gooya mountain.jpg|center|class=carousel-image-wrapper|link=Gooya mountain]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Gooya kam zoi wuro la tudu ga arewa [[Nijeriya]], inda Bòo pikka ye kam la yare miyya aji magana da yawa ga yankin da ke kewaye.
</div>
<div class="carousel-slide-title">[[Potiskum]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[File:Paomedia small-n-flat file-picture.svg|20px|link=]] Featured Picture</div>
</div>
<div class="carousel-image">
[[File:Daniski Festival 04.jpg|center|class=carousel-image-wrapper|link=File:Daniski Festival 04.jpg]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Daniski Hills Annual Festival kam zoi tarayya la al’ada, ba Bòo pikka ga Fika Emirate ga Yobe State, [[Nijeriya]].
</div>
<div class="carousel-slide-title">[[:File:Daniski Festival 04.jpg|Daniski Festival Picture]]</div>
</div>
</div>
</li>
</ul>
</div>
</div>
<div style="display:flex; flex-wrap:wrap;">
{{Box
|header=[[File:Paomedia small-n-flat sign-info.svg|20px|link=]] Elle Wikipidiya?
|content=<span style="float: left; margin: 6px 12px 6px 0px; display: inline-block;">[[File:Wikipedia-logo-v2-bol.svg|100px]]</span>Wikipidiya shafi ji in Yana gizonla ona gudumawa inko rubutu mukalai kala aji gidan ga goggo gozi ilmi do ramu-ramu ga messesu. Gabo turanci ga unda shap Maddi la ramu ramu do gede ga ilmi ga shafuka Wikipedia ga sun Wikipedia, wikipidiya aji tattira ga harsuna GA duniya ga godon shafuka lemalo aji kirkira do ramu mukalai gabo kyauta inko taimako beyi wena ilmi bo kyauta, emeyye aji Wikipedia ga zarrar a shap ga duniya beyi wena ilmi koga asali beyi ilmi fetengo.
}}
{{Box
|header=[[File:Paomedia small-n-flat pencil.svg|20px|link=]] Kirkiru Foyo Article
|content=Kaji kume Harshe Bole? Kagita ina taimako beyi Bunƙasa kunsu eme Mona (ensakulopidiya) ko goggo kirkire foyo makaloli do fadada la aji Andi ga fatan aji doffa ka'idoji Al'umma lokaci ona ga gundumawa.<br><small><i></i></small>
<div style="margin-top:1em;">
<inputbox>
type=create
width=30
default=
buttonlabel=Kirkiru Foyo Makala
</inputbox>
</div>
}}
</div>
{{Box
|header=English speakers
|content=If you speak English, but you don't know anything about the Bole Language, you are also welcome to edit and assist in technical support, such as maintaining Templates or Modules. Your role is vital to the smooth running of the Bole Wikipedia!
}}
{{Box
|header=[[File:Wikimedia-logo.svg|20px|link=]] Project Modi
|content={{SisterProjects}}
}}
sjqv31r9u27s4t0bq3v2o3743u10zie
Tempilet:Ambox
10
40
9136
78
2026-08-22T14:42:25Z
RAPTOR7762
18
Protected "[[Tempilet:Ambox]]": High traffic page ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
77
wikitext
text/x-wiki
{{#invoke:Message box|ambox}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
pishm14b7r8s9qmic2anyb35b75ycvs
Tempilet:Ambox/doc
10
41
9289
85
2026-08-23T04:35:24Z
RAPTOR7762
18
9289
wikitext
text/x-wiki
{{pp-protected}}
{{Mbox templates}}
== Usage ==
Simple usage example:
<syntaxhighlight>
{{Ambox
| text = Some text.
}}
</syntaxhighlight>
{{Ambox
| text = Some text.
}}
== Ambox types ==
{{Ambox
| type = speedy
| text = <code>type{{=}}speedy</code> – Speedy deletion templates.
}}
{{Ambox
| type = delete
| text = <code>type{{=}}delete</code> – Deletion templates.
}}
{{Ambox
| type = content
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = style
| text = <code>type{{=}}style</code> – Minor warnings and problems.
}}
{{Ambox
| type = notice
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = move
| text = <code>type{{=}}content</code> – Merge, split, rename and transwiki messages and proposals.
}}
{{Ambox
| type = protection
| text = <code>type{{=}}content</code> – Protection templates such as {{Tl|Pp}} when shown on "other pages"
}}
34m5uwpkuou98lwhqkh6oauq8pl37ul
9290
9289
2026-08-23T04:36:19Z
RAPTOR7762
18
9290
wikitext
text/x-wiki
{{pp-protected}}
{{template rating|release}}
{{Mbox templates}}
== Usage ==
Simple usage example:
<syntaxhighlight>
{{Ambox
| text = Some text.
}}
</syntaxhighlight>
{{Ambox
| text = Some text.
}}
== Ambox types ==
{{Ambox
| type = speedy
| text = <code>type{{=}}speedy</code> – Speedy deletion templates.
}}
{{Ambox
| type = delete
| text = <code>type{{=}}delete</code> – Deletion templates.
}}
{{Ambox
| type = content
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = style
| text = <code>type{{=}}style</code> – Minor warnings and problems.
}}
{{Ambox
| type = notice
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = move
| text = <code>type{{=}}content</code> – Merge, split, rename and transwiki messages and proposals.
}}
{{Ambox
| type = protection
| text = <code>type{{=}}content</code> – Protection templates such as {{Tl|Pp}} when shown on "other pages"
}}
8akr4oi597kky1x8hwhu5gfhfp7nues
9292
9290
2026-08-23T04:38:12Z
RAPTOR7762
18
9292
wikitext
text/x-wiki
{{pp-protected|small=yes}}
{{template rating|release}}
{{Mbox templates}}
== Usage ==
Simple usage example:
<syntaxhighlight>
{{Ambox
| text = Some text.
}}
</syntaxhighlight>
{{Ambox
| text = Some text.
}}
== Ambox types ==
{{Ambox
| type = speedy
| text = <code>type{{=}}speedy</code> – Speedy deletion templates.
}}
{{Ambox
| type = delete
| text = <code>type{{=}}delete</code> – Deletion templates.
}}
{{Ambox
| type = content
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = style
| text = <code>type{{=}}style</code> – Minor warnings and problems.
}}
{{Ambox
| type = notice
| text = <code>type{{=}}content</code> – Major warnings and problems.
}}
{{Ambox
| type = move
| text = <code>type{{=}}content</code> – Merge, split, rename and transwiki messages and proposals.
}}
{{Ambox
| type = protection
| text = <code>type{{=}}content</code> – Protection templates such as {{Tl|Pp}} when shown on "other pages"
}}
n3ic3sv12q8q9s084vdroh1yf0lmm0k
Tempilet:Box
10
44
9531
8995
2026-08-23T11:18:27Z
RAPTOR7762
18
9531
wikitext
text/x-wiki
<div style="flex:1; min-width:300px; overflow:hidden; border-radius:4px; margin:4px; background:#FFF; box-shadow:0 0 8px rgba(0,0,0,0.15);">
{{#if:{{{header|Header}}}|<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif;">
<div style="padding:5px 10px; color:{{#switch:{{{color|}}}|merah=#E5484D|kuning=#E5B633|hijau=#79B022|biru=#14679E|ungu=#6A4C93|#default=#333333}};">{{{header|Header}}}</div></div>|}}
<div style="padding:15px; overflow:auto;">{{{content|Content}}}</div>
</div>
<noinclude>
{{Documentation}}
</noinclude>
29wyt6424rzzo752zoqnf376hj4ny7h
Tempilet:Clear
10
49
9133
8288
2026-08-22T14:39:00Z
RAPTOR7762
18
Protected "[[Tempilet:Clear]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
8288
wikitext
text/x-wiki
<div style="clear:{{{1|both}}};" class={{{class|}}}></div><noinclude>
{{Documentation}}
</noinclude>
17aszado3hry2vhcvwg5rsftmytfm6b
9233
2024-02-13T14:32:36Z
en>Redrose64
0
pass class through
9233
wikitext
text/x-wiki
<div style="clear:{{{1|both}}};" class={{{class|}}}></div><noinclude>
{{documentation}}
</noinclude>
an9yinekx1cqo1nkoi5u8nuqub9qbvg
9234
9133
2026-08-23T03:37:34Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Clear]]
8288
wikitext
text/x-wiki
<div style="clear:{{{1|both}}};" class={{{class|}}}></div><noinclude>
{{Documentation}}
</noinclude>
17aszado3hry2vhcvwg5rsftmytfm6b
Tempilet:Cmbox
10
53
9134
147
2026-08-22T14:41:10Z
RAPTOR7762
18
Protected "[[Tempilet:Cmbox]]": High traffic page ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
146
wikitext
text/x-wiki
{{#invoke:Message box|cmbox}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
ao1ddpsq92az598hhsmuto1v16w7o60
9135
9134
2026-08-22T14:41:59Z
RAPTOR7762
18
Changed protection settings for "[[Tempilet:Cmbox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
146
wikitext
text/x-wiki
{{#invoke:Message box|cmbox}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
ao1ddpsq92az598hhsmuto1v16w7o60
Tempilet:Documentation
10
81
9141
8879
2026-08-22T14:46:18Z
RAPTOR7762
18
Protected "[[Tempilet:Documentation]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
295
wikitext
text/x-wiki
{{#invoke:Documentation|main|_content={{ {{#invoke:Documentation|contentTitle}}}}}}<noinclude>
<!-- Add categories to the /doc subpage -->
</noinclude>
0ewc0zrrhhwemyqxzzlg1kd31r4j5zn
Tempilet:Fmbox
10
93
9138
344
2026-08-22T14:43:12Z
RAPTOR7762
18
Protected "[[Tempilet:Fmbox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
343
wikitext
text/x-wiki
{{#invoke:Message box|fmbox}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
qndjs6isv01yuo18vex1kjat7p94i9s
Tempilet:High-use
10
100
9069
2023-05-30T09:39:48Z
en>Lectonar
0
Changed protection settings for "[[Template:High-use]]": [[WP:High-risk templates|High-risk template or module]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9069
wikitext
text/x-wiki
{{#invoke:High-use|main|1={{{1|}}}|2={{{2|}}}|info={{{info|}}}|demo={{{demo|}}}|form={{{form|}}}|expiry={{{expiry|}}}|system={{{system|}}}}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwiki links go to Wikidata, thank you! -->
</noinclude>
j29sm6019piulvmp7rcudlkhl1yuxmv
9070
372
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Template:High-use]]
371
wikitext
text/x-wiki
{{Ombox
| image = [[Fayil:Ambox warning yellow.svg|40px|link=]]
| text = <strong>Template na ye a yi amfani ga shafuka kusan {{{1|n}}}</strong>, amma canji da ka yi za a gani sosai. Gwada canji a shafin /sandbox ko /testcases na template, ko a shafin ka. Ka yi magana a shafin magana kafin ka yi canji.<hr><small>This template is used on approximately {{{1|n}}} pages and changes may be widely noticed. Test changes in the template's /sandbox or /testcases subpages, or in your own user subpage. Consider discussing changes on the talk page before implementing them.</small>
| type = style
}}
palz45qjhiivl59sak2hee3671ncvqq
Tempilet:Main other
10
129
9017
2025-07-28T14:53:49Z
en>Pppery
0
Make substable per request
9017
wikitext
text/x-wiki
{{safesubst:<noinclude/>#switch:
<noinclude><!-- If no or empty "demospace" parameter then detect namespace --></noinclude>
{{safesubst:<noinclude/>#if:{{{demospace|}}}
| {{safesubst:<noinclude/>lc: {{{demospace}}} }} <noinclude><!-- Use lower case "demospace" --></noinclude>
| {{safesubst:<noinclude/>#ifeq:{{safesubst:<noinclude/>NAMESPACE}}|{{safesubst:<noinclude/>ns:0}}
| main
| other
}}
}}
| main = {{{1|}}}
| other
| #default = {{{2|}}}
}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
aljcm6nr1pwk5dw5g13lyhxhplulpg5
9018
670
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Main_other]]
669
wikitext
text/x-wiki
{{safesubst:<noinclude/>#switch:
<noinclude><!-- If no or empty "demospace" parameter then detect namespace --></noinclude>
{{safesubst:<noinclude/>#if:{{{demospace|}}}
| {{safesubst:<noinclude/>lc: {{{demospace}}} }} <noinclude><!-- Use lower case "demospace" --></noinclude>
| {{safesubst:<noinclude/>#ifeq:{{safesubst:<noinclude/>NAMESPACE}}|{{safesubst:<noinclude/>ns:0}}
| main
| other
}}
}}
| main = {{{1|}}}
| other
| #default = {{{2|}}}
}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
bzdu3898l39aig9lyxswxzk8auxdcwo
Tempilet:Main page/Styles.css
10
130
9209
672
2026-08-23T03:28:05Z
RAPTOR7762
18
Protected "[[Tempilet:Main page/Styles.css]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
671
sanitized-css
text/css
/* Derived from https://ay.wikipedia.org/wiki/Plantilla:Portada/styles.css (2025-06-06) */
.image-carousel {
overflow: hidden;
width: 100%;
height: 210px;
min-width: 280px;
}
.image-carousel ul {
width: 100%;
margin: 0;
padding: 0;
display: table;
table-layout: fixed;
height: 100%;
}
.image-carousel ul li {
display: table-cell;
vertical-align: top;
position: relative;
height: 100%;
min-height: 210px;
width: 33.33333%;
transition: all 1000ms ease;
}
.carousel-image {
width: 100%;
height: 100%;
display: block;
position: relative;
overflow: hidden;
}
.carousel-image-wrapper {
position: absolute;
display: block;
width: 100%;
height: 100%;
z-index: 1;
}
.carousel-image-wrapper img {
width: 100%;
height: 100%;
min-height: 170px;
object-fit: cover;
position: absolute;
top: 0;
left: 0;
}
.carousel-slide-content-wrapper {
overflow: hidden;
width: 100%;
height: calc(100% - 40px);
position: absolute;
top: 40px;
}
.carousel-slide-content {
display: flex;
flex-direction: column;
justify-content: flex-end;
height: 100%;
width: 100%;
position: relative;
padding: 15px 20px;
box-sizing: border-box;
color: #fff;
z-index: 3;
}
.carousel-slide-content .carousel-slide-title,
.carousel-slide-content .carousel-slide-description {
opacity: 0;
width: 100%;
position: relative;
}
.carousel-slide-title {
font-size: 135%;
font-weight: bold;
text-align: right;
}
.carousel-slide-description {
text-align: left;
}
@media (min-width: 800px) {
.image-carousel ul:hover li {
width: 10%;
}
.image-carousel ul:hover li:hover {
width: 60%;
}
.image-carousel ul:hover li:hover .carousel-slide-content {
background: rgba(0, 0, 0, 0.7);
}
.image-carousel ul:hover li:hover .carousel-slide-title,
.image-carousel ul:hover li:hover .carousel-slide-description {
opacity: 1;
}
}
.carousel-slide-title a {
font-weight: bold;
}
.carousel-slide-title a,
.carousel-slide-description a {
color: white;
}
.carousel-slide-title a:link,
.carousel-slide-title a:visited,
.carousel-slide-title a:hover,
.carousel-slide-title a:active,
.carousel-slide-description a:link,
.carousel-slide-description a:visited,
.carousel-slide-description a:hover,
.carousel-slide-description a:active {
color: white;
}
@media (max-width: 800px) {
.image-carousel {
height: auto;
min-height: unset;
}
.image-carousel ul {
display: block;
height: auto;
}
.image-carousel ul li {
display: block;
width: 100%;
height: auto;
min-height: unset;
transition: none;
}
.carousel-image {
height: auto;
}
.carousel-image-wrapper {
position: relative;
height: auto;
}
.carousel-image-wrapper img {
position: relative;
width: 100%;
height: auto;
min-height: unset;
object-fit: cover;
}
.carousel-slide-content-wrapper {
position: relative;
height: auto;
top: auto;
}
.carousel-slide-content {
position: relative;
background: rgba(0, 0, 0, 0.6);
padding: 10px;
color: white;
}
/* Override opacity on mobile */
.carousel-slide-content-wrapper .carousel-slide-title,
.carousel-slide-content-wrapper .carousel-slide-description {
opacity: 1;
}
/* Disable hover effect for mobile */
.image-carousel ul:hover li {
width: 100%;
}
.image-carousel ul:hover li:hover {
width: 100%;
}
.image-carousel ul:hover li:hover .carousel-slide-content {
background: rgba(0, 0, 0, 0.6);
}
}
oo3w83swmvqsq5j8si7i4akgkk2svge
9210
9209
2026-08-23T03:28:39Z
RAPTOR7762
18
9210
sanitized-css
text/css
/* {{pp-protected|small=yes}}
Derived from https://ay.wikipedia.org/wiki/Plantilla:Portada/styles.css (2025-06-06) */
.image-carousel {
overflow: hidden;
width: 100%;
height: 210px;
min-width: 280px;
}
.image-carousel ul {
width: 100%;
margin: 0;
padding: 0;
display: table;
table-layout: fixed;
height: 100%;
}
.image-carousel ul li {
display: table-cell;
vertical-align: top;
position: relative;
height: 100%;
min-height: 210px;
width: 33.33333%;
transition: all 1000ms ease;
}
.carousel-image {
width: 100%;
height: 100%;
display: block;
position: relative;
overflow: hidden;
}
.carousel-image-wrapper {
position: absolute;
display: block;
width: 100%;
height: 100%;
z-index: 1;
}
.carousel-image-wrapper img {
width: 100%;
height: 100%;
min-height: 170px;
object-fit: cover;
position: absolute;
top: 0;
left: 0;
}
.carousel-slide-content-wrapper {
overflow: hidden;
width: 100%;
height: calc(100% - 40px);
position: absolute;
top: 40px;
}
.carousel-slide-content {
display: flex;
flex-direction: column;
justify-content: flex-end;
height: 100%;
width: 100%;
position: relative;
padding: 15px 20px;
box-sizing: border-box;
color: #fff;
z-index: 3;
}
.carousel-slide-content .carousel-slide-title,
.carousel-slide-content .carousel-slide-description {
opacity: 0;
width: 100%;
position: relative;
}
.carousel-slide-title {
font-size: 135%;
font-weight: bold;
text-align: right;
}
.carousel-slide-description {
text-align: left;
}
@media (min-width: 800px) {
.image-carousel ul:hover li {
width: 10%;
}
.image-carousel ul:hover li:hover {
width: 60%;
}
.image-carousel ul:hover li:hover .carousel-slide-content {
background: rgba(0, 0, 0, 0.7);
}
.image-carousel ul:hover li:hover .carousel-slide-title,
.image-carousel ul:hover li:hover .carousel-slide-description {
opacity: 1;
}
}
.carousel-slide-title a {
font-weight: bold;
}
.carousel-slide-title a,
.carousel-slide-description a {
color: white;
}
.carousel-slide-title a:link,
.carousel-slide-title a:visited,
.carousel-slide-title a:hover,
.carousel-slide-title a:active,
.carousel-slide-description a:link,
.carousel-slide-description a:visited,
.carousel-slide-description a:hover,
.carousel-slide-description a:active {
color: white;
}
@media (max-width: 800px) {
.image-carousel {
height: auto;
min-height: unset;
}
.image-carousel ul {
display: block;
height: auto;
}
.image-carousel ul li {
display: block;
width: 100%;
height: auto;
min-height: unset;
transition: none;
}
.carousel-image {
height: auto;
}
.carousel-image-wrapper {
position: relative;
height: auto;
}
.carousel-image-wrapper img {
position: relative;
width: 100%;
height: auto;
min-height: unset;
object-fit: cover;
}
.carousel-slide-content-wrapper {
position: relative;
height: auto;
top: auto;
}
.carousel-slide-content {
position: relative;
background: rgba(0, 0, 0, 0.6);
padding: 10px;
color: white;
}
/* Override opacity on mobile */
.carousel-slide-content-wrapper .carousel-slide-title,
.carousel-slide-content-wrapper .carousel-slide-description {
opacity: 1;
}
/* Disable hover effect for mobile */
.image-carousel ul:hover li {
width: 100%;
}
.image-carousel ul:hover li:hover {
width: 100%;
}
.image-carousel ul:hover li:hover .carousel-slide-content {
background: rgba(0, 0, 0, 0.6);
}
}
sz8juqosohkrcp5ginrk9c6vuwsy025
Tempilet:Mbox
10
136
9095
2022-12-18T05:46:16Z
en>TadejM
0
9095
wikitext
text/x-wiki
{{#invoke:Message box|mbox}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
aqsrswx233se5jbjaza2b2hrk7pgx53
9096
700
2026-08-22T14:37:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Mbox]]
699
wikitext
text/x-wiki
{{#invoke:Message box|mbox}}<noinclude>
{{Documentation}}
</noinclude>
pvm9nlvkt71tloexx1r8m88i47rdcul
9140
9096
2026-08-22T14:43:52Z
RAPTOR7762
18
Protected "[[Tempilet:Mbox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
699
wikitext
text/x-wiki
{{#invoke:Message box|mbox}}<noinclude>
{{Documentation}}
</noinclude>
pvm9nlvkt71tloexx1r8m88i47rdcul
Tempilet:Ombox
10
151
9139
8301
2026-08-22T14:43:31Z
RAPTOR7762
18
Protected "[[Tempilet:Ombox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
8301
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{Documentation}}
</noinclude>
qq88dkmr0d25v74aki6n3grywd06t6e
9362
2020-04-01T06:12:36Z
en>MusikAnimal
0
1 revision imported
9362
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
1o93yrjvq6v2ylug2k0uaaltljurje2
9363
9139
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Ombox]]
8301
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{Documentation}}
</noinclude>
qq88dkmr0d25v74aki6n3grywd06t6e
Tempilet:Plainlist/styles.css
10
156
9081
2022-12-11T06:59:53Z
en>Izno
0
add this reset from mobile.css
9081
sanitized-css
text/css
/* {{pp-template|small=yes}} */
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
padding: 0; /* Reset Minerva default */
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
9iguthb0t8w7c89r3am2dbgv55d4w1c
9082
802
2026-08-22T12:06:30Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Plainlist/styles.css]]
801
sanitized-css
text/css
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
padding: 0; /* Reset Minerva default */
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
2iy4a0uss4epemofk3s8a02vftiou1z
Tempilet:Redirect
10
158
9059
2018-02-27T17:34:09Z
en>Primefac
0
[[Wikipedia:Templates for discussion/Log/2018 February 18#Template:Redirect3_and_Template:About2]] closed as merge ([[WP:XFDC|XFDcloser]])
9059
wikitext
text/x-wiki
<includeonly>{{#invoke:redirect hatnote|redirect|1}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
nahryqse47xqenividwc88opp02rhjv
9060
8302
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Redirect]]
8302
wikitext
text/x-wiki
{{Hatnote|"{{{1|}}}" redirects here. {{About|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}|{{{6|}}}}}}}<noinclude>
</noinclude>
cyu03xsxbpz3glilg61ghyse3h1h3gg
Tempilet:Reflist
10
159
9023
2025-12-17T13:08:01Z
en>Anomie
0
VE for some reason requires a div wrapping the references tag. 🤷
9023
wikitext
text/x-wiki
<templatestyles src="Reflist/styles.css" /><!--
-->{{#switch:{{{liststyle}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=<div class="reflist-liststyle-{{{liststyle}}}">
<nowiki/>}}<!--
-->{{#if:{{{1|}}}{{{colwidth|}}}|
<div class="mw-references-wrap <!--
-->{{#iferror:{{#ifexpr: {{{1|}}} > 1 }}|mw-references-columns|{{#switch:{{{1|}}}|1=|2=mw-references-columns reflist-columns-2|#default=mw-references-columns reflist-columns-3}} }}" <!-- end class
-->{{#if: {{{1|}}}<!-- start style. The multiplication by 0.9 is for [[hysterical raisins]]. -->
| {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }} |style="column-width: calc( 0.9 * {{{1}}} );"}}
| {{#if: {{{colwidth|}}}|style="column-width: calc( 0.9 * {{{colwidth}}} );"}}
}}>{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive=0}}</div>
|
<div><!-- VE for some reason requires a div wrapping the references tag. 🤷 -->
{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive=1}}</div>
}}<!--
-->{{#switch:{{{liststyle}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=</div>}}<!--
-->{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}<noinclude>
{{Documentation}}
</noinclude>
6ru6cuze0qz3wvjdrkqztati1gmdgd2
9024
810
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Reflist]]
809
wikitext
text/x-wiki
<templatestyles src="Reflist/styles.css" /><!--
-->{{#switch:{{{liststyle}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=<div class="reflist-liststyle-{{{liststyle}}}">
<nowiki/>}}<!--
-->{{#if:{{{1|}}}{{{colwidth|}}}|
<div class="mw-references-wrap <!--
-->{{#iferror:{{#ifexpr: {{{1|}}} > 1 }}|mw-references-columns|{{#switch:{{{1|}}}|1=|2=mw-references-columns reflist-columns-2|#default=mw-references-columns reflist-columns-3}} }}" <!-- end class
-->{{#if: {{{1|}}}<!-- start style. The multiplication by 0.9 is for [[hysterical raisins]]. -->
| {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }} |style="column-width: calc( 0.9 * {{{1}}} );"}}
| {{#if: {{{colwidth|}}}|style="column-width: calc( 0.9 * {{{colwidth}}} );"}}
}}>{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive=0}}</div>
|
<div><!-- VE for some reason requires a div wrapping the references tag. 🤷 -->
{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive=1}}</div>
}}<!--
-->{{#switch:{{{liststyle}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=</div>}}<!--
-->{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Panni:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Tempilet:Reflist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}<noinclude>
{{Documentation}}
</noinclude>
fmxnyc9kl47uezp6tuvydn0e7z2v2py
Tempilet:Reflist/styles.css
10
160
9025
2025-12-13T15:43:44Z
en>Anomie
0
Update to reduce differences in behavior between {{reflist}} and <references/>. See talk. Note, if this breaks some custom styles you have, likely they were already broken with <references/> and you should take this opportunity to update them.
9025
sanitized-css
text/css
/* {{pp|small=yes}} */
/* columns-2 and columns-3 are legacy for "2 or more" column view from when the
* template was implemented with column-count.
*/
.reflist-columns-2 {
column-width: 30em;
}
.reflist-columns-3 {
column-width: 25em;
}
/* Match Vector 2022 after [[gerrit:1185300]]. */
body.skin-vector-2022 .reflist-columns-2 {
column-width: 27em;
}
body.skin-vector-2022 .reflist-columns-3 {
column-width: 22.5em;
}
/* These should probably be moved to MediaWiki:Common.css to work with <references> as well. */
.references[data-mw-group=upper-alpha] {
list-style-type: upper-alpha;
}
.references[data-mw-group=upper-roman] {
list-style-type: upper-roman;
}
.references[data-mw-group=lower-alpha] {
list-style-type: lower-alpha;
}
.references[data-mw-group=lower-greek] {
list-style-type: lower-greek;
}
.references[data-mw-group=lower-roman] {
list-style-type: lower-roman;
}
/* Liststyle param. */
div.reflist-liststyle-upper-alpha .references {
list-style-type: upper-alpha;
}
div.reflist-liststyle-upper-roman .references {
list-style-type: upper-roman;
}
div.reflist-liststyle-lower-alpha .references {
list-style-type: lower-alpha;
}
div.reflist-liststyle-lower-greek .references {
list-style-type: lower-greek;
}
div.reflist-liststyle-lower-roman .references {
list-style-type: lower-roman;
}
0y79vyw9wqc26bp1ubg1khshuusjvc4
9026
812
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Reflist/styles.css]]
811
sanitized-css
text/css
/* {{pp|small=yes}} */
/* columns-2 and columns-3 are legacy for "2 or more" column view from when the
* template was implemented with column-count.
*/
.reflist-columns-2 {
column-width: 30em;
}
.reflist-columns-3 {
column-width: 25em;
}
/* Match Vector 2022 after [[gerrit:1185300]]. */
body.skin-vector-2022 .reflist-columns-2 {
column-width: 27em;
}
body.skin-vector-2022 .reflist-columns-3 {
column-width: 22.5em;
}
/* These should probably be moved to MediaWiki:Common.css to work with <references> as well. */
.references[data-mw-group=upper-alpha] {
list-style-type: upper-alpha;
}
.references[data-mw-group=upper-roman] {
list-style-type: upper-roman;
}
.references[data-mw-group=lower-alpha] {
list-style-type: lower-alpha;
}
.references[data-mw-group=lower-greek] {
list-style-type: lower-greek;
}
.references[data-mw-group=lower-roman] {
list-style-type: lower-roman;
}
/* Liststyle param. */
div.reflist-liststyle-upper-alpha .references {
list-style-type: upper-alpha;
}
div.reflist-liststyle-upper-roman .references {
list-style-type: upper-roman;
}
div.reflist-liststyle-lower-alpha .references {
list-style-type: lower-alpha;
}
div.reflist-liststyle-lower-greek .references {
list-style-type: lower-greek;
}
div.reflist-liststyle-lower-roman .references {
list-style-type: lower-roman;
}
0y79vyw9wqc26bp1ubg1khshuusjvc4
Tempilet:Template link
10
176
9168
8827
2026-08-23T01:43:46Z
RAPTOR7762
18
Protected "[[Tempilet:Template link]]" ([Ramu=Allow only autoconfirmed users] (indefinite) [Zeme=Allow only autoconfirmed users] (indefinite))
8307
wikitext
text/x-wiki
<code><nowiki>{{</nowiki>[[Tempilet:{{{1|Foo}}}|{{{1|Foo}}}]]<nowiki>}}</nowiki></code><noinclude>
{{Documentation}}
</noinclude>
hjhgf10ddd6etez99giddmrtj1vkdqb
9201
9168
2026-08-23T02:55:36Z
RAPTOR7762
18
/* */
9201
wikitext
text/x-wiki
<code><nowiki>{{</nowiki>[[Tempilet:{{{1|Foo}}}|{{{1|Foo}}}]]<nowiki>}}</nowiki></code><noinclude>
{{Documentation}}
</noinclude>
8g2baw9x5ifq07lgic9eo5pa5e771vj
Tempilet:Tmbox
10
183
9137
913
2026-08-22T14:42:55Z
RAPTOR7762
18
Protected "[[Tempilet:Tmbox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
912
wikitext
text/x-wiki
{{#invoke:Message box|tmbox}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
9dp1xebk27mjywck966g7u60j9vi29b
Tempilet:Tmbox/doc
10
184
9291
916
2026-08-23T04:37:34Z
RAPTOR7762
18
9291
wikitext
text/x-wiki
{{pp-protected|small=yes}}
{{template rating|release}}
{{Mbox templates}}
This is the {{Tl|Tmbox}} (['''T''']alk page ['''m''']essage ['''box''']) [[WP:MTM|metatemplate]]. This template is called by other templates to give a consistent structure and appearance to boilerplate messages used on talk pages across the project. It ''may'' be called directly on a talk page in order to present a one-off message in the same format as boilerplate messages, but this is non-standard (if a message is important enough to be presented in this form, you should consider creating a separate template so that it is easily available to other editors). Tmbox offers several different colors for different purposes, provides default images if no image parameter is given, and has some other pleasant features. This template works similarly to {{Tl|Ambox}} and uses the same parameters.
This template should not be used for WikiProject banners. Such banners have special programming constraints that merit their own meta-templates. See the "See also" section below for links.
=== Suggested style standard ===
The types of talkpage messageboxes follow the same naming convention as the boxes for all other namespaces, but the type of any particular talkpage messagebox may not be as obvious as in other namespaces. When deciding on the type to use for a talkpage messagebox, please consider the following guidelines:
* '''speedy''' should ''only'' be used for [[:Category:Speedy deletion templates|speedy deletion templates]].
* '''delete''' should ''only'' be used for templates relating to ''ongoing'' deletion discussions. Please do ''not'' use this type just to get a red border for a messagebox.
* '''content''' and '''style''' should be used for warnings and alerts. Use '''content''' (which has an orange border) for more important and immediate alerts, and '''style''' (yellow border) for less important warnings. Messageboxes of these types should ideally be ''transitory'': they should not be expected to remain on a talkpage indefinitely.
* '''move''' and '''protection''' should only be used for messageboxes relating to moves and merges, and page protection, respectively.
* The '''notice''' type should be used for the majority of talkpage messageboxes; those that are intended to convey or summarise information. If a talkpage messagebox does not obviously fit into one of the other types, it is probably a notice type.
=== Usage ===
Simple usage example:
<syntaxhighlight lang="wikitext">
{{Tmbox | text = Some text.}}
</syntaxhighlight>
{{Tmbox | text = Some text.}}
=== Talk page message box types ===
The following examples use different '''type''' parameters but use no image parameters thus they use the default images for each type.
{{Tmbox
| type = speedy
| text = type=<u>speedy</u> – Speedy deletion templates.
}}
{{Tmbox
| type = delete
| text = type=<u>delete</u> – Deletion templates.
}}
{{Tmbox
| type = content
| text = type=<u>content</u> – Major warnings and problems.
}}
{{Tmbox
| type = style
| text = type=<u>style</u> – Minor warnings and problems.
}}
{{Tmbox
| type = notice
| text = type=<u>notice</u> – Notices and messages of any kind, both permanent and temporary.
}}
{{Tmbox
| type = move
| text = type=<u>move</u> – Merge, split, rename and transwiki messages and proposals.
}}
{{Tmbox
| type = protection
| text = type=<u>protection</u> – Protection templates.
}}
lfj2iaz9dvtcawbp0310omc8c06fx9z
Tempilet:Uses TemplateStyles
10
190
9498
2023-04-18T22:22:16Z
en>Grufo
0
Move the preview inside the documentation
9498
wikitext
text/x-wiki
<includeonly>{{#invoke:Uses TemplateStyles|main}}</includeonly><noinclude>{{documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
bbov914irrnmmvc6pz3scgivkjsu4ve
9499
933
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Uses_TemplateStyles]]
932
wikitext
text/x-wiki
{{Ombox
|image=[[Fayil:Farm-Fresh css add.svg|30px|alt=|link=]]
|text=<small>This {{#switch:{{NAMESPACE}}|Template = template|Module = module}} uses [[Wikipidiya:TemplateStyles|TemplateStyles]]:<br>
<ul>
{{#if:{{{1|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{1}}}]]</li>|<span style="color:#BF3C2C"><big><b>Error: No module specified</b></big></span>}}
{{#if:{{{2|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{2}}}]]</li>|}}
{{#if:{{{3|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{3}}}]]</li>|}}
{{#if:{{{4|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{4}}}]]</li>|}}
{{#if:{{{5|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{5}}}]]</li>|}}
{{#if:{{{6|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{6}}}]]</li>|}}
{{#if:{{{7|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{7}}}]]</li>|}}
{{#if:{{{8|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{8}}}]]</li>|}}
{{#if:{{{9|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{9}}}]]</li>|}}
{{#if:{{{10|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{10}}}]]</li>|}}
{{#if:{{{11|}}}|<li styles="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{11}}}]]</li>|}}
{{#if:{{{12|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{12}}}]]</li>|}}
{{#if:{{{13|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{13}}}]]</li>|}}
{{#if:{{{14|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{14}}}]]</li>|}}
{{#if:{{{15|}}}|<li style="padding:0px; margin-top:2px; margin-bottom:2px; margin-left:0px;">[[{{{15}}}]]</li>|}}
</ul></small>}}<noinclude>
{{Documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
4oajgo2jvqnnnweeqry86np1s1mfv8i
Module:Date
828
230
9090
1032
2026-08-22T14:13:31Z
RAPTOR7762
18
Protected "[[Module:Date]]": High traffic page ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
1031
Scribunto
text/plain
-- Date functions for use by other modules.
-- I18N and time zones are not supported.
local MINUS = '−' -- Unicode U+2212 MINUS SIGN
local floor = math.floor
local Date, DateDiff, diffmt -- forward declarations
local uniq = { 'unique identifier' }
local function is_date(t)
-- The system used to make a date read-only means there is no unique
-- metatable that is conveniently accessible to check.
return type(t) == 'table' and t._id == uniq
end
local function is_diff(t)
return type(t) == 'table' and getmetatable(t) == diffmt
end
local function _list_join(list, sep)
return table.concat(list, sep)
end
local function collection()
-- Return a table to hold items.
return {
n = 0,
add = function (self, item)
self.n = self.n + 1
self[self.n] = item
end,
join = _list_join,
}
end
local function strip_to_nil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (convenient when Date fields are provided from
-- another module which may pass a string, a number, or another type).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local function is_leap_year(year, calname)
-- Return true if year is a leap year.
if calname == 'Julian' then
return year % 4 == 0
end
return (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0
end
local function days_in_month(year, month, calname)
-- Return number of days (1..31) in given month (1..12).
if month == 2 and is_leap_year(year, calname) then
return 29
end
return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month]
end
local function h_m_s(time)
-- Return hour, minute, second extracted from fraction of a day.
time = floor(time * 24 * 3600 + 0.5) -- number of seconds
local second = time % 60
time = floor(time / 60)
return floor(time / 60), time % 60, second
end
local function hms(date)
-- Return fraction of a day from date's time, where (0 <= fraction < 1)
-- if the values are valid, but could be anything if outside range.
return (date.hour + (date.minute + date.second / 60) / 60) / 24
end
local function julian_date(date)
-- Return jd, jdz from a Julian or Gregorian calendar date where
-- jd = Julian date and its fractional part is zero at noon
-- jdz = same, but assume time is 00:00:00 if no time given
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- Testing shows this works for all dates from year -9999 to 9999!
-- JDN 0 is the 24-hour period starting at noon UTC on Monday
-- 1 January 4713 BC = (-4712, 1, 1) Julian calendar
-- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar
local offset
local a = floor((14 - date.month)/12)
local y = date.year + 4800 - a
if date.calendar == 'Julian' then
offset = floor(y/4) - 32083
else
offset = floor(y/4) - floor(y/100) + floor(y/400) - 32045
end
local m = date.month + 12*a - 3
local jd = date.day + floor((153*m + 2)/5) + 365*y + offset
if date.hastime then
jd = jd + hms(date) - 0.5
return jd, jd
end
return jd, jd - 0.5
end
local function set_date_from_jd(date)
-- Set the fields of table date from its Julian date field.
-- Return true if date is valid.
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- This handles the proleptic Julian and Gregorian calendars.
-- Negative Julian dates are not defined but they work.
local calname = date.calendar
local low, high -- min/max limits for date ranges −9999-01-01 to 9999-12-31
if calname == 'Gregorian' then
low, high = -1930999.5, 5373484.49999
elseif calname == 'Julian' then
low, high = -1931076.5, 5373557.49999
else
return
end
local jd = date.jd
if not (type(jd) == 'number' and low <= jd and jd <= high) then
return
end
local jdn = floor(jd)
if date.hastime then
local time = jd - jdn -- 0 <= time < 1
if time >= 0.5 then -- if at or after midnight of next day
jdn = jdn + 1
time = time - 0.5
else
time = time + 0.5
end
date.hour, date.minute, date.second = h_m_s(time)
else
date.second = 0
date.minute = 0
date.hour = 0
end
local b, c
if calname == 'Julian' then
b = 0
c = jdn + 32082
else -- Gregorian
local a = jdn + 32044
b = floor((4*a + 3)/146097)
c = a - floor(146097*b/4)
end
local d = floor((4*c + 3)/1461)
local e = c - floor(1461*d/4)
local m = floor((5*e + 2)/153)
date.day = e - floor((153*m + 2)/5) + 1
date.month = m + 3 - 12*floor(m/10)
date.year = 100*b + d - 4800 + floor(m/10)
return true
end
local function fix_numbers(numbers, y, m, d, H, M, S, partial, hastime, calendar)
-- Put the result of normalizing the given values in table numbers.
-- The result will have valid m, d values if y is valid; caller checks y.
-- The logic of PHP mktime is followed where m or d can be zero to mean
-- the previous unit, and -1 is the one before that, etc.
-- Positive values carry forward.
local date
if not (1 <= m and m <= 12) then
date = Date(y, 1, 1)
if not date then return end
date = date + ((m - 1) .. 'm')
y, m = date.year, date.month
end
local days_hms
if not partial then
if hastime and H and M and S then
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
days_hms = hms({ hour = H, minute = M, second = S })
end
end
if days_hms or not (1 <= d and d <= days_in_month(y, m, calendar)) then
date = date or Date(y, m, 1)
if not date then return end
date = date + (d - 1 + (days_hms or 0))
y, m, d = date.year, date.month, date.day
if days_hms then
H, M, S = date.hour, date.minute, date.second
end
end
end
numbers.year = y
numbers.month = m
numbers.day = d
if days_hms then
-- Don't set H unless it was valid because a valid H will set hastime.
numbers.hour = H
numbers.minute = M
numbers.second = S
end
end
local function set_date_from_numbers(date, numbers, options)
-- Set the fields of table date from numeric values.
-- Return true if date is valid.
if type(numbers) ~= 'table' then
return
end
local y = numbers.year or date.year
local m = numbers.month or date.month
local d = numbers.day or date.day
local H = numbers.hour
local M = numbers.minute or date.minute or 0
local S = numbers.second or date.second or 0
local need_fix
if y and m and d then
date.partial = nil
if not (-9999 <= y and y <= 9999 and
1 <= m and m <= 12 and
1 <= d and d <= days_in_month(y, m, date.calendar)) then
if not date.want_fix then
return
end
need_fix = true
end
elseif y and date.partial then
if d or not (-9999 <= y and y <= 9999) then
return
end
if m and not (1 <= m and m <= 12) then
if not date.want_fix then
return
end
need_fix = true
end
else
return
end
if date.partial then
H = nil -- ignore any time
M = nil
S = nil
else
if H then
-- It is not possible to set M or S without also setting H.
date.hastime = true
else
H = 0
end
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
if date.want_fix then
need_fix = true
else
return
end
end
end
date.want_fix = nil
if need_fix then
fix_numbers(numbers, y, m, d, H, M, S, date.partial, date.hastime, date.calendar)
return set_date_from_numbers(date, numbers, options)
end
date.year = y -- -9999 to 9999 ('n BC' → year = 1 - n)
date.month = m -- 1 to 12 (may be nil if partial)
date.day = d -- 1 to 31 (* = nil if partial)
date.hour = H -- 0 to 59 (*)
date.minute = M -- 0 to 59 (*)
date.second = S -- 0 to 59 (*)
if type(options) == 'table' then
for _, k in ipairs({ 'am', 'era', 'format' }) do
if options[k] then
date.options[k] = options[k]
end
end
end
return true
end
local function make_option_table(options1, options2)
-- If options1 is a string, return a table with its settings, or
-- if it is a table, use its settings.
-- Missing options are set from table options2 or defaults.
-- If a default is used, a flag is set so caller knows the value was not intentionally set.
-- Valid option settings are:
-- am: 'am', 'a.m.', 'AM', 'A.M.'
-- 'pm', 'p.m.', 'PM', 'P.M.' (each has same meaning as corresponding item above)
-- era: 'BCMINUS', 'BCNEGATIVE', 'BC', 'B.C.', 'BCE', 'B.C.E.', 'AD', 'A.D.', 'CE', 'C.E.'
-- Option am = 'am' does not mean the hour is AM; it means 'am' or 'pm' is used, depending on the hour,
-- and am = 'pm' has the same meaning.
-- Similarly, era = 'BC' means 'BC' is used if year <= 0.
-- BCMINUS displays a MINUS if year < 0 and the display format does not include %{era}.
-- BCNEGATIVE is similar but displays a hyphen.
local result = { bydefault = {} }
if type(options1) == 'table' then
result.am = options1.am
result.era = options1.era
elseif type(options1) == 'string' then
-- Example: 'am:AM era:BC' or 'am=AM era=BC'.
for item in options1:gmatch('%S+') do
local lhs, rhs = item:match('^(%w+)[:=](.+)$')
if lhs then
result[lhs] = rhs
end
end
end
options2 = type(options2) == 'table' and options2 or {}
local defaults = { am = 'am', era = 'BC' }
for k, v in pairs(defaults) do
if not result[k] then
if options2[k] then
result[k] = options2[k]
else
result[k] = v
result.bydefault[k] = true
end
end
end
return result
end
local ampm_options = {
-- lhs = input text accepted as an am/pm option
-- rhs = code used internally
['am'] = 'am',
['AM'] = 'AM',
['a.m.'] = 'a.m.',
['A.M.'] = 'A.M.',
['pm'] = 'am', -- same as am
['PM'] = 'AM',
['p.m.'] = 'a.m.',
['P.M.'] = 'A.M.',
}
local era_text = {
-- Text for displaying an era with a positive year (after adjusting
-- by replacing year with 1 - year if date.year <= 0).
-- options.era = { year<=0 , year>0 }
['BCMINUS'] = { 'BC' , '' , isbc = true, sign = MINUS },
['BCNEGATIVE'] = { 'BC' , '' , isbc = true, sign = '-' },
['BC'] = { 'BC' , '' , isbc = true },
['B.C.'] = { 'B.C.' , '' , isbc = true },
['BCE'] = { 'BCE' , '' , isbc = true },
['B.C.E.'] = { 'B.C.E.', '' , isbc = true },
['AD'] = { 'BC' , 'AD' },
['A.D.'] = { 'B.C.' , 'A.D.' },
['CE'] = { 'BCE' , 'CE' },
['C.E.'] = { 'B.C.E.', 'C.E.' },
}
local function get_era_for_year(era, year)
return (era_text[era] or era_text['BC'])[year > 0 and 2 or 1] or ''
end
local function strftime(date, format, options)
-- Return date formatted as a string using codes similar to those
-- in the C strftime library function.
local sformat = string.format
local shortcuts = {
['%c'] = '%-I:%M %p %-d %B %-Y %{era}', -- date and time: 2:30 pm 1 April 2016
['%x'] = '%-d %B %-Y %{era}', -- date: 1 April 2016
['%X'] = '%-I:%M %p', -- time: 2:30 pm
}
if shortcuts[format] then
format = shortcuts[format]
end
local codes = {
a = { field = 'dayabbr' },
A = { field = 'dayname' },
b = { field = 'monthabbr' },
B = { field = 'monthname' },
u = { fmt = '%d' , field = 'dowiso' },
w = { fmt = '%d' , field = 'dow' },
d = { fmt = '%02d', fmt2 = '%d', field = 'day' },
m = { fmt = '%02d', fmt2 = '%d', field = 'month' },
Y = { fmt = '%04d', fmt2 = '%d', field = 'year' },
H = { fmt = '%02d', fmt2 = '%d', field = 'hour' },
M = { fmt = '%02d', fmt2 = '%d', field = 'minute' },
S = { fmt = '%02d', fmt2 = '%d', field = 'second' },
j = { fmt = '%03d', fmt2 = '%d', field = 'dayofyear' },
I = { fmt = '%02d', fmt2 = '%d', field = 'hour', special = 'hour12' },
p = { field = 'hour', special = 'am' },
}
options = make_option_table(options, date.options)
local amopt = options.am
local eraopt = options.era
local function replace_code(spaces, modifier, id)
local code = codes[id]
if code then
local fmt = code.fmt
if modifier == '-' and code.fmt2 then
fmt = code.fmt2
end
local value = date[code.field]
if not value then
return nil -- an undefined field in a partial date
end
local special = code.special
if special then
if special == 'hour12' then
value = value % 12
value = value == 0 and 12 or value
elseif special == 'am' then
local ap = ({
['a.m.'] = { 'a.m.', 'p.m.' },
['AM'] = { 'AM', 'PM' },
['A.M.'] = { 'A.M.', 'P.M.' },
})[ampm_options[amopt]] or { 'am', 'pm' }
return (spaces == '' and '' or ' ') .. (value < 12 and ap[1] or ap[2])
end
end
if code.field == 'year' then
local sign = (era_text[eraopt] or {}).sign
if not sign or format:find('%{era}', 1, true) then
sign = ''
if value <= 0 then
value = 1 - value
end
else
if value >= 0 then
sign = ''
else
value = -value
end
end
return spaces .. sign .. sformat(fmt, value)
end
return spaces .. (fmt and sformat(fmt, value) or value)
end
end
local function replace_property(spaces, id)
if id == 'era' then
-- Special case so can use local era option.
local result = get_era_for_year(eraopt, date.year)
if result == '' then
return ''
end
return (spaces == '' and '' or ' ') .. result
end
local result = date[id]
if type(result) == 'string' then
return spaces .. result
end
if type(result) == 'number' then
return spaces .. tostring(result)
end
if type(result) == 'boolean' then
return spaces .. (result and '1' or '0')
end
-- This occurs if id is an undefined field in a partial date, or is the name of a function.
return nil
end
local PERCENT = '\127PERCENT\127'
return (format
:gsub('%%%%', PERCENT)
:gsub('(%s*)%%{(%w+)}', replace_property)
:gsub('(%s*)%%(%-?)(%a)', replace_code)
:gsub(PERCENT, '%%')
)
end
local function _date_text(date, fmt, options)
-- Return a formatted string representing the given date.
if not is_date(date) then
error('date:text: need a date (use "date:text()" with a colon)', 2)
end
if type(fmt) == 'string' and fmt:match('%S') then
if fmt:find('%', 1, true) then
return strftime(date, fmt, options)
end
elseif date.partial then
fmt = date.month and 'my' or 'y'
else
fmt = 'dmy'
if date.hastime then
fmt = (date.second > 0 and 'hms ' or 'hm ') .. fmt
end
end
local function bad_format()
-- For consistency with other format processing, return given format
-- (or cleaned format if original was not a string) if invalid.
return mw.text.nowiki(fmt)
end
if date.partial then
-- Ignore days in standard formats like 'ymd'.
if fmt == 'ym' or fmt == 'ymd' then
fmt = date.month and '%Y-%m %{era}' or '%Y %{era}'
elseif fmt == 'my' or fmt == 'dmy' or fmt == 'mdy' then
fmt = date.month and '%B %-Y %{era}' or '%-Y %{era}'
elseif fmt == 'y' then
fmt = date.month and '%-Y %{era}' or '%-Y %{era}'
else
return bad_format()
end
return strftime(date, fmt, options)
end
local function hm_fmt()
local plain = make_option_table(options, date.options).bydefault.am
return plain and '%H:%M' or '%-I:%M %p'
end
local need_time = date.hastime
local t = collection()
for item in fmt:gmatch('%S+') do
local f
if item == 'hm' then
f = hm_fmt()
need_time = false
elseif item == 'hms' then
f = '%H:%M:%S'
need_time = false
elseif item == 'ymd' then
f = '%Y-%m-%d %{era}'
elseif item == 'mdy' then
f = '%B %-d, %-Y %{era}'
elseif item == 'dmy' then
f = '%-d %B %-Y %{era}'
else
return bad_format()
end
t:add(f)
end
fmt = t:join(' ')
if need_time then
fmt = hm_fmt() .. ' ' .. fmt
end
return strftime(date, fmt, options)
end
local day_info = {
-- 0=Sun to 6=Sat
[0] = { 'Sun', 'Sunday' },
{ 'Mon', 'Monday' },
{ 'Tue', 'Tuesday' },
{ 'Wed', 'Wednesday' },
{ 'Thu', 'Thursday' },
{ 'Fri', 'Friday' },
{ 'Sat', 'Saturday' },
}
local month_info = {
-- 1=Jan to 12=Dec
{ 'Jan', 'January' },
{ 'Feb', 'February' },
{ 'Mar', 'March' },
{ 'Apr', 'April' },
{ 'May', 'May' },
{ 'Jun', 'June' },
{ 'Jul', 'July' },
{ 'Aug', 'August' },
{ 'Sep', 'September' },
{ 'Oct', 'October' },
{ 'Nov', 'November' },
{ 'Dec', 'December' },
}
local function name_to_number(text, translate)
if type(text) == 'string' then
return translate[text:lower()]
end
end
local function day_number(text)
return name_to_number(text, {
sun = 0, sunday = 0,
mon = 1, monday = 1,
tue = 2, tuesday = 2,
wed = 3, wednesday = 3,
thu = 4, thursday = 4,
fri = 5, friday = 5,
sat = 6, saturday = 6,
})
end
local function month_number(text)
return name_to_number(text:gsub('%.', ''), {
jan = 1, january = 1,
feb = 2, february = 2,
mar = 3, march = 3,
apr = 4, april = 4,
may = 5,
jun = 6, june = 6,
jul = 7, july = 7,
aug = 8, august = 8,
sep = 9, september = 9, sept = 9,
oct = 10, october = 10,
nov = 11, november = 11,
dec = 12, december = 12,
})
end
local function _list_text(list, fmt)
-- Return a list of formatted strings from a list of dates.
if not type(list) == 'table' then
error('date:list:text: need "list:text()" with a colon', 2)
end
local result = { join = _list_join }
for i, date in ipairs(list) do
result[i] = date:text(fmt)
end
return result
end
local function _date_list(date, spec)
-- Return a possibly empty numbered table of dates meeting the specification.
-- Dates in the list are in ascending order (oldest date first).
-- The spec should be a string of form "<count> <day> <op>"
-- where each item is optional and
-- count = number of items wanted in list
-- day = abbreviation or name such as Mon or Monday
-- op = >, >=, <, <= (default is > meaning after date)
-- If no count is given, the list is for the specified days in date's month.
-- The default day is date's day.
-- The spec can also be a positive or negative number:
-- -5 is equivalent to '5 <'
-- 5 is equivalent to '5' which is '5 >'
if not is_date(date) then
error('date:list: need a date (use "date:list()" with a colon)', 2)
end
local list = { text = _list_text }
if date.partial then
return list
end
local count, offset, operation
local ops = {
['>='] = { before = false, include = true },
['>'] = { before = false, include = false },
['<='] = { before = true , include = true },
['<'] = { before = true , include = false },
}
if spec then
if type(spec) == 'number' then
count = floor(spec + 0.5)
if count < 0 then
count = -count
operation = ops['<']
end
elseif type(spec) == 'string' then
local num, day, op = spec:match('^%s*(%d*)%s*(%a*)%s*([<>=]*)%s*$')
if not num then
return list
end
if num ~= '' then
count = tonumber(num)
end
if day ~= '' then
local dow = day_number(day:gsub('[sS]$', '')) -- accept plural days
if not dow then
return list
end
offset = dow - date.dow
end
operation = ops[op]
else
return list
end
end
offset = offset or 0
operation = operation or ops['>']
local datefrom, dayfirst, daylast
if operation.before then
if offset > 0 or (offset == 0 and not operation.include) then
offset = offset - 7
end
if count then
if count > 1 then
offset = offset - 7*(count - 1)
end
datefrom = date + offset
else
daylast = date.day + offset
dayfirst = daylast % 7
if dayfirst == 0 then
dayfirst = 7
end
end
else
if offset < 0 or (offset == 0 and not operation.include) then
offset = offset + 7
end
if count then
datefrom = date + offset
else
dayfirst = date.day + offset
daylast = date.monthdays
end
end
if not count then
if daylast < dayfirst then
return list
end
count = floor((daylast - dayfirst)/7) + 1
datefrom = Date(date, {day = dayfirst})
end
for i = 1, count do
if not datefrom then break end -- exceeds date limits
list[i] = datefrom
datefrom = datefrom + 7
end
return list
end
-- Cache the current date/time (UTC).
--
-- Note that os.date() returns an empty object with optimized lazy getters for each field.
-- Avoid current.min or current.sec in articles! https://phabricator.wikimedia.org/T416616
--
-- Beware that while os.date() uses 'min' and 'sec', our Date() uses 'minute' and 'second'.
local current = os.date('!*t')
local function extract_date(newdate, text)
-- Parse the date/time in text and return n, o where
-- n = table of numbers with date/time fields
-- o = table of options for AM/PM or AD/BC or format, if any
-- or return nothing if date is known to be invalid.
-- Caller determines if the values in n are valid.
-- A year must be positive ('1' to '9999'); use 'BC' for BC.
-- In a y-m-d string, the year must be four digits to avoid ambiguity
-- ('0001' to '9999'). The only way to enter year <= 0 is by specifying
-- the date as three numeric parameters like ymd Date(-1, 1, 1).
-- Dates of form d/m/y, m/d/y, y/m/d are rejected as potentially ambiguous.
local date, options = {}, {}
if text:sub(-1) == 'Z' then
-- Extract date/time from a Wikidata timestamp.
-- The year can be 1 to 16 digits but this module handles 1 to 4 digits only.
-- Examples: '+2016-06-21T14:30:00Z', '-0000000180-00-00T00:00:00Z'.
local sign, y, m, d, H, M, S = text:match('^([+%-])(%d+)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)Z$')
if sign then
y = tonumber(y)
if sign == '-' and y > 0 then
y = -y
end
if y <= 0 then
options.era = 'BCE'
end
date.year = y
m = tonumber(m)
d = tonumber(d)
H = tonumber(H)
M = tonumber(M)
S = tonumber(S)
if m == 0 then
newdate.partial = true
return date, options
end
date.month = m
if d == 0 then
newdate.partial = true
return date, options
end
date.day = d
if H > 0 or M > 0 or S > 0 then
date.hour = H
date.minute = M
date.second = S
end
return date, options
end
return
end
local function extract_ymd(item)
-- Called when no day or month has been set.
local y, m, d = item:match('^(%d%d%d%d)%-(%w+)%-(%d%d?)$')
if y then
if date.year then
return
end
if m:match('^%d%d?$') then
m = tonumber(m)
else
m = month_number(m)
end
if m then
date.year = tonumber(y)
date.month = m
date.day = tonumber(d)
return true
end
end
end
local function extract_day_or_year(item)
-- Called when a day would be valid, or
-- when a year would be valid if no year has been set and partial is set.
local number, suffix = item:match('^(%d%d?%d?%d?)(.*)$')
if number then
local n = tonumber(number)
if #number <= 2 and n <= 31 then
suffix = suffix:lower()
if suffix == '' or suffix == 'st' or suffix == 'nd' or suffix == 'rd' or suffix == 'th' then
date.day = n
return true
end
elseif suffix == '' and newdate.partial and not date.year then
date.year = n
return true
end
end
end
local function extract_month(item)
-- A month must be given as a name or abbreviation; a number could be ambiguous.
local m = month_number(item)
if m then
date.month = m
return true
end
end
local function extract_time(item)
local h, m, s = item:match('^(%d%d?):(%d%d)(:?%d*)$')
if date.hour or not h then
return
end
if s ~= '' then
s = s:match('^:(%d%d)$')
if not s then
return
end
end
date.hour = tonumber(h)
date.minute = tonumber(m)
date.second = tonumber(s) -- nil if empty string
return true
end
local item_count = 0
local index_time
local function set_ampm(item)
local H = date.hour
if H and not options.am and index_time + 1 == item_count then
options.am = ampm_options[item] -- caller checked this is not nil
if item:match('^[Aa]') then
if not (1 <= H and H <= 12) then
return
end
if H == 12 then
date.hour = 0
end
else
if not (1 <= H and H <= 23) then
return
end
if H <= 11 then
date.hour = H + 12
end
end
return true
end
end
for item in text:gsub(',', ' '):gsub(' ', ' '):gmatch('%S+') do
item_count = item_count + 1
if era_text[item] then
-- Era is accepted in peculiar places.
if options.era then
return
end
options.era = item
elseif ampm_options[item] then
if not set_ampm(item) then
return
end
elseif item:find(':', 1, true) then
if not extract_time(item) then
return
end
index_time = item_count
elseif date.day and date.month then
if date.year then
return -- should be nothing more so item is invalid
end
if not item:match('^(%d%d?%d?%d?)$') then
return
end
date.year = tonumber(item)
elseif date.day then
if not extract_month(item) then
return
end
elseif date.month then
if not extract_day_or_year(item) then
return
end
elseif extract_month(item) then
options.format = 'mdy'
elseif extract_ymd(item) then
options.format = 'ymd'
elseif extract_day_or_year(item) then
if date.day then
options.format = 'dmy'
end
else
return
end
end
if not date.year or date.year == 0 then
return
end
local era = era_text[options.era]
if era and era.isbc then
date.year = 1 - date.year
end
return date, options
end
local function autofill(date1, date2)
-- Fill any missing month or day in each date using the
-- corresponding component from the other date, if present,
-- or with 1 if both dates are missing the month or day.
-- This gives a good result for calculating the difference
-- between two partial dates when no range is wanted.
-- Return filled date1, date2 (two full dates).
local function filled(a, b)
-- Return date a filled, if necessary, with month and/or day from date b.
-- The filled day is truncated to fit the number of days in the month.
local fillmonth, fillday
if not a.month then
fillmonth = b.month or 1
end
if not a.day then
fillday = b.day or 1
end
if fillmonth or fillday then -- need to create a new date
a = Date(a, {
month = fillmonth,
day = math.min(fillday or a.day, days_in_month(a.year, fillmonth or a.month, a.calendar))
})
end
return a
end
return filled(date1, date2), filled(date2, date1)
end
local function date_add_sub(lhs, rhs, is_sub)
-- Return a new date from calculating (lhs + rhs) or (lhs - rhs),
-- or return nothing if invalid.
-- The result is nil if the calculated date exceeds allowable limits.
-- Caller ensures that lhs is a date; its properties are copied for the new date.
if lhs.partial then
-- Adding to a partial is not supported.
-- Can subtract a date or partial from a partial, but this is not called for that.
return
end
local function is_prefix(text, word, minlen)
local n = #text
return (minlen or 1) <= n and n <= #word and text == word:sub(1, n)
end
local function do_days(n)
local forcetime, jd
if floor(n) == n then
jd = lhs.jd
else
forcetime = not lhs.hastime
jd = lhs.jdz
end
jd = jd + (is_sub and -n or n)
if forcetime then
jd = tostring(jd)
if not jd:find('.', 1, true) then
jd = jd .. '.0'
end
end
return Date(lhs, 'juliandate', jd)
end
if type(rhs) == 'number' then
-- Add/subtract days, including fractional days.
return do_days(rhs)
end
if type(rhs) == 'string' then
-- rhs is a single component like '26m' or '26 months' (with optional sign).
-- Fractions like '3.25d' are accepted for the units which are handled as days.
local sign, numstr, id = rhs:match('^%s*([+-]?)([%d%.]+)%s*(%a+)$')
if sign then
if sign == '-' then
is_sub = not (is_sub and true or false)
end
local y, m, days
local num = tonumber(numstr)
if not num then
return
end
id = id:lower()
if is_prefix(id, 'years') then
y = num
m = 0
elseif is_prefix(id, 'months') then
y = floor(num / 12)
m = num % 12
elseif is_prefix(id, 'weeks') then
days = num * 7
elseif is_prefix(id, 'days') then
days = num
elseif is_prefix(id, 'hours') then
days = num / 24
elseif is_prefix(id, 'minutes', 3) then
days = num / (24 * 60)
elseif is_prefix(id, 'seconds') then
days = num / (24 * 3600)
else
return
end
if days then
return do_days(days)
end
if numstr:find('.', 1, true) then
return
end
if is_sub then
y = -y
m = -m
end
assert(-11 <= m and m <= 11)
y = lhs.year + y
m = lhs.month + m
if m > 12 then
y = y + 1
m = m - 12
elseif m < 1 then
y = y - 1
m = m + 12
end
local d = math.min(lhs.day, days_in_month(y, m, lhs.calendar))
return Date(lhs, y, m, d)
end
end
if is_diff(rhs) then
local days = rhs.age_days
if (is_sub or false) ~= (rhs.isnegative or false) then
days = -days
end
return lhs + days
end
end
local full_date_only = {
dayabbr = true,
dayname = true,
dow = true,
dayofweek = true,
dowiso = true,
dayofweekiso = true,
dayofyear = true,
gsd = true,
juliandate = true,
jd = true,
jdz = true,
jdnoon = true,
}
-- Metatable for a date's calculated fields.
local datemt = {
__index = function (self, key)
if rawget(self, 'partial') then
if full_date_only[key] then return end
if key == 'monthabbr' or key == 'monthdays' or key == 'monthname' then
if not self.month then return end
end
end
local value
if key == 'dayabbr' then
value = day_info[self.dow][1]
elseif key == 'dayname' then
value = day_info[self.dow][2]
elseif key == 'dow' then
value = (self.jdnoon + 1) % 7 -- day-of-week 0=Sun to 6=Sat
elseif key == 'dayofweek' then
value = self.dow
elseif key == 'dowiso' then
value = (self.jdnoon % 7) + 1 -- ISO day-of-week 1=Mon to 7=Sun
elseif key == 'dayofweekiso' then
value = self.dowiso
elseif key == 'dayofyear' then
local first = Date(self.year, 1, 1, self.calendar).jdnoon
value = self.jdnoon - first + 1 -- day-of-year 1 to 366
elseif key == 'era' then
-- Era text (never a negative sign) from year and options.
value = get_era_for_year(self.options.era, self.year)
elseif key == 'format' then
value = self.options.format or 'dmy'
elseif key == 'gsd' then
-- GSD = 1 from 00:00:00 to 23:59:59 on 1 January 1 AD Gregorian calendar,
-- which is from jd 1721425.5 to 1721426.49999.
value = floor(self.jd - 1721424.5)
elseif key == 'juliandate' or key == 'jd' or key == 'jdz' then
local jd, jdz = julian_date(self)
rawset(self, 'juliandate', jd)
rawset(self, 'jd', jd)
rawset(self, 'jdz', jdz)
return key == 'jdz' and jdz or jd
elseif key == 'jdnoon' then
-- Julian date at noon (an integer) on the calendar day when jd occurs.
value = floor(self.jd + 0.5)
elseif key == 'isleapyear' then
value = is_leap_year(self.year, self.calendar)
elseif key == 'monthabbr' then
value = month_info[self.month][1]
elseif key == 'monthdays' then
value = days_in_month(self.year, self.month, self.calendar)
elseif key == 'monthname' then
value = month_info[self.month][2]
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
-- Date operators.
local function mt_date_add(lhs, rhs)
if not is_date(lhs) then
lhs, rhs = rhs, lhs -- put date on left (it must be a date for this to have been called)
end
return date_add_sub(lhs, rhs)
end
local function mt_date_sub(lhs, rhs)
if is_date(lhs) then
if is_date(rhs) then
return DateDiff(lhs, rhs)
end
return date_add_sub(lhs, rhs, true)
end
end
local function mt_date_concat(lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end
local function mt_date_tostring(self)
return self:text()
end
local function mt_date_eq(lhs, rhs)
-- Return true if dates identify same date/time where, for example,
-- Date(-4712, 1, 1, 'Julian') == Date(-4713, 11, 24, 'Gregorian') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
-- The months may both be nil, but must be the same.
return lhs.year == rhs.year and lhs.month == rhs.month and lhs.calendar == rhs.calendar
end
return lhs.jdz == rhs.jdz
end
local function mt_date_lt(lhs, rhs)
-- Return true if lhs < rhs, for example,
-- Date('1 Jan 2016') < Date('06:00 1 Jan 2016') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
if lhs.calendar ~= rhs.calendar then
return lhs.calendar == 'Julian'
end
if lhs.partial then
lhs = lhs.partial.first
end
if rhs.partial then
rhs = rhs.partial.first
end
end
return lhs.jdz < rhs.jdz
end
--[[ Examples of syntax to construct a date:
Date(y, m, d, 'julian') default calendar is 'gregorian'
Date(y, m, d, H, M, S, 'julian')
Date('juliandate', jd, 'julian') if jd contains "." text output includes H:M:S
Date('currentdate')
Date('currentdatetime')
Date('1 April 1995', 'julian') parse date from text
Date('1 April 1995 AD', 'julian') using an era sets a flag to do the same for output
Date('04:30:59 1 April 1995', 'julian')
Date(date) copy of an existing date
Date(date, t) same, updated with y,m,d,H,M,S fields from table t
Date(t) date with y,m,d,H,M,S fields from table t
]]
function Date(...) -- for forward declaration above
-- Return a table holding a date assuming a uniform calendar always applies
-- (proleptic Gregorian calendar or proleptic Julian calendar), or
-- return nothing if date is invalid.
-- A partial date has a valid year, however its month may be nil, and
-- its day and time fields are nil.
-- Field partial is set to false (if a full date) or a table (if a partial date).
local calendars = { julian = 'Julian', gregorian = 'Gregorian' }
local newdate = {
_id = uniq,
calendar = 'Gregorian', -- default is Gregorian calendar
hastime = false, -- true if input sets a time
hour = 0, -- always set hour/minute/second so don't have to handle nil
minute = 0,
second = 0,
options = {},
list = _date_list,
subtract = function (self, rhs, options)
return DateDiff(self, rhs, options)
end,
text = _date_text,
}
local argtype, datetext, is_copy, jd_number, tnums
local numindex = 0
local numfields = { 'year', 'month', 'day', 'hour', 'minute', 'second' }
local numbers = {}
for _, v in ipairs({...}) do
v = strip_to_nil(v)
local vlower = type(v) == 'string' and v:lower() or nil
if v == nil then
-- Ignore empty arguments after stripping so modules can directly pass template parameters.
elseif calendars[vlower] then
newdate.calendar = calendars[vlower]
elseif vlower == 'partial' then
newdate.partial = true
elseif vlower == 'fix' then
newdate.want_fix = true
elseif is_date(v) then
-- Copy existing date (items can be overridden by other arguments).
if is_copy or tnums then
return
end
is_copy = true
newdate.calendar = v.calendar
newdate.partial = v.partial
newdate.hastime = v.hastime
newdate.options = v.options
newdate.year = v.year
newdate.month = v.month
newdate.day = v.day
newdate.hour = v.hour
newdate.minute = v.minute
newdate.second = v.second
elseif type(v) == 'table' then
if tnums then
return
end
tnums = {}
local tfields = { year=1, month=1, day=1, hour=2, minute=2, second=2 }
for tk, tv in pairs(v) do
if tfields[tk] then
tnums[tk] = tonumber(tv)
end
if tfields[tk] == 2 then
newdate.hastime = true
end
end
else
local num = tonumber(v)
if not num and argtype == 'setdate' and numindex == 1 then
num = month_number(v)
end
if num then
if not argtype then
argtype = 'setdate'
end
if argtype == 'setdate' and numindex < 6 then
numindex = numindex + 1
numbers[numfields[numindex]] = num
elseif argtype == 'juliandate' and not jd_number then
jd_number = num
if type(v) == 'string' then
if v:find('.', 1, true) then
newdate.hastime = true
end
elseif num ~= floor(num) then
-- The given value was a number. The time will be used
-- if the fractional part is nonzero.
newdate.hastime = true
end
else
return
end
elseif argtype then
return
elseif type(v) == 'string' then
if v == 'currentdate' or v == 'currentdatetime' or v == 'juliandate' then
argtype = v
else
argtype = 'datetext'
datetext = v
end
else
return
end
end
end
if argtype == 'datetext' then
if tnums or not set_date_from_numbers(newdate, extract_date(newdate, datetext)) then
return
end
elseif argtype == 'juliandate' then
newdate.partial = nil
newdate.jd = jd_number
if not set_date_from_jd(newdate) then
return
end
elseif argtype == 'currentdate' or argtype == 'currentdatetime' then
newdate.partial = nil
newdate.year = current.year
newdate.month = current.month
newdate.day = current.day
if argtype == 'currentdatetime' then
newdate.hour = current.hour
newdate.minute = current.min
newdate.second = current.sec
newdate.hastime = true
end
newdate.calendar = 'Gregorian' -- ignore any given calendar name
elseif argtype == 'setdate' then
if tnums or not set_date_from_numbers(newdate, numbers) then
return
end
elseif not (is_copy or tnums) then
return
end
if tnums then
newdate.jd = nil -- force recalculation in case jd was set before changes from tnums
if not set_date_from_numbers(newdate, tnums) then
return
end
end
if newdate.partial then
local year = newdate.year
local month = newdate.month
local first = Date(year, month or 1, 1, newdate.calendar)
month = month or 12
local last = Date(year, month, days_in_month(year, month), newdate.calendar)
newdate.partial = { first = first, last = last }
else
newdate.partial = false -- avoid index lookup
end
setmetatable(newdate, datemt)
local readonly = {}
local mt = {
__index = newdate,
__newindex = function(t, k, v) error('date.' .. tostring(k) .. ' is read-only', 2) end,
__add = mt_date_add,
__sub = mt_date_sub,
__concat = mt_date_concat,
__tostring = mt_date_tostring,
__eq = mt_date_eq,
__lt = mt_date_lt,
}
return setmetatable(readonly, mt)
end
local function _diff_age(diff, code, options)
-- Return a tuple of integer values from diff as specified by code, except that
-- each integer may be a list of two integers for a diff with a partial date, or
-- return nil if the code is not supported.
-- If want round, the least significant unit is rounded to nearest whole unit.
-- For a duration, an extra day is added.
local wantround, wantduration, wantrange
if type(options) == 'table' then
wantround = options.round
wantduration = options.duration
wantrange = options.range
else
wantround = options
end
if not is_diff(diff) then
local f = wantduration and 'duration' or 'age'
error(f .. ': need a date difference (use "diff:' .. f .. '()" with a colon)', 2)
end
if diff.partial then
-- Ignore wantround, wantduration.
local function choose(v)
if type(v) == 'table' then
if not wantrange or v[1] == v[2] then
-- Example: Date('partial', 2005) - Date('partial', 2001) gives
-- diff.years = { 3, 4 } to show the range of possible results.
-- If do not want a range, choose the second value as more expected.
return v[2]
end
end
return v
end
if code == 'ym' or code == 'ymd' then
if not wantrange and diff.iszero then
-- This avoids an unexpected result such as
-- Date('partial', 2001) - Date('partial', 2001)
-- giving diff = { years = 0, months = { 0, 11 } }
-- which would be reported as 0 years and 11 months.
return 0, 0
end
return choose(diff.partial.years), choose(diff.partial.months)
end
if code == 'y' then
return choose(diff.partial.years)
end
if code == 'm' or code == 'w' or code == 'd' then
return choose({ diff.partial.mindiff:age(code), diff.partial.maxdiff:age(code) })
end
return nil
end
local extra_days = wantduration and 1 or 0
if code == 'wd' or code == 'w' or code == 'd' then
local offset = wantround and 0.5 or 0
local days = diff.age_days + extra_days
if code == 'wd' or code == 'd' then
days = floor(days + offset)
if code == 'd' then
return days
end
return floor(days/7), days % 7
end
return floor(days/7 + offset)
end
local H, M, S = diff.hours, diff.minutes, diff.seconds
if code == 'dh' or code == 'dhm' or code == 'dhms' or code == 'h' or code == 'hm' or code == 'hms' or code == 'M' or code == 's' then
local days = floor(diff.age_days + extra_days)
local inc_hour
if wantround then
if code == 'dh' or code == 'h' then
if M >= 30 then
inc_hour = true
end
elseif code == 'dhm' or code == 'hm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
elseif code == 'M' then
if S >= 30 then
M = M + 1
end
else
-- Nothing needed because S is an integer.
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
days = days + 1
end
end
end
if code == 'dh' or code == 'dhm' or code == 'dhms' then
if code == 'dh' then
return days, H
elseif code == 'dhm' then
return days, H, M
else
return days, H, M, S
end
end
local hours = days * 24 + H
if code == 'h' then
return hours
elseif code == 'hm' then
return hours, M
elseif code == 'M' or code == 's' then
M = hours * 60 + M
if code == 'M' then
return M
end
return M * 60 + S
end
return hours, M, S
end
if wantround then
local inc_hour
if code == 'ymdh' or code == 'ymwdh' then
if M >= 30 then
inc_hour = true
end
elseif code == 'ymdhm' or code == 'ymwdhm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
elseif code == 'ymd' or code == 'ymwd' or code == 'yd' or code == 'md' then
if H >= 12 then
extra_days = extra_days + 1
end
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
extra_days = extra_days + 1
end
end
end
local y, m, d = diff.years, diff.months, diff.days
if extra_days > 0 then
d = d + extra_days
if d > 28 or code == 'yd' then
-- Recalculate in case have passed a month.
diff = diff.date1 + extra_days - diff.date2
y, m, d = diff.years, diff.months, diff.days
end
end
if code == 'ymd' then
return y, m, d
elseif code == 'yd' then
if y > 0 then
-- It is known that diff.date1 > diff.date2.
diff = diff.date1 - (diff.date2 + (y .. 'y'))
end
return y, floor(diff.age_days)
elseif code == 'md' then
return y * 12 + m, d
elseif code == 'ym' or code == 'm' then
if wantround then
if d >= 16 then
m = m + 1
if m >= 12 then
m = 0
y = y + 1
end
end
end
if code == 'ym' then
return y, m
end
return y * 12 + m
elseif code == 'ymw' then
local weeks = floor(d/7)
if wantround then
local days = d % 7
if days > 3 or (days == 3 and H >= 12) then
weeks = weeks + 1
end
end
return y, m, weeks
elseif code == 'ymwd' then
return y, m, floor(d/7), d % 7
elseif code == 'ymdh' then
return y, m, d, H
elseif code == 'ymwdh' then
return y, m, floor(d/7), d % 7, H
elseif code == 'ymdhm' then
return y, m, d, H, M
elseif code == 'ymwdhm' then
return y, m, floor(d/7), d % 7, H, M
end
if code == 'y' then
if wantround and m >= 6 then
y = y + 1
end
return y
end
return nil
end
local function _diff_duration(diff, code, options)
if type(options) ~= 'table' then
options = { round = options }
end
options.duration = true
return _diff_age(diff, code, options)
end
-- Metatable for some operations on date differences.
diffmt = { -- for forward declaration above
__concat = function (lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end,
__tostring = function (self)
return tostring(self.age_days)
end,
__index = function (self, key)
local value
if key == 'age_days' then
if rawget(self, 'partial') then
local function jdz(date)
return (date.partial and date.partial.first or date).jdz
end
value = jdz(self.date1) - jdz(self.date2)
else
value = self.date1.jdz - self.date2.jdz
end
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
function DateDiff(date1, date2, options) -- for forward declaration above
-- Return a table with the difference between two dates (date1 - date2).
-- The difference is negative if date1 is older than date2.
-- Return nothing if invalid.
-- If d = date1 - date2 then
-- date1 = date2 + d
-- If date1 >= date2 and the dates have no H:M:S time specified then
-- date1 = date2 + (d.years..'y') + (d.months..'m') + d.days
-- where the larger time units are added first.
-- The result of Date(2015,1,x) + '1m' is Date(2015,2,28) for
-- x = 28, 29, 30, 31. That means, for example,
-- d = Date(2015,3,3) - Date(2015,1,31)
-- gives d.years, d.months, d.days = 0, 1, 3 (excluding date1).
if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then
return
end
local wantfill
if type(options) == 'table' then
wantfill = options.fill
end
local isnegative = false
local iszero = false
if date1 < date2 then
isnegative = true
date1, date2 = date2, date1
elseif date1 == date2 then
iszero = true
end
-- It is known that date1 >= date2 (period is from date2 to date1).
if date1.partial or date2.partial then
-- Two partial dates might have timelines:
---------------------A=================B--- date1 is from A to B inclusive
--------C=======D-------------------------- date2 is from C to D inclusive
-- date1 > date2 iff A > C (date1.partial.first > date2.partial.first)
-- The periods can overlap ('April 2001' - '2001'):
-------------A===B------------------------- A=2001-04-01 B=2001-04-30
--------C=====================D------------ C=2001-01-01 D=2001-12-31
if wantfill then
date1, date2 = autofill(date1, date2)
else
local function zdiff(date1, date2)
local diff = date1 - date2
if diff.isnegative then
return date1 - date1 -- a valid diff in case we call its methods
end
return diff
end
local function getdate(date, which)
return date.partial and date.partial[which] or date
end
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
local years, months
if maxdiff.years == mindiff.years then
years = maxdiff.years
if maxdiff.months == mindiff.months then
months = maxdiff.months
else
months = { mindiff.months, maxdiff.months }
end
else
years = { mindiff.years, maxdiff.years }
end
return setmetatable({
date1 = date1,
date2 = date2,
partial = {
years = years,
months = months,
maxdiff = maxdiff,
mindiff = mindiff,
},
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
end
local y1, m1 = date1.year, date1.month
local y2, m2 = date2.year, date2.month
local years = y1 - y2
local months = m1 - m2
local d1 = date1.day + hms(date1)
local d2 = date2.day + hms(date2)
local days, time
if d1 >= d2 then
days = d1 - d2
else
months = months - 1
-- Get days in previous month (before the "to" date) given December has 31 days.
local dpm = m1 > 1 and days_in_month(y1, m1 - 1, date1.calendar) or 31
if d2 >= dpm then
days = d1 - hms(date2)
else
days = dpm - d2 + d1
end
end
if months < 0 then
years = years - 1
months = months + 12
end
days, time = math.modf(days)
local H, M, S = h_m_s(time)
return setmetatable({
date1 = date1,
date2 = date2,
partial = false, -- avoid index lookup
years = years,
months = months,
days = days,
hours = H,
minutes = M,
seconds = S,
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
return {
_current = current,
_Date = Date,
_days_in_month = days_in_month,
}
p4lffcwq8w4s1hro04tf52ddm3itw32
Module:Documentation
828
232
9142
8881
2026-08-22T14:47:02Z
RAPTOR7762
18
Protected "[[Module:Documentation]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
1035
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
local format = mw.ustring.format
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
return ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
end
p.message = message
local function makeWikilink(page, display)
if display then
return format('[[%s|%s]]', page, display)
else
return format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
-- 'documentation-toolbar'
return format(
'<span class="%s">(%s)</span>',
message('toolbar-class'),
table.concat(ret, ' | ')
)
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
:tag('div')
-- 'documentation-container'
:addClass(message('container'))
:attr('role', 'complementary')
:attr('aria-labelledby', args.heading ~= '' and 'documentation-heading' or nil)
:attr('aria-label', args.heading == '' and 'Documentation' or nil)
:newline()
:tag('div')
-- 'documentation'
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
-- 'documentation-clear'
:addClass(message('clear'))
:done()
:newline()
:done()
:wikitext(p._endBox(args, env))
:done()
:wikitext(p.addTrackingCategories(env))
-- 'Module:Documentation/styles.css'
return mw.getCurrentFrame():extensionTag (
'templatestyles', '', {src=cfg['templatestyles']
}) .. tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title
-- objects and other namespace- or path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') or (subpage == message('doc-subpage') and mw.title.getCurrentTitle().namespace == env.docSpace) then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the
-- same as the subject namespace. However, pages in the Article, File,
-- MediaWiki or Category namespaces must have their /doc, /sandbox and
-- /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Inmusamman:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.canonicalUrl(
'Special:ComparePages',
{ page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Fayil:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[Wikipedia:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[Wikipedia:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
-- 'module-sandbox-category' --> 'Module sandboxes'
-- 'other-sandbox-category' --> 'Sandboxes outside of template or module namespace'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle
and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Tempilet:Foo]] (diff)."
local text = '__EXPECTUNUSEDTEMPLATE__'
local pagetype, sandboxCat
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
sandboxCat = message('sandbox-category')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
sandboxCat = message('module-sandbox-category')
else
pagetype = message('sandbox-notice-pagetype-other')
sandboxCat = message('other-sandbox-category')
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Tempilet:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.contentModel == "Scribunto" then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br />' .. message('sandbox-notice-testcases-run-blurb', {testcasesLink, testcasesRunLink})
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br />' .. message('sandbox-notice-testcases-blurb', {testcasesLink})
end
end
-- Add the sandbox to the sandbox category.
omargs.text = text .. makeCategoryLink(sandboxCat)
-- 'documentation-clear'
return '<div class="' .. message('clear') .. '"></div>'
.. require('Module:Message box').main('ombox', omargs)
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
return require('Module:Protection banner')._main{
message('protection-reason-edit'), small = true
}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
return require('Module:Protection banner')._main{
action = 'move', small = true
}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content or args[1] then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
if docTitle.isRedirect then
docTitle = docTitle.redirectTarget
end
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
return {
title = title,
docTitle = docTitle,
-- View, display, edit, and purge links if /doc exists.
viewLinkDisplay = message('view-link-display'),
editLinkDisplay = message('edit-link-display'),
historyLinkDisplay = message('history-link-display'),
purgeLinkDisplay = message('purge-link-display'),
preload = preload,
createLinkDisplay = message('create-link-display')
}
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create][purge] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local docTitle = data.docTitle
-- yes, we do intend to purge the template page on which the documentation appears
local purgeLink = makeWikilink("Special:Purge/" .. data.title.prefixedText, data.purgeLinkDisplay)
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, data.editLinkDisplay)
local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, data.historyLinkDisplay)
return "[" .. viewLink .. "] [" .. editLink .. "] [" .. historyLink .. "] [" .. purgeLink .. "]"
else
local createLink = makeUrlLink(docTitle:canonicalUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
return "[" .. createLink .. "] [" .. purgeLink .. "]"
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[Fayil:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
else
-- 'documentation-heading'
data.headingClass = message('main-div-heading-class')
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
-- 'mw-editsection-like plainlinks'
data.linksClass = message('start-box-link-classes')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
-- 'documentation-startbox'
:addClass(message('start-box-class'))
:newline()
:tag('span')
:addClass(data.headingClass)
:attr('id', 'documentation-heading')
:cssText(data.headingStyleText)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the link box.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '') .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
end
end
local box = mw.html.create('div')
-- 'documentation-metadata'
box:attr('role', 'note')
:addClass(message('end-box-class'))
-- 'plainlinks'
:addClass(message('end-box-plainlinks'))
:wikitext(text)
:done()
return '\n' .. tostring(box)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Tempilet:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[Wikipedia:Template documentation|documentation]]
-- is [[Taimako:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editDisplay = message('edit-link-display')
local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, editDisplay)
local historyDisplay = message('history-link-display')
local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, historyDisplay)
return message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:canonicalUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
return message('create-module-doc-blurb', {createLink})
.. '<br />'
end
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeWikilink("Special:EditPage/" .. sandboxPage, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:canonicalUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:canonicalUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeWikilink("Special:EditPage/" .. testcasesPage, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if testcasesTitle.contentModel == "Scribunto" and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:canonicalUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
return makeCategoryLink(message('strange-usage-category'))
end
return ''
end
return p
fwf1l6mawlsx2fol0yhf2qbb0idq8m1
Module:Documentation/config
828
233
9159
8883
2026-08-23T01:00:39Z
RAPTOR7762
18
Protected "[[Module:Documentation/config]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
1040
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Fayil:Edit In Sandbox Icon - Color.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[Wikipidiya:Template test cases|template sandbox]] page'
cfg['sandbox-notice-pagetype-module'] = '[[Wikipidiya:Template test cases|module sandbox]] page'
cfg['sandbox-notice-pagetype-other'] = 'sandbox page'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = 'This is the $1 for $2.'
cfg['sandbox-notice-diff-blurb'] = 'This is the $1 for $2 ($3).'
cfg['sandbox-notice-compare-link-display'] = 'diff'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = 'See also the companion subpage for $1.'
cfg['sandbox-notice-testcases-link-display'] = 'test cases'
cfg['sandbox-notice-testcases-run-blurb'] = 'See also the companion subpage for $1 ($2).'
cfg['sandbox-notice-testcases-run-link-display'] = 'run'
-- cfg['sandbox-category'] - A category to add to all template sandboxes.
-- cfg['module-sandbox-category'] - A category to add to all module sandboxes.
-- cfg['module-sandbox-category'] - A category to add to all sandboxe not in templates or modules.
cfg['sandbox-category'] = 'Template sandboxes'
cfg['module-sandbox-category'] = 'Module sandboxes'
cfg['other-sandbox-category'] = 'Sandboxes outside of template or module namespace'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[Fayil:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = 'Template documentation'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = 'Module documentation'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = 'Documentation'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = 'view'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = 'edit'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = 'history'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = 'purge'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = 'create'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = 'The above [[Wikipedia:Template documentation|documentation]] is [[Taimako:Transclusion|transcluded]] from $1.'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'] (cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'] (cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'] (cfg['testcases-edit-link-display'] | cfg['testcases-run-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'] (cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "Editors can experiment in this template's $1 and $2 pages."
cfg['experiment-blurb-module'] = "Editors can experiment in this module's $1 and $2 pages."
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = 'sandbox'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = 'edit'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = 'create'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = 'diff'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = 'Create sandbox version of $1'
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = 'mirror'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = 'testcases'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = 'edit'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = 'run'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = 'create'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = 'Add categories to the $1 subpage.'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1.'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = 'Subpages of this $1'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = 'template'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = 'module'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = 'page'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['templatestyles']
-- The name of the TemplateStyles page where CSS is kept.
-- Sandbox CSS will be at Module:Documentation/sandbox/styles.css when needed.
cfg['templatestyles'] = 'Module:Documentation/styles.css'
-- cfg['container']
-- Class which can be used to set flex or grid CSS on the
-- two child divs documentation and documentation-metadata
cfg['container'] = 'documentation-container'
-- cfg['main-div-classes']
-- Classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'documentation'
-- cfg['main-div-heading-class']
-- Class for the main heading for templates and modules and assoc. talk spaces
cfg['main-div-heading-class'] = 'documentation-heading'
-- cfg['start-box-class']
-- Class for the start box
cfg['start-box-class'] = 'documentation-startbox'
-- cfg['start-box-link-classes']
-- Classes used for the [view][edit][history] or [create] links in the start box.
-- mw-editsection-like is per [[Wikipedia:Village pump (technical)/Archive 117]]
cfg['start-box-link-classes'] = 'mw-editsection-like plainlinks'
-- cfg['end-box-class']
-- Class for the end box.
cfg['end-box-class'] = 'documentation-metadata'
-- cfg['end-box-plainlinks']
-- Plainlinks
cfg['end-box-plainlinks'] = 'plainlinks'
-- cfg['toolbar-class']
-- Class added for toolbar links.
cfg['toolbar-class'] = 'documentation-toolbar'
-- cfg['clear']
-- Just used to clear things.
cfg['clear'] = 'documentation-clear'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
dkotj9f6tcgmf81gx6xweofvl1ravm5
Module:TableTools
828
272
9530
8837
2026-08-23T10:41:57Z
RAPTOR7762
18
Protected "[[Module:TableTools]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
1149
Scribunto
text/plain
------------------------------------------------------------------------------------
-- 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. --
------------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local p = {}
-- Define often-used variables and functions.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
function p.isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity
end
------------------------------------------------------------------------------------
-- isNan
--
-- This function returns true if the given number is a NaN value, and false if
-- not. Although it doesn't operate on tables, it is included here as it is useful
-- for determining whether a value can be a valid table key. Lua will generate an
-- error if a NaN is used as a table key.
------------------------------------------------------------------------------------
function p.isNan(v)
return type(v) == 'number' and v ~= v
end
------------------------------------------------------------------------------------
-- shallowClone
--
-- This returns a clone of a table. The value returned is a new table, but all
-- subtables and functions are shared. Metamethods are respected, but the returned
-- table will have no metatable of its own.
------------------------------------------------------------------------------------
function p.shallowClone(t)
checkType('shallowClone', 1, t, 'table')
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- This removes duplicate values from an array. Non-positive-integer keys are
-- ignored. The earliest value is kept, and all subsequent duplicate values are
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
function p.removeDuplicates(arr)
checkType('removeDuplicates', 1, arr, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for _, v in ipairs(arr) do
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
elseif not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
return ret
end
------------------------------------------------------------------------------------
-- numKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in numerical order.
------------------------------------------------------------------------------------
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- affixNums
--
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return
-- {1, 3, 6}.
------------------------------------------------------------------------------------
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- numData
--
-- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table
-- of subtables in the format
-- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}.
-- Keys that don't end with an integer are stored in a subtable named "other". The
-- compress option compresses the table so that it can be iterated over with
-- ipairs.
------------------------------------------------------------------------------------
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Positional parameters match the blank string; put them at the start of the subtable instead.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- This takes an array with one or more nil values, and removes the nil values
-- while preserving the order, so that the array can be safely traversed with
-- ipairs.
------------------------------------------------------------------------------------
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- This is an iterator for sparse arrays. It can be used like ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- size
--
-- This returns the size of a key/value pair table. It will also work on arrays,
-- but for arrays it is more efficient to use the # operator.
------------------------------------------------------------------------------------
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for _ in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then
return tostring(item1) < tostring(item2)
else
return item1 < item2
end
end
------------------------------------------------------------------------------------
-- keysToList
--
-- Returns an array of the keys in a table, sorted using either a default
-- comparison function or a custom keySort function.
------------------------------------------------------------------------------------
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'})
end
local arr = {}
local index = 1
for k in pairs(t) do
arr[index] = k
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(arr, keySort)
end
return arr
end
------------------------------------------------------------------------------------
-- sortedPairs
--
-- Iterates through a table, with the keys sorted using the keysToList function.
-- If there are only numerical keys, sparseIpairs is probably more efficient.
------------------------------------------------------------------------------------
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local arr = p.keysToList(t, keySort, true)
local i = 0
return function ()
i = i + 1
local key = arr[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- isArray
--
-- Returns true if the given value is a table and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArray(v)
if type(v) ~= 'table' then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- isArrayLike
--
-- Returns true if the given value is iterable and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArrayLike(v)
if not pcall(pairs, v) then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- invert
--
-- Transposes the keys and values in an array. For example, {"a", "b", "c"} ->
-- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to
-- the index of the last duplicate) and NaN values are ignored.
------------------------------------------------------------------------------------
function p.invert(arr)
checkType("invert", 1, arr, "table")
local isNan = p.isNan
local map = {}
for i, v in ipairs(arr) do
if not isNan(v) then
map[v] = i
end
end
return map
end
------------------------------------------------------------------------------------
-- listToSet
--
-- Creates a set from the array part of the table. Indexing the set by any of the
-- values of the array returns true. For example, {"a", "b", "c"} ->
-- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them
-- never equal to any value (including other NaNs or even themselves).
------------------------------------------------------------------------------------
function p.listToSet(arr)
checkType("listToSet", 1, arr, "table")
local isNan = p.isNan
local set = {}
for _, v in ipairs(arr) do
if not isNan(v) then
set[v] = true
end
end
return set
end
------------------------------------------------------------------------------------
-- deepCopy
--
-- Recursive deep copy function. Preserves identities of subtables.
------------------------------------------------------------------------------------
local function _deepCopy(orig, includeMetatable, already_seen)
if type(orig) ~= "table" then
return orig
end
-- already_seen stores copies of tables indexed by the original table.
local copy = already_seen[orig]
if copy ~= nil then
return copy
end
copy = {}
already_seen[orig] = copy -- memoize before any recursion, to avoid infinite loops
for orig_key, orig_value in pairs(orig) do
copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen)
end
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
setmetatable(copy, _deepCopy(mt, true, already_seen))
end
end
return copy
end
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen or {})
end
------------------------------------------------------------------------------------
-- sparseConcat
--
-- Concatenates all values in the table that are indexed by a number, in order.
-- sparseConcat{a, nil, c, d} => "acd"
-- sparseConcat{nil, b, c, d} => "bcd"
------------------------------------------------------------------------------------
function p.sparseConcat(t, sep, i, j)
local arr = {}
local arr_i = 0
for _, v in p.sparseIpairs(t) do
arr_i = arr_i + 1
arr[arr_i] = v
end
return table.concat(arr, sep, i, j)
end
------------------------------------------------------------------------------------
-- length
--
-- Finds the length of an array, or of a quasi-array with keys such as "data1",
-- "data2", etc., using an exponential search algorithm. It is similar to the
-- operator #, but may return a different value when there are gaps in the array
-- portion of the table. Intended to be used on data loaded with mw.loadData. For
-- other tables, use #.
-- Note: #frame.args in frame object always be set to 0, regardless of the number
-- of unnamed template parameters, so use this function for frame.args.
------------------------------------------------------------------------------------
function p.length(t, prefix)
-- requiring module inline so that [[Module:Exponential search]] which is
-- only needed by this one function doesn't get millions of transclusions
local expSearch = require("Module:Exponential search")
checkType('length', 1, t, 'table')
checkType('length', 2, prefix, 'string', true)
return expSearch(function (i)
local key
if prefix then
key = prefix .. tostring(i)
else
key = i
end
return t[key] ~= nil
end) or 0
end
------------------------------------------------------------------------------------
-- inArray
--
-- Returns true if searchElement is a member of the array, and false otherwise.
-- Equivalent to JavaScript array.includes(searchElement) or
-- array.includes(searchElement, fromIndex), except fromIndex is 1 indexed
------------------------------------------------------------------------------------
function p.inArray(array, searchElement, fromIndex)
checkType("inArray", 1, array, "table")
-- if searchElement is nil, error?
fromIndex = tonumber(fromIndex)
if fromIndex then
if (fromIndex < 0) then
fromIndex = #array + fromIndex + 1
end
if fromIndex < 1 then fromIndex = 1 end
for _, v in ipairs({unpack(array, fromIndex)}) do
if v == searchElement then
return true
end
end
else
for _, v in pairs(array) do
if v == searchElement then
return true
end
end
end
return false
end
------------------------------------------------------------------------------------
-- merge
--
-- Given the arrays, returns an array containing the elements of each input array
-- in sequence.
------------------------------------------------------------------------------------
function p.merge(...)
local arrays = {...}
local ret = {}
for i, arr in ipairs(arrays) do
checkType('merge', i, arr, 'table')
for _, v in ipairs(arr) do
ret[#ret + 1] = v
end
end
return ret
end
------------------------------------------------------------------------------------
-- extend
--
-- Extends the first array in place by appending all elements from the second
-- array.
------------------------------------------------------------------------------------
function p.extend(arr1, arr2)
checkType('extend', 1, arr1, 'table')
checkType('extend', 2, arr2, 'table')
for _, v in ipairs(arr2) do
arr1[#arr1 + 1] = v
end
end
return p
4n03zk6kcoeg4gz82mieeh94c1szcjy
Module:Yesno
828
273
9092
8821
2026-08-22T14:15:34Z
RAPTOR7762
18
Protected "[[Module:Yesno]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
1152
Scribunto
text/plain
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to the template {{yesno}}.
return function (val, default)
-- If your wiki uses non-ascii characters for any of "yes", "no", etc., you
-- should replace "val:lower()" with "mw.ustring.lower(val)" in the
-- following line.
val = type(val) == 'string' and val:lower() or val
if val == nil then
return nil
elseif val == true
or val == 'yes'
or val == 'y'
or val == 'true'
or val == 't'
or val == 'on'
or tonumber(val) == 1
then
return true
elseif val == false
or val == 'no'
or val == 'n'
or val == 'false'
or val == 'f'
or val == 'off'
or tonumber(val) == 0
then
return false
else
return default
end
end
swdskn7svew8i9wuydn9uj5l3r2ghcs
Module:Yesno/doc
828
274
9091
1155
2026-08-22T14:14:41Z
RAPTOR7762
18
9091
wikitext
text/x-wiki
{{Template rating|release}}
4gg9hd14ezf0g36wd5h58l106fdgy3u
9204
2025-09-29T09:46:33Z
en>Dandorid
0
Introduce terse coding that always returns a boolean value ('nil' is never returned).
9204
wikitext
text/x-wiki
<noinclude>{{pp|small=yes}}
</noinclude>{{used in system}}
{{Module rating|protected}}
{{cascade-protected template|page=module}}
This module provides a consistent interface for processing boolean or boolean-style string input. While Lua allows the <code>true</code> and <code>false</code> boolean values, wikicode templates can only express boolean values through strings such as "yes", "no", etc. This module processes these kinds of strings and turns them into boolean input for Lua to process. It also returns <code>nil</code> values as <code>nil</code>, to allow for distinctions between <code>nil</code> and <code>false</code>. The module also accepts other Lua structures as input, i.e. booleans, numbers, tables, and functions. If it is passed input that it does not recognise as boolean or <code>nil</code>, it is possible to specify a default value to return.
== Syntax ==
<syntaxhighlight lang="lua">yesno(value, default)</syntaxhighlight>
<code>value</code> is the value to be tested. Boolean input or boolean-style input (see below) always evaluates to either <code>true</code> or <code>false</code>, and <code>nil</code> always evaluates to <code>nil</code>. Other values evaluate to <code>default</code>.
== Usage ==
First, load the module. Note that it can only be loaded from other Lua modules, not from normal wiki pages. For normal wiki pages you can use {{tl|yesno}} instead.
<syntaxhighlight lang="lua">
local yesno = require('Module:Yesno')
</syntaxhighlight>
Some input values always return <code>true</code>, and some always return <code>false</code>. <code>nil</code> values always return <code>nil</code>.
<syntaxhighlight lang="lua">
-- These always return true:
yesno('yes')
yesno('y')
yesno('true')
yesno('t')
yesno('on')
yesno('1')
yesno(1)
yesno(true)
-- These always return false:
yesno('no')
yesno('n')
yesno('false')
yesno('f')
yesno('off')
yesno('0')
yesno(0)
yesno(false)
-- A nil value always returns nil:
yesno(nil)
yesno()
</syntaxhighlight>
String values are converted to lower case before they are matched:
<syntaxhighlight lang="lua">
-- These always return true:
yesno('Yes')
yesno('YES')
yesno('yEs')
yesno('Y')
yesno('tRuE')
-- These always return false:
yesno('No')
yesno('NO')
yesno('nO')
yesno('N')
yesno('fALsE')
</syntaxhighlight>
===Undefined input ('foo')===
You can specify a default value if yesno receives input other than that listed above. If you don't supply a default, the module will return <code>nil</code> for these inputs.
<syntaxhighlight lang="lua">
-- These return nil:
yesno(nil)
yesno('foo')
yesno({})
yesno(5)
yesno('')
yesno(function() return 'This is a function.' end)
yesno(nil, true)
yesno(nil, 'bar')
-- These return true:
yesno('foo', true)
yesno({}, true)
yesno(5, true)
yesno('', true)
yesno(function() return 'This is a function.' end, true)
-- These return "bar":
yesno('foo', 'bar')
yesno({}, 'bar')
yesno(5, 'bar')
yesno('', 'bar')
yesno(function() return 'This is a function.' end, 'bar')
</syntaxhighlight>
Although the empty string usually evaluates to false in wikitext, it evaluates to true in Lua. This module prefers the Lua behaviour over the wikitext behaviour. If treating the empty string as false is important for your module, you will need to convert empty strings to a value that evaluates to false before passing them to this module. In the case of arguments received from wikitext, this can be done by using [[Module:Arguments]].
===Handling nil results===
By definition:
<syntaxhighlight lang="lua">
yesno(nil) -- Returns nil.
yesno('foo') -- Returns nil.
yesno(nil, true) -- Returns nil.
yesno(nil, false) -- Returns nil.
yesno('foo', true) -- Returns true.
</syntaxhighlight>
To get the binary <syntaxhighlight lang="lua" inline>true/false</syntaxhighlight>-only values, use code like:
<syntaxhighlight lang="lua">
myvariable = yesno(value or false) -- When value is nil, result is false.
myvariable = yesno(value or true) -- When value is nil, result is true. (XXX: when value is false, result is true...)
myvariable = yesno('foo') or false -- Unknown string returns nil, result is false.
myvariable = yesno('foo', true) or false -- Default value (here: true) applies, result is true.
</syntaxhighlight>
Better suggestions:
<syntaxhighlight lang="lua">
local myvariable = yesno(value)
if myvariable == nil then -- value is nil or an unrecognized string
myvariable = true
end
-- more efficient when value is nil, but more verbose
-- (note the default result has to be written twice)
local myvariable
if value == nil then
myvariable = true
else
myvariable = yesno(value, true)
end
-- Terse coding when the default is false:
myvariable = yesno(value or false, false)
-- if value is nil, yesno() is called with false instead; result is false.
-- If value is 'foo', yesno() is called with 'foo'; 'foo' makes no sense, so the default (false) is returned.
-- if value is 'yes' or 'no', yesno() is called with 'yes' or 'no'; result is true or false.
-- Terse coding when the default is true:
myvariable = yesno(value or true, true)
-- if value is nil, yesno() is called with true instead; result is true.
-- If value is 'foo', yesno() is called with 'foo'; 'foo' makes no sense, so the default (true) is returned.
-- if value is 'yes' or 'no', yesno() is called with 'yes' or 'no'; result is true or false.
</syntaxhighlight><!--
--><includeonly>{{sandbox other||
[[Category:Lua metamodules]]
}}</includeonly>
<noinclude>
[[Category:Module documentation pages]]
</noinclude>
7nij6zaba2wmwxwnrr39rd4qis7t51p
9205
9091
2026-08-23T02:57:39Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Yesno/doc]]
9091
wikitext
text/x-wiki
{{Template rating|release}}
4gg9hd14ezf0g36wd5h58l106fdgy3u
Bauchi
0
455
9087
8475
2026-08-22T12:10:48Z
Abu Sadeeq77
197
9087
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
ljfsrt3wbjw6myt9lh6z4333305bjzz
9088
9087
2026-08-22T13:36:02Z
Abu Sadeeq77
197
9088
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
kn9pceuzfi2tl412fb27dllhyoopneq
9143
9088
2026-08-22T18:12:44Z
Abu Sadeeq77
197
9143
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
lwb9ubmudtmchb0hn3qpza0rxd5tzcy
9144
9143
2026-08-22T18:43:41Z
Abu Sadeeq77
197
9144
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
jyow1cy5fffmq4713n8fho6dqqfzma5
9145
9144
2026-08-22T18:44:59Z
Abu Sadeeq77
197
9145
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
jqzeufjkneitgusbyjtk7u36a751zpl
9146
9145
2026-08-22T19:12:05Z
Abu Sadeeq77
197
9146
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
j57y12n6cd677plbfo6eugfrzn42oqr
9147
9146
2026-08-22T19:18:41Z
Abu Sadeeq77
197
9147
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
brtw3h8310r448684wrj3ncfp2fzq54
9148
9147
2026-08-22T19:22:16Z
Abu Sadeeq77
197
9148
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
Beyilla Aji undani ga Bauchi kasantu kafin soni 1976 gunduma ga yanki jiha gudi Ko ɗar ga . Dangane ga kidaya in 2006 jiha Aji ga mi'yya Kimani 4.653,006
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
0at2na1j1yzt9grslcnb0ouejnlmbbg
9149
9148
2026-08-22T19:30:02Z
Abu Sadeeq77
197
9149
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
Beyilla Aji undani ga Bauchi kasantu kafin soni 1976 gunduma ga yanki jiha gudi Ko ɗar ga . Dangane ga kidaya in 2006 jiha Aji ga mi'yya Kimani 4.653,006
Jiha Bauchi wattu Tina Dom kala-kala gaga soni Manne . Andi harshe Ajawa ga Aji amfa ga ishin ga jiha Bauchi kala Koga bisani yakilannin ga gaga sonii 1920 ga soni in 1940 inko asali anin amfani ga harshe ye manjisu Bo afiniwa.
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
6x9wepgni5vmobzu9rxv0tnjt2kn6ay
9150
9149
2026-08-22T19:34:34Z
Abu Sadeeq77
197
9150
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
Beyilla Aji undani ga Bauchi kasantu kafin soni 1976 gunduma ga yanki jiha gudi Ko ɗar ga . Dangane ga kidaya in 2006 jiha Aji ga mi'yya Kimani 4.653,006
Jiha Bauchi wattu Tina Dom kala-kala gaga soni Manne . Andi harshe Ajawa ga Aji amfa ga ishin ga jiha Bauchi kala Koga bisani yakilannin ga gaga sonii 1920 ga soni in 1940 inko asali anin amfani ga harshe ye manjisu Bo afiniwa.
Ga Lokaci Mulki mallaka Har lokaci wena yanci, ita aga yanki plateau ga yanki gudi Najeriya, Har zuwa soni in 1967 lokacin la an wena ga jihohi ga yankuna Bauchi, Bornoga Adamawa Aji gonta beyi wena jiha gudi ga Dar.
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
dwgmwdwlorcuqxs39grjnce6f57swqx
9151
9150
2026-08-22T19:40:47Z
Abu Sadeeq77
197
9151
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' Woli Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom miyya (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru filanti ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi Nigeria. La kobai majjito Nigeria wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
Beyilla Aji undani ga Bauchi kasantu kafin soni 1976 gunduma ga yanki jiha gudi Ko ɗar ga . Dangane ga kidaya in 2006 jiha Aji ga mi'yya Kimani 4.653,006
Jiha Bauchi wattu Tina Dom kala-kala gaga soni Manne . Andi harshe Ajawa ga Aji amfa ga ishin ga jiha Bauchi kala Koga bisani yakilannin ga gaga sonii 1920 ga soni in 1940 inko asali anin amfani ga harshe ye manjisu Bo afiniwa.
Ga Lokaci Mulki mallaka Har lokaci wena yanci, ita aga yanki plateau ga yanki gudi Najeriya, Har zuwa soni in 1967 lokacin la an wena ga jihohi ga yankuna Bauchi, Bornoga Adamawa Aji gonta beyi wena jiha gudi ga Dar.
Boi wena jiha Bauchi ga soni in 1976, ga Lokaci jihohi balau Bauchi ga Gombe in Gonto , jiha Andi dolinshe hukumomi guda (20) jamji kala (23). Jamji kala ga soni in 1997 , wantun jiha Gombe. Koga jiha Bauchi inko Aji wena sauwi dolinshe hukumomi ga Woli inko Dayan jaha Bauchi ga dolinshe hukumomi (20) mana yadda foran goyi:
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
dix02p7wypt2uerjuoznm728z8ief6r
9152
9151
2026-08-22T19:47:07Z
Abu Sadeeq77
197
9152
wikitext
text/x-wiki
{{Databox|item=Q811144}}
'''Bauchi''' [[Woli]] Bauchi woli Ji ya a fayta Aushi Dola Darr Ga woli [[Nijeriya]]. Gontattuk lefe Ga [[Kano]] Ko Aushi kafa [[Jigawa]], [[Gombe]], ga [[Jiha Yobe|Yobe]] Ko fayta Darr, kafa [[Kaduna]] Ko Zoni. Woli Bauchi wen zalshe sunto Ko labar Bani yele Bauchi, Yaa Ke itaji Burnin in Siri ye Har soni in 1976. Ga lokacin la bissan manshi jihohi gudi mana dar ga Nigeria. Ga boii jiha Bauchi bikkantun jiha Gombe, la koboii majjito jiha an Dono kotto ga soni in 1996
Zan woli Bauchi Ga Soni Dubu Modi Ga Dalma ɓonum Ga kobawulo Ga basshi modi (1976), Ga lotayeji missan Manshi woliye Aushi Ndola Darr [[Nijeriya]]. Ga boii woli Bauchi tattuk/gontattuk woli [[Gombe]], yake Ko tetteke ita Mai jito wolin in kotto Ga Ga Soni 1996.
Bauchi itaji jaha in badi ga fadi woli (2) kala in bawulo ga godom [[Miyya Ogun|miyya]] (3). Itaga godom filaye kimani kilomita dubu arba 'in ga badi ga dalma hordo ga cassa'in ga kunum(45, 893) godom miyya kimani miliyan bawulo ga dubu dalma badi ga arba'in ga dalma baccimodi ga sittin ga kunum (7,540,663) (4) ga bisa kidaya soninshe in dubu balau ga baccimodi 2006 . Jaha ye rabajjito dangane ga yanayi woli zuwa kashi balau (2) west sudaniya savanna koga aushi ga kala semi-desert sahel savanna koga Arewa ga koga montane Jos plateau aushi mana zoni jiha (5) koga kyautalla beyinshe ga goruye gontu ga yankari National park katafri beyi zenani fa dabbobi mana bijimi bido barewa ga Turum Giwa ga messesu.(6)
Bauchi ji siri jaha bauchi. Bala abdulkadir Muhammad Ishin ji gwamna jiha ye Yan zaben la soninshe in 2019 har zuwa inso. Maddi koga su. Manshiwa jiha gontan go ga abubakar tafawa balewa gamin Isa yakubu, isah Hamma misau Nazif gamawa, haruna Ningi ga ali wakil.
Andi yarinshe godom ga yankuma daban daban in jihar gotango ga, Bo'fikka, ga Butawa ga yare warji koga yankuna dalla jiha yaren Fulfulde, yare Kanuri, ga yare karei'karei koga zani goru [[filanti]] ga yare gerawa, koga birni bauchi ga kewaye to yare zaar (sayawa) koga aushi yare Tangale Jarawa ko aushi mana zoni. Kala asari miyya goru (kaso tamanin ga badi 85%) musulwa ji ga dole kaso kiristoci ga kaso baccimodi 6% ga maguzawa ga kaso bonum 9% (7)
ga farko soni Alif 1800,a Filanti jahadi bikkantun mafi akasari goruye birni Bauchi in inso. Jamji kafan moyinshe Bauchi ga wol woli daula musulunci in Sokoto ga Karni in 1900, turawa Mulki mallaka bikkantun moyinshe ye mete zuwoto ga wol woli mulki mallaka in gudi [[Nijeriya|Nigeria]]. La kobai majjito [[Nijeriya|Nigeria]] wol woli mulki turawa kafin wena yanci ga soni 1960 , Yan asali yanki jiha Bauchi Iya a gudi Nigeria Boi wena yanci koyi ga soni 1967, lokacin la bissan jiha ye majjito wol woli jiha gudi Nigeria ko ɗar boi bissa jiha gudi Ko ɗar kafan jiha Bauchi ga Foti kunum' (3) ga tare February ga soni in (20) kala boi kafato wantun dolinshe hukumomi ga zoni jiha ye meteji manjisu Bo jiha Gombe.
Ga matsayi to in jiha la dogaran ga mara, tattali dara jiha ye Ta'allaku gako dabbobi ga hantsi manamin auduga, Duro kute, tumaturi ga kala doya jizani ga Tina Dom amfani mara daidai ga sauwa habika tishi ga masana'antu sarrifa karai tishi in gwan_gwani, ga kala oppako ma'adanai manamin mana kisato columbite, ga kala beyi ewe ido mana mala kume zoii in yankari ga Amma in wikki spring.
== Asali sun ==
Dan game ga tarihi in gargajiya goruye watu asali ji ko gama an'bara Modi la Sunni baushe , la dowu ga yanki ye kafin nako moyinshe in farko wato Yakubu (la wantun Ko Dalla soni in 1800-10) jahohi Bauchi ga Adamawa kasantan anin yanci ga Goma ga mi'yya Daula Filanti in Sokoto.
== Tarihi ==
Beyilla Aji undani ga Bauchi kasantu kafin soni 1976 gunduma ga yanki jiha gudi Ko ɗar ga . Dangane ga kidaya in 2006 jiha Aji ga mi'yya Kimani 4.653,006
Jiha Bauchi wattu Tina Dom kala-kala gaga soni Manne . Andi harshe Ajawa ga Aji amfa ga ishin ga jiha Bauchi kala Koga bisani yakilannin ga gaga sonii 1920 ga soni in 1940 inko asali anin amfani ga harshe ye manjisu Bo afiniwa.
Ga Lokaci Mulki mallaka Har lokaci wena yanci, ita aga yanki plateau ga yanki gudi Najeriya, Har zuwa soni in 1967 lokacin la an wena ga jihohi ga yankuna Bauchi, Bornoga [[Adamawa]] Aji gonta beyi wena jiha gudi ga Dar.
Boi wena jiha Bauchi ga soni in 1976, ga Lokaci jihohi balau Bauchi ga Gombe in Gonto , jiha Andi dolinshe hukumomi guda (20) jamji kala (23). Jamji kala ga soni in 1997 , wantun jiha [[Gombe]]. Koga jiha Bauchi inko Aji wena sauwi dolinshe hukumomi ga Woli inko Dayan jaha Bauchi ga dolinshe hukumomi (20) mana yadda foran goyi:
==Dolinshe Hukumomi==
jaha bauchi Andi adadi dolinshe hukumomi kobalau ([[20]]). Mate:
{| class="sortable wikitable"
|-
! Dolinshe Hukuma
! Fadin kasa (km<sup>2</sup>)
! Adadin 2006<br> Mutane
! Cibiyar Karamar Hukuma
! Lambar aika<br>sako
|-
| [[Bauchi]]
| align="right"|3,687
| align="right"|493,810
| [[Bauchi]]
| 740
|-
| [[Tafawa Balewa, Nigeria|Tafawa Balewa]]
| align="right"|2,515
| align="right"|219,988
| [[Bununu, Nigeria|Bununu]]
| 740
|-
| [[Dass, Nigeria|Dass]]
| align="right"|535
| align="right"|89,943
| [[Dass, Nigeria|Dass]]
| 740
|-
| [[Toro, Nigeria|Toro]]
| align="right"|6,932
| align="right"|350,404
| [[Toro, Nigeria|Toro]]
| 740
|-
| [[Bogoro]]
| align="right"|894
| align="right"|84,215
| [[Bogoro]]
| 741
|-
| [[Ningi, Nigeria|Ningi]]
| align="right"|4,625
| align="right"|387,192
| [[Ningi, Nigeria|Ningi]]
| 742
|-
| [[Warji]]
| align="right"|625
| align="right"|114,720
| [[Warji]]
| 742
|-
| [[Ganjuwa]]
| align="right"|5,059
| align="right"|280,468
| [[Kafin Madaki]]
| 742
|-
| [[Kirfi]]
| align="right"|2,371
| align="right"|147,618
| [[Kirfi]]
| 743
|-
| [[Alkaleri]]
| align="right"|5,918
| align="right"|329,424
| [[Alkaleri]]
| 743
|-
| ''Southern region totals''
| align="right"|''33,161''
| align="right"|''2,497,782''
|
|
|-
| [[Darazo]]
| align="right"|3,015
| align="right"|251,597
| [[Darazo]]
| 750
|-
| [[Misau]]
| align="right"|1,226
| align="right"|263,487
| [[Misau]]
| 750
|-
| [[Giade]]
| align="right"|668
| align="right"|156,969
| [[Giade]]
| 750
|-
| [[Shira, Nigeria|Shira]]
| align="right"|1,321
| align="right"|234,014
| [[Yana, Nigeria|Yana]]
| 750
|-
| [[Jama'are]]
| align="right"|493
| align="right"|117,883
| [[Jama'are]]
| 751
|-
| [[Katagum]]
| align="right"|1,436
| align="right"|295,970
| [[Azare]]
| 751
|-
| [[Itas/Gadau]]
| align="right"|1,398
| align="right"|229,996
| [[Itas]]
| 751
|-
| [[Zaki, Nigeria|Zaki]]
| align="right"|1,476
| align="right"|191,457
| [[Katagum]]
| 752
|-
| [[Gamawa]]
| align="right"|2,925
| align="right"|286,388
| [[Gamawa]]
| 752
|-
| [[Damban]]
| align="right"|1,077
| align="right"|150,922
| [[Damban]]
| 752
|-
| ''Northern region totals''
| align="right"|''15,035''
| align="right"|''2,178,683''
|
|
|}
== Ɗiwwa ==
czdl3usgcg19rwjcljcnuxyx3gjlp0s
Bayelsa
0
456
9153
8800
2026-08-22T19:52:51Z
Abu Sadeeq77
197
9153
wikitext
text/x-wiki
[[File:Targa automobilistiche Nigeria Bayelsa 1992.jpg|thumb|Lambar Bayelsa]]
[[File:Bayelsa state contingent.jpg|thumb|mi'yya Bayelsa]]
[[File:Swali Market, Swali. Bayelsa, Nigeria.jpg|thumb|gawa bimbadi Swali ga birnin Bayelsa]]
[[File:Rivers in bayelsa.jpg|thumb|fali bayelsa]]
[[File:First Baptist Church, Ovom, Bayelsa state.jpg|thumb|modi koga jiha bayelsa]]
[[File:Masquerade display.jpg|thumb|Al adon balyalsa]]
''''Italic text''''{{Databox|item=Q532153}}
'''Bayelsa''' Woli Bayelsa eta a fayta gudi fayta gudin [[Nijeriya]], ita a tene Dai Dai Dalla beyi [[Niger]] Delta.<ref>"Yenagoa | Location, Facts, & Population". ''Encyclopedia Britannica''. Retrieved 2021-09-11.</ref><ref name=":0">"Bayelsa – History & Culture – Bayelsa State Government". Retrieved 2021-09-11.</ref> Zan tan woli Bayelsa ye gaga Soni Dubu Modi Ga Dalma ɓonum Ga bacchi Modi(1996),<ref>"Bayelsa State". ''[[BBC]] News Pidgin''. Retrieved 2022-03-06.</ref> Ke foɗin tango Koji woli Rivers.<ref>"Rivers state Archives". ''The Guardian [[Nigeria]] News - [[Nigeria]] and World News''. Retrieved 2022-03-06.</ref> mammeye zowwo faruye wentan Koga woli Yaa Onan go foyo Ga woliye. Gontattuk kodoki Ga woli Rivers<ref>"Rivers state Archives". ''The Guardian Nigeria News - [[Nigeria]] and World News''. Retrieved 2022-03-06.</ref> Ko fayta Darr, gake woli Delta Ko Zoni, beyila Aushi Atalanta tattuk beyi ye lo gudi Ga woli ye.
Woli bayelsa itaga Siri woli Kimani kilomita 10,773kmaq, inko she majjito jiha Laga karanci fili ga Nigeria. Kala itaga godom mi'yya Kimani 2,394,725, (kiyasi in 2016) shiyasa itaji jiha Laga mi'yya sosai sa. Siri birni jiha ye itaji Yenagoa . Douye Diri ji gwamna jiha ye soni in 2022. Antaimika ni ishinji Lawrence Ewrudjakpo. Dottawa jiha ye gontango gamin, [[Goodluck Jonathan|Goodluck]] Jonathan, David Clark Ben Murray Bruce, Emmanuel paulker Izibefien ga Even Foster Ogola. Ga sanadiya kasantuwato ga yanki Niger Delta, Jiha Bayelsa mamayantun Andi ga Kogi ga Amma. Kala shaf goruye amma ji. Inko she shiyasa itaga tinadom sosae sa ko Ina goggo titi.
Aji amfani ga Harshe Ijaw ga lema au ga jiha ye jizani ga Messe harsuna mana Isoko ga Urhobo ga manshi kyauyuka jiha ye.
Bukukuwa Bayelsa
Itaga dolinshe hukumomi 8: Ekeremor, kolokumal Opokuma,Yenagoa, Nemba,Ogabia, Sagbama,hi brassa ga kala ijaw aushi. Bayelsa kasantu boni ga mi'yya Urhabo ga dole Hukuma Sagbama.
Ga dalili kasantu ga yanki Dara Mor fetur Niger Delta tattali dara jiha bayelsa ta allakan gako she Mor fetur ga maikata tacayi . Yanki Oloibiri Oilfield beyila zalan oppa Mor fetur ga Nigeria. Jamji zuwa soni 2015, kiyastan gako Aji wena Kashi 30_40% in Mor fetur ga [[Nijeriya|Nigeria]]. Aji Ina lakabi ga jiha ye ga sun "Glory of all lands " jamji itaga tafki gas la siri ga Nigeria (18 trillion cubic). Shaf Andi Siri bozo Mor fetur kala Aji kokari Ko beyi Tina Dom tattali dara woli, yakul itu godaom ga jiha jamji ga yakul beyi Dono. Ko fesako Mor fetur.
== Siyasa ==
Ko soni in 2020 zuwa soni 2023, Douye Diri ji gwamna jiha ye ga yayila, Lawrence Ewrudjakpo Aji taimika ni.
== Ɗolle hukumomi ==
# Brass
# Ekeremor
# Kolo kuma/okopuma
# Nembe
# Ogbia
# Sagbana
# Southerm ijew
# Yenagua
== Beyi ==
Bayelsa ita aga jahohi aushi Nigeria, jiha ye a tene Dalla Niger Delta. Fodan jiha Bayelsa Koga jiha Rivers, kala Aji Koga foyo jihohi Nigeria.
Jiha Bayelsa gontan iyaka ga jiha Rivers Koga Dar, jiha Delta (jiha) Koga zoni, ga yayi ga Amma Atalanta mamayantun yanki aushi jiha ye.
== Tarihi ==
Ga karni in 20th, bukatu in wena Poyo jiha ga harshen Ijaw ga rinjaye ga yankin Monani ga Niger Delta. Ga Dalla soni in 1941, zuwa in 1956, kafan kungiyoyi godom la aji ona goyon bayan wena jiha in Miy'ya Ijaw ga yankin aushi Najeriya. Isaac Adaka Boro, modi shahararren an gwagwarmayar Ijaw ga soni in 1960, la layannin ga Oloibiri itu yinkurin ikirarin "Jimhoriyar Mi'yya Niger Delta ("Niger Delta Peoples Republic") ga soni in 1966.Shugaba woli in mulkin mallaka Sani Abacha ji kirkiru Jihar Bayelsa Koga Jihar Rivers ga Foti modi 1, ga Tere Oktoban, soni in 1966. Wantun asalin sun koga haruffa in farko in sun dolinshe hukumomin in: Brass LGA (BALGA), Yenagoa LGA (YELGA) ga kala Sagbama LGA (SALGA).[19]
Ga Foti 20 , ga Tere disamba soni in 1999, ji sojoji [[Nijeriya|Nigeria]] kaddiman ga yella monannin ga Moto kiyashin odi. Aji kokonto ainihi godom mi'yya la mottanjisu, shafga she , Nnimmo Bassey, Siri Darekta in Hakki Harkoki beyi Dono, foru gako soja fetila tajiya guda 2500 ji la mottan jisu.
Gako zaizaya woli ga jiha ye ga dalili beyi Ruta mor petur antun zanga-zanga godom mana min "Rise for Bayelsa" la antungo inko inganta wena Amma senayi ga yankuna la dole. Koga soni in 2019, ji Gwamnati jiha Bayelsa zalan zauwa Gwagwarmaya wena ga mafita dangane ga matsaloli gurbata beyi Dono ga jiha ye.
== Tattali Dara ==
Jiha ye ita aga jiha Laga barka Mor fetur ga Nigeria. Ga dalili she Andi godom Mor fetur ga jiha ye. Shfaga jiha ye itaga Dara Mor. Jiha Andi wena karanci wena dodo Koga kasafi Mor fetur ga dalili yakul daidaito ga tsari kasafi Koga Gwamnati woli.
== Yanayi woli ==
Bayelsa la zagayeni ga Amma fali ga kala korama. Yankuna jiha ye godom kiwiyasu ga Amma inko she a giyta riskasu Ko tituna sa. Andi Gandu mala in "Edumanom Forest Reserve" ga jiha . Yan Tere Yuli soni in 2008 , inko innan Bido chimpanzee in tetteke itaji Niger Delta. Messe muhimma birni boii yengola Aji gonta ga: Akassa , Lobia Amassoma (the home of the Niger Delta University), Eniwari , Ekeremor, Aliebiri , peretoru , Twon-Brass Egwema -Brass, Kaiama, Nembe, Odi, Ogabia , Okpoama, Brass Oporoma, Korokorosei, Otuan, Koroama, Okorobiri, Obunagha, Ogboloma, Sagbama, Olugbobiri, peremabiri, Ekowe, ga kala swali.
Andi kala solu Lighthouse la a tene Yan soni in 1910.
== Harsuna ==
Asali Harshe la Aji amfa ga ishin ishinji Harsha ijew , jizani ga Ɓo Kolukuma, mein, Bomu, Nemba , Epie-Atisa, ga kala Ogbia. Mana de ga Messe jihohi Nigeria, Turanci ji Harshe Gwamnati jiha ye.
Jeri harsuna jiha Bayelsa dangane ga dolinshe hukumomi LGA la Aji amfa ga mete.
:<ref name="e22">{{Cite news|url=https://www.ethnologue.com/country/NG|title=Nigeria|work=Ethnologue|edition=22|access-date=2020-01-10}}</ref>
[[File:Izon-tubos.jpg|300px|thumb|Ekeremor, Bayelsa State]]
{| class="wikitable"
! LGA !! Languages
|-
| Brass || Abureni; Southeast Ijo; Ogbia; Kugbo
|-
| Ekeremor || Izon
|-
| Kolokuma Opokuma || Izon
|-
| Nembe || Abureni; Southeast Ijo. Izon (Ijaw)
|-
| Ogbia || Abureni; Southeast Ijo; Odual; Ogbia; Oruma
|-
| Sagbama || Biseni; Isoko; Izon; Ogbah; Okodia; Urhobo
|-
| Ijaw ta Kudu || Southeast Ijo; Izon
|-
| Yenagoa || Engenni; Epie; Izon; Ekpeye
|}
== Matsala Beyi Dono ==
== Penpeli la gonsa ==
Eme Bu'um Olloki ji la Aji Indo inko dalili bokka Mor fetur gako ka'ida sa (aji undani ga gargaji "Osi Kpo). La mugaye sinadarai Aji yellako yakul lafiya mana fada huhu, ga mala, matsaloli Dishi, matsala Sena penpeli ga Messe su. Agita inne Messe illolito mana Gurbacewa penpeli, Amma ga woli la she aji yollako moto Mi'yya, ga tsirrai, ga dabbobi.
== Ambaliya Amma ==
Emeyye matsala la wenani ga jiha bayelsa ji. Inko ita ako Ɓo Amma Atalanta. Indako zori amma teku ji, muhimmi dalili in ambaliya Amma ye. Ambaliya elentun matsala ga mi'yya godom Dara ga mi'yya. Lebeyi yalla ga Bayelsa Aji inner matsala ambaliya, kala ambaliya ye ya'tu inayi ga beyi Maddi mana , Ekeremor,Ijaw,Ko aushi, Sagbama,kolokumal/Opokuma ga kala Yenagoa la Aji fuskata matsala ga le soni yalla yaku doffa tsari Soli ishinma aga matsala la Aji alako ambaliya ga jiha ye in bayelsa.
== Jubba mor ==
Emeyye muhimmi al'amari Modi ji la Aji alako matsala Beyi donno ga jiha bayelsa ga dalili Ruta kamfanoni Mor ga jiha bayelsa. Jubba mor aji alako matsala ga mala, halittu ga Amma, ga mi'yya kala le Foti yalla Aji sanarwa Udengs Eradiri labar jubba Mor ga jiha bayelsa, Niger Delta.
Mana yadda Aji forayi , ga kisato Kagita Ina mara ka ai girbi kawena Yan gollaka, do kadai Bo iwa kifi ka iwako godom, Amma honsene kagita Dina kabushi kawena lelensa.
Matsala modi in beyi dono itaji pempeli la gonsa (Soot) , la godom mi'yya bayelsa Aji complaint mete agito yolla numfashi gonsa.
Amma ga soni (2018) anin dodo antum amfani ga take "Save Rivers from this Soot of death" wato a kiyaye Amma ga moto Soot, ga shaf beyi la Amma tiwoyi.
== Ilimi ==
Jiha Bayelsa Andi makarantu mataki daban daban la Aji ona ilmi ga godom mi'yya jiha ye.
== Jami'o i ==
makarantu Dom ga sakandare ga bayelsa.
* [[Jami'ar Neja Delta]].
* College of Health Science Bayelsa.
* [[Isaac Adaka Boro|Isaac Jasper Boro]] College of Education.
* College of Nursing Bayelsa.
* Bayelsa Medical University.
* Bayelsa State College of Art and Science.
* University of Africa.
* International Institute of Tourism and Hospitality<ref>https://independent.ng/bayelsa-govt-tasks-governing-councils-of-state-owned-tertiary-institutions/amp/</ref>
== Sun mi'yya la Monasu sosae Ga Bayelsa ==
<!---♦♦♦ Only add a person to this list if they already have their own article on the English Wikipedia ♦♦♦--->
<!---♦♦♦ Please keep the list in alphabetical order by LAST NAME ♦♦♦--->
* [[Diepreye Alamieyeseigha]], Manshi an siyasa ga Nigeria kala manshi gwamna jiha bayelsa.
* [[Diezani Alison-Madueke]],Ministan Ma'adanai, Sufuri ga Albarkatun Mor-fetur<ref>{{Cite news|url=https://www.vanguardngr.com/2014/12/diezani-alison-madueke-scored-another-firs/amp/|title=Diezani Alison-Madueke scored another firs - Vanguard News|date=2014-12-02|work=Vanguard News|access-date=2018-07-30|language=en-US}}</ref>
* [[MC Aproko]], stand-up comedian.
*[[Owoye Andrew Azazi]], Chief of Army Staff ga (Nigeria), Chief of Defense Staff ga lokacin mulkin shugaba [[Olusegun Obasanjo]] Jamji kala an ona in shugaba woli Shawara gako harka tsaron in shugaban woli [[Goodluck Jonathan]].
*[[Noah Sarenren Bazee]] a professional footballer who plays for [[Bundesliga]] side [[Hannover 96]].<ref>{{Cite web|title=Noah Bazee biography, net worth, age, family, contact & picture|url=https://www.manpower.com.ng/people/15766/noah-bazee|access-date=2021-09-12|website=www.manpower.com.ng}}</ref>
* [[Isaac Adaka Boro]], Jarumi ga yakin basasar Najeriya (Nigerian Army)<ref>{{Cite web|url=http://www.gamji.com/article4000/news4657.htm|title=Who Killed Adaka Boro|website=www.gamji.com|access-date=2018-07-30|archive-date=2018-07-24|archive-url=https://web.archive.org/web/20180724163427/http://www.gamji.com/article4000/news4657.htm|url-status=dead}}</ref>
* [[Timi Dakolo]], an aru<ref>{{Cite news|url=https://praisemama.com/artists/timi-dakolo/|title=TIMI DAKOLO|work=PraiseMaMa.com|access-date=2018-07-30|language=en-US|archive-url=https://web.archive.org/web/20180730110833/https://praisemama.com/artists/timi-dakolo/|archive-date=2018-07-30|url-status=dead}}</ref>
* [[Edmund Daukoru]], Ministan Najeriya in Jiha gako Makamashi kala kasancetu Secretary General ga Kungiyar wolinshe Anin Fete ga Mor Fetur ga shekara in 2006, HRM<ref>{{Cite web|url=http://www.gamji.com/article6000/NEWS6840.htm|title=Edmund Daukoru|website=www.gamji.com|access-date=2018-07-30}}</ref>
*[[Henry Seriake Dickson]], manshi gwamna kala dan siyasa
* [[Alfred Diete-Spiff]], Manshi gwamnan Jihar Rivers, [[Style (manner of address)#Monarchies|HRM]]<ref>{{Cite web|url=http://www.waado.org/Environment/FedGovt_NigerDelta/BayelsaInvasion/IjawsReactToInvasion/DieteSpiffReflectsOnInvasion.html|title=Former Military Governor Diete-Spiff Reflects On Background Problems of the Invasion|last=Society|first=Urhobo Historical|website=www.waado.org|access-date=2018-07-30|archive-date=2018-02-19|archive-url=https://web.archive.org/web/20180219212259/http://www.waado.org/Environment/FedGovt_NigerDelta/BayelsaInvasion/IjawsReactToInvasion/DieteSpiffReflectsOnInvasion.html|url-status=dead}}</ref>
*Honourable [[Douye Diri]] an goma an siyasa kala an zartarwa lake wakiltar mazabar [[Yenagoa]]/Kolokuna/Opokuma na 'in anin majalisu.<ref>{{Cite web|title=Hon. Douye Diri biography, net worth, age, family, contact & picture|url=https://www.manpower.com.ng/people/16700/hon-douye-diri|access-date=2021-09-12|website=www.manpower.com.ng}}</ref>
*[[Tamara Eteimo]] la monantan ga sun Tamara ko Angiama, dole hukumar Ijaw Ko aushi ga Jihar Bayelsa. Anin Aru R&B ga Najeriya, Ani rubuta aru kala jaruma.<ref>{{Cite web|title=Tamara Eteimo biography, net worth, age, family, contact & picture|url=https://www.manpower.com.ng/people/15992/tamara-eteimo|access-date=2021-09-12|website=www.manpower.com.ng}}</ref>
* [[Dan Etete]] Ministan or Fetur<ref>{{Cite news|url=https://blerf.org/index.php/biography/etete-chief-dan-lauzia/|title=ETETE, Chief Dan Lauzia|date=2017-02-03|work=Biographical Legacy and Research Foundation|access-date=2018-07-30|language=en-US}}</ref>
* [[Finidi George]], an Bonfo ƙollon sheke ga Super Easgles<ref>{{Cite news|url=https://allafrica.com/stories/201003240473.html|title=Nigeria: Eagles, Black Stars Will Survive Group Stage -Finidi|date=2010-03-24|work=This Day (Lagos)|access-date=2018-07-30}}</ref>
* [[Daniel Igali]], [[Canadians|Canadian]] la watu yauta zinare ga gasa Olympic gold kala jarumin duniya in dambe<ref>{{Cite news|url=http://thenationonlineng.net/daniel-igali-obscurity-wrestling-stardom/|title=DANIEL IGALI - From obscurity to wrestling stardom - The Nation Nigeria|date=2016-07-03|work=The Nation Nigeria|access-date=2018-07-30|language=en-US}}</ref>
* [[Ernest Ikoli]], an jarida kala an fafutukar zauwa 'yanci ga lokacin mulkin mallaka.<ref>{{Cite news|url=http://thenationonlineng.net/unsung-heroes-of-independence-2/|title=Unsung heroes of independence - The Nation Nigeria|date=2015-10-02|work=The Nation Nigeria|access-date=2018-07-30|language=en-US}}</ref>
* [[Goodluck Jonathan]], manshi shugaba woli Najeriya<ref>{{Cite web|url=http://www.gej.ng/biography|title=Biography {{!}} The Office of Goodluck Ebele Jonathan|website=www.gej.ng|language=en-US|access-date=2018-07-30|archive-date=2018-07-30|archive-url=https://web.archive.org/web/20180730110431/http://www.gej.ng/biography|url-status=dead}}</ref>
*[[Heineken Lokpobiri]], Ministan Jiha gako harkokin mara<ref>{{cite web|url=https://www.legit.ng/1091118-present-nigerian-ministers-portfolios.html|title=Present Nigerian Ministers and their portfolios|author=Falae, Vivian|website=legit.ng}}</ref>
*Senator [[Ben Murray-Bruce]] la Aji wakiltar mazabar Bayelsa East Senatorial District ga majalisar Dokoki in woli. daga Akassa in Jihar Bayelsa, Nigeria.<ref>{{Cite web|title=Ben Murray-Bruce biography, net worth, age, family, contact & picture|url=https://www.manpower.com.ng/people/15496/ben-murray-bruce|access-date=2021-09-12|website=www.manpower.com.ng}}</ref>
* [[Ebikibina Ogborodi]], rijistran NECO in rikon kwarya<ref>{{Cite web|url=https://www.channelstv.com/2021/06/03/neco-appoints-ebikibina-ogborodi-as-acting-registrar|title=Ogborodi Appointed Acting NECO Registrar After Obioma's Death|last=Egba|first=Abdullahi|work=[[Channels TV]]|date=3 June 2021|accessdate=3 June 2021}}</ref>
* [[Gabriel Okara]], an rubuta littafai kala mahikayanci<ref>{{Cite news|url=https://www.britannica.com/biography/Gabriel-Okara|title=Gabriel Okara {{!}} Nigerian author|work=Encyclopedia Britannica|access-date=2018-07-30|language=en}}</ref>
* [[Melford Okilo]], gwamanan Jihar Rivers<ref>{{Cite news|url=https://www.brandcampaign.com.ng/governor-melford-okilo-discovered-olumba-olumba/|title=How Governor Melford Okilo Discovered Olumba Olumba Brotherhood - Brand Campaign|date=2016-09-14|work=Brand Campaign|access-date=2018-07-30|language=en-US|archive-url=https://web.archive.org/web/20180730110918/https://www.brandcampaign.com.ng/governor-melford-okilo-discovered-olumba-olumba/|archive-date=2018-07-30|url-status=dead}}</ref>
*[[Kemebradikumo Pondei]], managing director in rikon kwarya ga [[Niger Delta Development Commission]]
*[[Ebinabo Potts-Johnson]] layantan ga Jihar Bayelsa, 'ani tella kala 'ani Bonfo kwaikwayo.<ref>{{Cite web|title=Ebinabo Potts-Johnson biography, net worth, age, family, contact & picture|url=https://www.manpower.com.ng/people/16130/ebinabo-potts-johnson|access-date=2021-09-12|website=www.manpower.com.ng}}</ref>
* [[Samson Siasia]], an Bonfo kwallon sheke ga Eagles kala Coach<ref>{{Cite news|url=https://www.premiumtimesng.com/news/268855-268855.html|title=Bayelsa honours Samson SIasia, others|date=2018-05-18|work=Premium Times Nigeria|access-date=2018-07-30|language=en-GB}}</ref>
* [[Timipre Sylva]], manshi gwamnan Jihar Bayelsa, Ministan Najeriya an tinayi in jiha gako harkokin mor fetur.<ref>{{Cite web|url=http://www.gamji.com/article6000/news7604.htm|title=Masquerades and Jokers as Governors in Bayelsa State|website=www.gamji.com|access-date=2018-07-30}}{{Dead link|date=July 2024 |bot=InternetArchiveBot |fix-attempted=yes }}</ref>
* [[Timaya]], an aru<ref>{{Cite journal|date=2011-09-28|title=Afrotainment-Museke Online African Music Awards 2011|url=http://www.3-mob.com/?p=1870|journal=3-mob.com}}</ref>
*[[Patience Torlowei]], an tsara kwalliya kala an'aru
== Manazarta ==
{{reflist|4}}
f5b9gvbkmp43o99izzzfs4kgy02dm2n
Birtaniya
0
466
9155
8483
2026-08-22T20:55:17Z
Adamu mc
141
9155
wikitext
text/x-wiki
{{Infobox country
| conventional_long_name = United Kingdom of Great Britain and Northern Ireland
| image_flag = Flag of the United Kingdom (1-2).svg
| image_coat = Coat of arms of the United Kingdom (2022, variant 2).svg
| image_map = Europe-UK.svg
| image_map2 = United_Kingdom_(+overseas_territories_and_crown_dependencies)_in_the_World_(+Antarctica_claims).svg
| national_anthem = "[[God Save the King]]"<br>[[Fayil:United_States_Navy_Band_-_God_Save_the_Queen.ogg]]
| official_languages = [[Yarenshe Turanci]]
| capital = [[London]]
| demonym = British
| ethnic_groups = 83.1% White<br>8.6% Asian<br>3.7% Black<br>2.7% Mixed<br>2.0% other
| government =
Unitary parliamentary constitutional monarchy
| leader1 = [[Charles III]]
| leader1_type = Monarch
| leader2 = [[Keir Stammer]]
| leader2_type = Prime Minister
<!--
| sovereignty_type = Independence from the [[United Kingdom]]
| established_event1 = Proclamation
| established_date1 = 24 April 1916 1975
| established_event2 = Declaration
| established_date2 = 21 January 1919
| established_event3 = [[Anglo-Irish Treaty]]
| established_date3 = 6 December 1921
-->
| area_sq_km = 244,376 km<sup>2</sup>
| area_sq_mi = 94,354 sq mi
| area_rank = 78<sup>th</sup>
}}
[[Fayil:Uk topo en.jpg|thumb|right|250px|Taswirar Birtaniya.]]
[[Fayil:The British Empire- A survey.JPG|thumb|the British empire]]
'''Birtaniya''' do [[Birtania]]: (ga turanci British) woli ji, ga [[nahiya Turai]], Birtaniya ga godom filaye kimani kilomita Arabba'i 242,495. Birtaniya aji ga godom miyya kimani miyya 4,954,645, bisa ga jimilla kidaya in soninshe (2016). Birtaniya aji ga iyaka ga Ayilan. Siri birni Birtaniya, Landon ji, bosa sosai Birtaniya kunsan ingila weyilKala ga sultan, united kingdom (ga fainiwa moyinshe modi do moyinshe la gollaka) kunsu ingila ga weilz sukotlan Ayilan ko gudi kala ga woli Aylan.
Sarauniya Birtaniya [[Charles's]] III Birtaniya wattu yanci kafin karni in bimbadi.
== Ɗiwwa ==
k1uy9pnycjl44bdmtr78za7ny45okn7
9156
9155
2026-08-22T20:57:46Z
Adamu mc
141
9156
wikitext
text/x-wiki
{{Infobox country
| conventional_long_name = United Kingdom of Great Britain and Northern Ireland
| image_flag = Flag of the United Kingdom (1-2).svg
| image_coat = Coat of arms of the United Kingdom (2022, variant 2).svg
| image_map = Europe-UK.svg
| image_map2 = United_Kingdom_(+overseas_territories_and_crown_dependencies)_in_the_World_(+Antarctica_claims).svg
| national_anthem = "[[God Save the King]]"<br>[[Fayil:United_States_Navy_Band_-_God_Save_the_Queen.ogg]]
| official_languages = [[Yarenshe Turanci]]
| capital = [[London]]
| demonym = British
| ethnic_groups = 83.1% White<br>8.6% Asian<br>3.7% Black<br>2.7% Mixed<br>2.0% other
| government =
Unitary parliamentary constitutional monarchy
| leader1 = [[Charles III]]
| leader1_type = Monarch
| leader2 = [[Keir Stammer]]
| leader2_type = Prime Minister
<!--
| sovereignty_type = Independence from the [[United Kingdom]]
| established_event1 = Proclamation
| established_date1 = 24 April 1916 1975
| established_event2 = Declaration
| established_date2 = 21 January 1919
| established_event3 = [[Anglo-Irish Treaty]]
| established_date3 = 6 December 1921
-->
| area_sq_km = 244,376 km<sup>2</sup>
| area_sq_mi = 94,354 sq mi
| area_rank = 78<sup>th</sup>
}}
[[Fayil:Uk topo en.jpg|thumb|right|250px|Taswirar Birtaniya.]]
[[Fayil:The British Empire- A survey.JPG|thumb|the British empire]]
'''Birtaniya''' do [[Birtania]]: (ga turanci British) woli ji, ga [[nahiya Turai]], Birtaniya ga godom filaye kimani kilomita Arabba'i 242,495. Birtaniya aji ga godom miyya kimani miyya 4,954,645, bisa ga jimilla kidaya in soninshe (2016). Birtaniya aji ga iyaka ga Ayilan. Siri birni Birtaniya, Landon ji, bosa sosai Birtaniya kunsan ingila weyilKala ga sultan, united kingdom (ga fainiwa moyinshe modi do moyinshe la gollaka) kunsu ingila ga weilz sukotlan Ayilan ko gudi kala ga woli Aylan.
[[Sarauniya]] Birtaniya [[Charles's]] III Birtaniya wattu yanci kafin karni in bimbadi.
== Ɗiwwa ==
83hedsu4d09yk72tku357340nd1raax
CNN
0
475
9154
8488
2026-08-22T20:01:34Z
Abu Sadeeq77
197
9154
wikitext
text/x-wiki
{{Databox|item=Q48340}}
[[Fayil:CNN.svg|thumb|right]]
'''CNN''' (Cable News Network) Tasha watso Labar ji in woli ga woli adi hedikwatar su ga Atlanta. Jojiya Amurka. (1)(2)(3) Kafan ta koga soninshe in 1980 koga Sara la malliku kafofi watsa Labar in [[Amurka]] Ted Tumer ga Reese schonfeld ga matsayi Tasha watsa Labar in awanni 24. Ga lama foti yalla kala ga hali honsene Mallika kamfani aji wasta Labar ko Sara Manhattan warner Bros. Discover.(4) CNN itaji Tasha itashi Tasha television in fara la zalan watsa Labar in 24 kala Tasha talabijin ye in farko la zalan watsa Labar ga Amurka.(5)(6)(7)(8)(9).
Yan koga tere satumba in soni 2018, CNN Andi miyya la aji mu amala ga mate in (subscribers) ga Tashar ye miyya miliyan 90.1 ga matsayi ga matsayi anin digga dodo (Subscription) kala kashi 97.7% koga 100 aji inasu mu'amala ga Tashar Andi gaga akwati na television missu ga boninshe su) (10). MSNCB, Matsakaici anin inne 580.000 ga ka'ida koga wuni sikituwo ga 49% koga sonin la gadawo, koga sikito anin inne tsaffi goggo sadarwa (channels) .(11) Yayin la CNN ga matsayi in 14 koga jeri tashoshi watsa Labar in 2019.(12)(13) Boni television ye itu koke zonge in zaburu ji gako mataki in bawulo 7th koga mataki in ko haddo la Ishin gaboii koga siri goggo sadarwa la mate antu five Andi (Fox News ga mataki in 5 ga MSNBC ga mataki in 6. Ga soni eme in (14) kala mataki in 11 ga soni in 2021.(15).
Ga shafi ga duniya shirye-shirye CNN Aji watsani ko goggo CNN international, inko anin inne aji inneyi ga wolinshe daban ga yankuna 212:(16) Yan koga tere mayu 2019. Boni television ye mallaka Amurka ji aji takaita sun in CNN (US) Bugu ga sauwi aji watsa shirye-shirye ko dolinshe tsibirai Maddi in Caribbean kala ga Japan, Inko zalan watsa shirye-shirye ga kafa yadi labarai ga fassarar lokaci modi koga harshe Jafananci.(17).
== Ɗiwwa ==
<references/>
2ud8eagewqb6hpxxi4d5dueqdwgblo1
Peji In Siri/en
0
756
9298
8177
2026-08-23T04:49:37Z
RAPTOR7762
18
RAPTOR7762 moved page [[Peji Unsiri/en]] to [[Peji In Siri/en]] over a redirect without leaving a redirect: Misspelled title
6469
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
<div style="text-align:center;">
{{Clickable button|Special:Purge/Peji In Siri|Purge this page|class=mw-ui-progressive}}
</div>
<templatestyles src="Main page/Styles.css" />
<div style="position:relative; text-align:center; padding:3em 1em; background:#fff; overflow:hidden;">
<div style="position:absolute; top:-50px; left:0; right:0; text-align:center; opacity:0.1; z-index:0;">
[[Fayil:Wikipedia-logo-v2.svg|600px|center|class=notpageimage|link=]]
</div>
<div style="position:relative; z-index:1;">
<div style="font-variant:small-caps; font-family:'Linux Libertine','Georgia',serif;"><div style="font-size:180%;">Welcome to</div>
<div style="font-size:270%; line-height:1;">[[Wikipidiya|<span style="display: inline-block; letter-spacing: -0.35em; margin-right: 0.2em; font-family: serif;">V<span style="margin-left: -0.1em;">V</span></span>ikipedia]] in the Bole Language</div>
</div>
<div style="font-size:120%; line-height:1.2;"> Wikipedia is a free encyclopedia in the [[Harshe Bole|Bole language]] which anyone can edit.</div>
<div style="font-size:120%; line-height:1.2;"> There are currently '''{{NUMBEROFARTICLES}}''' in the Bole language.</div>
</div>
</div>
<div style="margin:10px 0px 10px 0px; -moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); -webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px rgba(0, 0, 0, 0.1); background-color:#FFFFFF;">
{| style="border-spacing: 1px; border-collapse: separate; width:100%; text-align:center; font-size:0.85em; padding:2px 3px 2px 3px;" class="hp-portalen"
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Atiimala|<span style="color:#000000;">Animals</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Annoba|<span style="color:#000000;">Disaster</span>]]
| style="background-color:#F0F4F9; border-top:5px solid; border-color:#336699; padding:3px 0.15em; width:6.6%;" | [[:Category:Fasaha|<span style="color:#000000;">Science</span>]]
| style="background-color:#F9F0F0; border-top:5px solid; border-color:#993333; padding:3px 0.15em; width:6.6%;" | [[:Category:Ilimi|<span style="color:#000000;">Education</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Lamba|<span style="color:#000000;">Number</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Miyya|<span style="color:#000000;">People</span>]]
| style="background-color:#F9F9F0; border-top:5px solid; border-color:#999933; padding:3px 0.15em; width:6.6%;" | [[:Category:Makami|<span style="color:#000000;">Weapons</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Malunwa|<span style="color:#000000;">Scholars</span>]]
| style="background-color:#F0F9F0; border-top:5px solid; border-color:#339933; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii|<span style="color:#000000;">Country</span>]]
| style="background-color:#F9F0F4; border-top:5px solid; border-color:#993366; padding:3px 0.15em; width:6.6%;" | [[:Category:Olii pewe|<span style="color:#000000;">Foreign Countries</span>]]
| style="background-color:#F0F0F9; border-top:5px solid; border-color:#333399; padding:3px 0.15em; width:6.6%;" | [[:Category:Tarihi|<span style="color:#000000;">History</span>]]
| style="background-color:#F0F9F9; border-top:5px solid; border-color:#339999; padding:3px 0.15em; width:6.6%;" | [[:Category:Goma|<span style="color:#000000;">Business</span>]]
| style="background-color:#F9F0F9; border-top:5px solid; border-color:#993399; padding:3px 0.15em; width:6.6%;" | [[:Category:Kimiyya|<span style="color:#000000;">Technology</span>]]
| style="background-color:#F4F9F0; border-top:5px solid; border-color:#669933; padding:3px 0.15em; width:6.6%;" | [[:Category:Zane|<span style="color:#000000;">Drawings</span>]]
|}
</div>
<templatestyles src="Main page/Styles.css" />
<div style="flex:1; min-width:300px; overflow:hidden; border-radius:4px; margin:8px 4px 4px 4px; box-shadow:0 0 8px rgba(0,0,0,0.15);">
<div class="image-carousel">
<ul>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[Fayil:Star-alt-icon.png|20px|link=]] Featured Article</div>
</div>
<div class="carousel-image">
[[Fayil:The City Gate of Abuja.jpg|center|class=carousel-image-wrapper|link=Nijeriya|Nijeriya]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">Nigeria (English: Nigeria): The Federal Republic of Nigeria is a country in Africa. It is located in the western part of Africa, around the Niger region. It borders Niger to the north and Chad to the northeast, and has a coastline on the Atlantic Ocean.</div>
<div class="carousel-slide-title">[[Nijeriya]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[Fayil:Paomedia small-n-flat sign-question.svg|20px|link=]] Did you know?</div>
</div>
<div class="carousel-image">
[[Fayil:Gooya mountain.jpg|center|class=carousel-image-wrapper|link=Gooya mountain]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description">The Bole people live in a town located in northern [[Nijeriya|Nigeria]], where Bole (Bòo Pikka) is their language and is widely spoken throughout the surrounding region.
</div>
<div class="carousel-slide-title">[[Potiskum]]</div>
</div>
</div>
</li>
<li>
<div style="background:#FFF; padding:5px; font-size:150%; font-family:'Arial',sans-serif; position: relative; z-index: 2;">
<div style="padding:5px 10px; color:#333333;">[[Fayil:Paomedia small-n-flat file-picture.svg|20px|link=]] Featured Picture</div>
</div>
<div class="carousel-image">
[[Fayil:Daniski Festival 04.jpg|center|class=carousel-image-wrapper|link=File:Daniski Festival 04.jpg]]
</div>
<div class="carousel-slide-content-wrapper">
<div class="carousel-slide-content">
<div class="carousel-slide-description"> Daniski Hills Annual Festival is a vibrant cultural event celebrated by the Bolewa people of the Fika Emirate in Yobe State, [[Nijeriya|Nigeria]].
</div>
<div class="carousel-slide-title">[[:File:Daniski Festival 04.jpg|Daniski Festival Picture]]</div>
</div>
</div>
</li>
</ul>
</div>
</div>
<div style="display:flex; flex-wrap:wrap;">
{{Box
|header=[[Fayil:Paomedia small-n-flat sign-info.svg|20px|link=]] What is Wikipedia?
|content=<span style="float: left; margin: 6px 12px 6px 0px; display: inline-block;">[[Fayil:Wikipedia-logo-v2.svg|80px|link=]]</span>Wikipedia is a website where people can contribute and write articles on many different topics to share knowledge and information with others. The English-language version was the first Wikipedia project and has grown into one of the largest sources of knowledge on the internet. Wikipedia is a collection of encyclopaedias in many languages of the world, created and maintained through freely written articles and voluntary contributions. Wikipedia aims to make knowledge freely available to everyone, regardless of their background, origin, or level of education.
}}
{{Box
|header=[[Fayil:Paomedia small-n-flat pencil.svg|20px|link=]] Kirkiru Foyo Article
|content=Do you know the Bole language? You can help develop this free encyclopaedia by creating new articles and expanding existing ones. Please follow the community's rules and guidelines whenever you contribute.
<div style="margin-top:1em;">
<inputbox>
type=create
width=30
default=
buttonlabel=Create article
</inputbox>
</div>
}}
</div>
<!--
{{Box
|header=[[Fayil:Ambox PR.svg|25px|link=]] Announcements
|content={{Main page announcements}}
}}
-->
{{Box
|header=[[Fayil:Wikimedia-logo.svg|20px|link=]] Project Modi
|content={{SisterProjects}}
}}
irs3rsx6g22d5s7r9f0mcbdacxgfg95
United Kingdom
0
833
9319
7189
2026-08-22T16:08:37Z
Alanscottwalker
336
/* Economy */ change to Bank Junction, the other link did not make sense
9319
wikitext
text/x-wiki
{{Short description|Country in northwestern Europe}}
{{Hatnote|"UK" redirects here. For other uses, see [[UK (disambiguation)]] and [[United Kingdom (disambiguation)]]. Not to be confused with [[England]] or [[Great Britain]].}}
{{pp-sock|small=yes}}
{{pp-move|small=yes}}
{{Use British English|date=April 2012}}
{{Use dmy dates|date=November 2025}}
{{Infobox country
| common_name = United Kingdom
| linking_name = the United Kingdom<!--Note: "the" required here as this entry used to create wikilinks-->
| conventional_long_name = United Kingdom of Great Britain and Northern Ireland
| image_flag = Flag of the United Kingdom (1-2).svg
| flag_type = [[Union Jack|Flag]]
| alt_flag = A flag composed of a red cross edged in white and superimposed on a red saltire, also edged in white, superimposed on a white saltire on a blue background
| image_coat =
| other_symbol = [[File:Coat of arms of the United Kingdom (2022, both variants).svg|250px]]<br />Used in relation to [[Scotland]] (right) and elsewhere (left)
| other_symbol_type = [[Coat of arms of the United Kingdom|Coat of arms]]:
| national_anthem = "[[God Save the King]]"{{Efn|"God Save the King" is the [[national anthem]] by custom, not statute, and there is no authorised version. Typically only the first verse is usually sung, although the second verse is also often sung as well at state and public events.<ref>{{Cite web |title=National Anthem |url=https://www.royal.uk/encyclopedia/national-anthem |access-date=10 April 2024 |website=The Royal Family |archive-date=20 May 2024 |archive-url=https://web.archive.org/web/20240520130352/https://www.royal.uk/encyclopedia/national-anthem |url-status=live}}</ref> The words ''King, he, him, his'', used at present, are replaced by ''Queen, she, her'' when the monarch is female.}}<br /><div style="display:inline-block;margin-top:0.4em;">[[File:United States Navy Band - God Save the Queen.ogg|God Save the King / Queen <!-- Do not change file name due to computer error without ensuring that the file is playable. -->]]</div>
| image_map = {{Switcher|[[File:Europe-UK (orthographic projection).svg|upright=1.15|frameless]]|Show globe|[[File:Europe-UK.svg|upright=1.15|frameless]]|Show map of Europe|[[File:United Kingdom (+overseas territories and crown dependencies) in the World (+Antarctica claims).svg|upright=1.15|frameless]]|Show [[British Overseas Territories]] and [[Crown Dependencies]]|[[File:Territorial waters - United Kingdom.svg|upright=1.15|frameless]]|Show [[Exclusive economic zone of the United Kingdom|their exclusive economic zones]]|default=1}}
| map_caption =
| capital = [[London]]
| coordinates = {{Coord|51|30|N|0|7|W|type:city(9,100,000)_region:GB-LND}}
| largest_city = capital
| languages_type = [[National language]]
| languages = [[English language|English]] <!--Note: Just English, don't add "British English".-->
| languages2_type = Regional and minority languages{{Efn|Scots, Ulster Scots, Welsh, Cornish, Scottish Gaelic and Irish are classed as [[Regional language|regional]] or [[Minority language|minority]] languages under the [[Council of Europe]]'s [[European Charter for Regional or Minority Languages]].<ref name="reglang">{{Cite web |title=List of declarations made with respect to treaty No. 148 |url=http://conventions.coe.int/treaty/Commun/ListeDeclarations.asp?CL=ENG&NT=148&VL=1 |access-date=12 December 2013 |publisher=[[Council of Europe]] |archive-date=12 December 2013 |archive-url=https://web.archive.org/web/20131212175720/http://conventions.coe.int/treaty/Commun/ListeDeclarations.asp?CL=ENG&NT=148&VL=1 |url-status=dead}}</ref> These include defined obligations to promote those languages.<ref>{{Cite web |title=Welsh language on GOV.UK – Content design: planning, writing and managing content – Guidance |url=https://www.gov.uk/guidance/content-design/welsh-language-on-gov-uk |access-date=3 August 2018 |website=gov.uk |archive-date=4 August 2018 |archive-url=https://web.archive.org/web/20180804014121/https://www.gov.uk/guidance/content-design/welsh-language-on-gov-uk |url-status=live |postscript=;}} {{Cite news |title=Welsh language scheme |work=GOV.UK |url=https://www.gov.uk/government/organisations/department-for-transport/about/welsh-language-scheme |access-date=3 August 2018 |archive-date=4 August 2018 |archive-url=https://web.archive.org/web/20180804014119/https://www.gov.uk/government/organisations/department-for-transport/about/welsh-language-scheme |url-status=live |postscript=;}} {{Cite news |title=Welsh language scheme |work=GOV.UK |url=https://www.gov.uk/government/organisations/home-office/about/welsh-language-scheme |access-date=3 August 2018 |archive-date=2 August 2018 |archive-url=https://web.archive.org/web/20180802010917/https://www.gov.uk/government/organisations/home-office/about/welsh-language-scheme |url-status=live}}</ref> See also [[Languages of the United Kingdom]]. Welsh has limited ''[[de jure]]'' official status in Wales, as well as in the provision of national government services provided for Wales.}}
| languages2 = {{Hlist
<!--Anglic-->
| [[Scots language|Scots]]
| [[Ulster Scots dialects|Ulster Scots]]
<!--Brittonic-->
| [[Welsh language|Welsh]]
| [[Cornish language|Cornish]]
<!--Goidelic-->
| [[Scottish Gaelic]]<!--Keep "Scottish Gaelic"; people will find "Gaelic" confusing, as the Irish language is also commonly called "Gaelic"-->
| [[Irish language|Irish]]
<!--BANZSL-->
| [[British Sign Language]]
}}
| ethnic_groups = {{unbulleted list
| 83.1% [[White people in the United Kingdom|White]]
| 8.6% [[British Asian|Asian]]
| 3.7% [[Black British|Black]]
| 2.7% [[Mixed (United Kingdom ethnicity category)|Mixed]]
| 2.0% [[Ethnic groups in the United Kingdom|other]]
}}
| ethnic_groups_year = 2021
| ethnic_groups_ref = {{Efn|name=UK-wide2021|Whereas the censuses of England and Wales and of Northern Ireland went ahead as planned in 2021, the census in Scotland was postponed until 2022. The Office for National Statistics reports that these UK-wide statistics "have been created to provide an image of how UK census data may have looked if the most recent UK censuses had been conducted with an aligned date of 21 March 2021".}}<ref name=Ethnicity2021>{{cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/censusbasedstatisticsuk2021|title=Table 06: UK06 - Ethnic group by sex by age, United Kingdom|work=Census-based statistics UK: 2021|publisher=Office for National Statistics|date=27 June 2025|access-date=28 March 2026}}</ref>
| religion = {{unbulleted list
| 46.6% [[Religion in the United Kingdom#Christianity|Christianity]]
| 37.6% [[Irreligion in the United Kingdom|no religion]]
| 6.0% [[Islam in the United Kingdom|Islam]]
| 1.6% [[Hinduism in the United Kingdom|Hinduism]]
| 2.2% [[Religion in the United Kingdom|other]]
| 5.9% not stated
}}
| religion_year = 2021
| religion_ref = {{Efn|name=UK-wide2021}}<ref name=Religion2021>{{cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/censusbasedstatisticsuk2021|title=Table 07: UK07 - Religion by sex by age, United Kingdom|work=Census-based statistics UK: 2021|publisher=Office for National Statistics|date=27 June 2025|access-date=28 March 2026}}</ref>
| demonym = {{hlist |[[British people|British]] |Briton |Brit (colloquial) }}
| government_type = Unitary [[Westminster parliamentary system|parliamentary constitutional monarchy]]{{Efn|Although the United Kingdom has traditionally been seen as a [[unitary state]], an alternative description of the UK as a "union state", put forward by, amongst others, [[Vernon Bogdanor]],<ref>{{Cite book |last=Bradbury |first=Jonathan |url=https://books.google.com/books?id=c3QWEAAAQBAJ&q=%2522union+state%2522+UK+unitary&pg=PA19 |title=Constitutional Policy and Territorial Politics in the UK: Volume 1: Union and Devolution 1997–2012 |date=2021 |publisher=Policy Press |isbn=978-1-5292-0588-6 |pages=19–20 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204328/https://books.google.com/books?id=c3QWEAAAQBAJ&q=%2522union+state%2522+UK+unitary&pg=PA19#v=onepage&q=%2522union%20state%2522%20UK%20unitary&f=false |url-status=live}}</ref> has become increasingly influential since the adoption of devolution in the 1990s.<ref>{{Cite book |last=Leith |first=Murray Stewart |url=https://books.google.com/books?id=PeBvAAAAQBAJ&q=Uk+%2522unitary+state%2522&pg=PA39 |title=Political Discourse and National Identity in Scotland |date=2012 |publisher=Edinburgh University Press |isbn=978-0-7486-8862-3 |page=39 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204223/https://books.google.com/books?id=PeBvAAAAQBAJ&q=Uk+%2522unitary+state%2522&pg=PA39#v=onepage&q=Uk%20%2522unitary%20state%2522&f=false |url-status=live}}</ref> A union state is considered to differ from a unitary state in that while it maintains a central authority it also recognises the authority of historic rights and infrastructures of its component parts.<ref>{{Cite book |last1=Gagnon |first1=Alain-G. |url=https://books.google.com/books?id=g0ahE2fTxS0C&q=%2522union+state%2522+UK+unitary&pg=PA47 |title=Multinational Democracies |last2=Tully |first2=James |date=2001 |publisher=Cambridge University Press |isbn=978-0-521-80473-8 |page=47 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204329/https://books.google.com/books?id=g0ahE2fTxS0C&q=%2522union+state%2522+UK+unitary&pg=PA47#v=onepage&q=%2522union%20state%2522%20UK%20unitary&f=false |url-status=live |postscript=;}} {{Cite book |last=Bogdanor |first=Vernon |title=Constitutional Reform in the United Kingdom: Practice and Principles |date=1998 |publisher=Hart Publishing |isbn=978-1-901362-84-8 |editor-last=Beatson |editor-first=Jack |location=Oxford |page=18 |chapter=Devolution: the Constitutional Aspects |chapter-url=https://books.google.com/books?id=YEEgDsCYmbQC&q=%2522union+state%2522+UK+unitary&pg=PA18}}</ref>}}
| leader_title1 = [[Monarchy of the United Kingdom|Monarch]]
| leader_name1 = [[Charles III]]
| leader_title2 = [[Prime Minister of the United Kingdom|Prime Minister]]
| leader_name2 = [[Andy Burnham]]
| legislature = [[Parliament of the United Kingdom|Parliament]]
| upper_house = [[House of Lords]]
| lower_house = [[House of Commons of the United Kingdom|House of Commons]]
| sovereignty_type = [[Formation of the United Kingdom of Great Britain and Northern Ireland|Formation]]
| established_event1 = [[Laws in Wales Acts 1535 and 1542|Laws in Wales Acts]]
| established_date1 = 1535 and 1542
| established_event2 = [[Union of the Crowns]]
| established_date2 = 24 March 1603
| established_event3 = [[Treaty of Union]]
| established_date3 = 22 July 1706
| established_event4 = [[Acts of Union 1707|Acts of Union of England and Scotland]]
| established_date4 = 1 May 1707
| established_event5 = [[Acts of Union 1800|Acts of Union of Great Britain and Ireland]]
| established_date5 = 1 January 1801
| established_event6 = [[Irish Free State Constitution Act 1922|Irish Free State Constitution Act]]
| established_date6 = 6 December 1922
| area_label = Total{{efn|name=ONSArea|[[Office for National Statistics|ONS]] Standard Area Measurement, 'area to mean high water'. Excludes the [[Crown Dependencies]] and [[British Overseas Territories]].}}
| area_km2 = 244376
| area_footnote = <ref name="ONS Standard Area Measurement">{{cite web |url=https://geoportal.statistics.gov.uk/datasets/ons::standard-area-measurements-for-administrative-areas-december-2023-in-the-uk/about |title=Standard Area Measurements for Administrative Areas (December 2023) in the UK |author=<!--Not stated--> |date=31 May 2024 |website=[[ONS Open Geography Portal|Open Geography Portal]] |publisher=Office for National Statistics |access-date=7 June 2024 |archive-date=7 June 2024 |archive-url=https://web.archive.org/web/20240607052407/https://geoportal.statistics.gov.uk/datasets/ons::standard-area-measurements-for-administrative-areas-december-2023-in-the-uk/about |url-status=live}}</ref>
| area_rank = 78th
| area_sq_mi = auto
| area_label2 = Land{{efn|name=ONSLandArea|[[Office for National Statistics|ONS]] Standard Area Measurement, "area to mean high water excluding inland water". Excludes the [[Crown Dependencies]] and [[British Overseas Territories]].}}
| area_data2 = {{convert|{{UK subdivision area|GSS=K02000001}}|km2|sqmi|abbr=on}}<ref name="ONS mid-year pop est" />
| percent_water =
| population_estimate = {{IncreaseNeutral}} {{UK subdivision population|GSS=K02000001}}<ref name="ONS mid-year pop est">{{UK subdivision statistics citation}}</ref>
| population_estimate_year = {{UK subdivision statistics year}}
| population_estimate_rank = 20th
| population_census = {{IncreaseNeutral}} 66,912,637{{Efn|name=UK-wide2021}}<ref name=Ethnicity2021/>
| population_census_year = 2021
| population_census_rank =
| population_density_km2 = {{UK subdivision density|GSS=K02000001}}
| population_density_sq_mi = auto
| population_density_rank = 48th
| pop_den_footnote = <ref name="ONS mid-year pop est" />
| GDP_PPP = {{increase}} $4.721 trillion<ref name="IMFWEO.UK">{{cite web |url=https://data.imf.org/en/Data-Explorer?datasetUrn=IMF.RES:WEO(9.0.0) |title=World Economic Outlook Database (April 2026 Edition) |publisher=[[International Monetary Fund]] |website=www.imf.org |date=14 April 2026 |access-date=18 April 2026}}</ref>
| GDP_PPP_year = 2026
| GDP_PPP_rank = 10th
| GDP_PPP_per_capita = {{increase}} $67,585<ref name="IMFWEO.UK" />
| GDP_PPP_per_capita_rank = 33rd
| GDP_nominal = {{increase}} $4.265 trillion<ref name="IMFWEO.UK" />
| GDP_nominal_year = 2026
| GDP_nominal_rank = 5th
| GDP_nominal_per_capita = {{increase}} $61,056<ref name="IMFWEO.UK" />
| GDP_nominal_per_capita_rank = 21st
| Gini = 35.4
| Gini_year = 2021
| Gini_change = decrease
| Gini_ref = <ref>{{Cite web |title=Income inequality |url=https://data.oecd.org/inequality/income-inequality.htm |access-date=12 February 2024 |website=OECD Data |publisher=[[OECD]] |archive-date=1 July 2022 |archive-url=https://web.archive.org/web/20220701171540/https://data.oecd.org/inequality/income-inequality.htm |url-status=live}}</ref>
| HDI = 0.946<!--number only-->
| HDI_year = 2023<!-- Please use the year to which the data refers, not the publication year.-->
| HDI_change = increase<!--increase/decrease/steady-->
| HDI_ref = <ref name="UNHDR">{{Cite web |date=6 May 2025 |title=Human Development Report 2025 |url=https://hdr.undp.org/system/files/documents/global-report-document/hdr2025reporten.pdf |url-status=live |archive-url=https://web.archive.org/web/20250506051232/https://hdr.undp.org/system/files/documents/global-report-document/hdr2025reporten.pdf |archive-date=6 May 2025 |access-date=6 May 2025 |publisher=[[United Nations Development Programme]] |language=en}}</ref>
| HDI_rank = 13th
| currency = [[Pound sterling|Sterling]]<!--The currency is simply called 'sterling' (see its article); originally, the penny (not the pound) was the primary unit. Internationally it is known as 'pound sterling' so the familiar unit is mentioned.-->{{Efn|Commonly also known as the "pound" (the name of [[pound (currency)|its base unit]]) or "pound sterling". Some of the devolved countries, [[Crown Dependency|Crown Dependencies]] and [[British Overseas Territory|British Overseas Territories]] issue their own sterling banknotes or currencies, or use another nation's currency. See [[List of British currencies]].}} ([[£]])
| currency_code = GBP
| utc_offset = +0
| time_zone = [[Greenwich Mean Time|GMT]]
| utc_offset_DST = +1
| time_zone_DST = [[British Summer Time|BST]]{{Efn|Also observed by the [[Crown Dependencies]]. For further information, see [[Time in the United Kingdom]].}}
| DST_note =
| date_format = {{Abbr|dd|day}}/{{Abbr|mm|month}}/{{Abbr|yyyy|year}} ([[Anno Domini|AD]]){{efn|The UK Government uses the [[ISO 8601]] format, {{Abbr|yyyy|year}}-{{Abbr|mm|month}}-{{Abbr|dd|day}}, for machine-readable dates and times.<ref>{{cite web |title=Formatting dates and times in data |url=https://www.gov.uk/government/publications/open-standards-for-government/date-times-and-time-stamps-standard |date=9 August 2022 |website=[[gov.uk]] |publisher=[[Government of the United Kingdom|HM Government]] |access-date=1 June 2024 |archive-date=9 May 2024 |archive-url=https://web.archive.org/web/20240509092813/https://www.gov.uk/government/publications/open-standards-for-government/date-times-and-time-stamps-standard |url-status=live}}</ref> See [[Date and time notation in the United Kingdom]].}}
| calling_code = [[Telephone numbers in the United Kingdom|+44]]{{Efn|Excludes most overseas territories. See [[Telephone numbers in the United Kingdom#Telephone numbers in Overseas Territories]].}}
| cctld = [[.uk]]{{Efn|The [[.gb]] domain is also reserved for the UK, but has been little used.}}
}}
The '''United Kingdom of Great Britain and Northern Ireland''', commonly known as the '''United Kingdom''' ('''UK''') or '''Britain''',<!--DO NOT CHANGE ORDER OF INTRO WITHOUT CONSENSUS-->{{Efn|Usage is mixed. ''[[The Guardian]]''<ref>{{Cite news |date=2021-04-23 |title=Guardian style guide: U |url=https://www.theguardian.com/guardian-style-guide-u |access-date=2025-12-29 |work=The Guardian |language=en-GB |issn=0261-3077}}</ref> and ''[[The Daily Telegraph|The Telegraph]]''<ref>{{Cite news |date=2025-07-25 |title=Places |url=https://www.telegraph.co.uk/style-book/places/ |access-date=2025-12-29 |work=The Telegraph |language=en-GB |issn=0307-1235 |archive-date=17 November 2025 |archive-url=https://web.archive.org/web/20251117111222/https://www.telegraph.co.uk/style-book/places/ |url-status=live }}</ref> use ''Britain'' as a synonym for the United Kingdom. The British [[Cabinet Office]]'s [[Government Digital Service]] style guide<ref>{{Cite web |title=Style guide - A to Z - Guidance - GOV.UK |url=https://www.gov.uk/guidance/style-guide/a-to-z#great-britain |access-date=2026-01-02 |website=www.gov.uk |language=en |archive-date=22 November 2024 |archive-url=https://web.archive.org/web/20241122222025/https://www.gov.uk/guidance/style-guide/a-to-z#great-britain |url-status=live }}</ref> for use on [[gov.uk]] recommends: "Use UK and United Kingdom in preference to Britain and British (UK business, UK foreign policy, ambassador and high commissioner). But British embassy, not UK embassy."}} is a country<!-- The term "country" was chosen as a result of a 2022 Request for Comment. Discuss potential changes on the talk page first. --> in [[northwestern Europe]], off the coast of [[European mainland|the continental mainland]]. It comprises [[England]], [[Scotland]], [[Wales]] and [[Northern Ireland]],{{efn|The [[Isle of Man]], [[Bailiwick of Guernsey|Guernsey]] and [[Jersey]] are [[Crown Dependencies]] and not part of the UK.}} with a population of over 69 million in 2024. The UK includes the island of [[Great Britain]], the north-eastern part of the island of [[Ireland]], and most of [[List of islands of the United Kingdom|the smaller islands]] within the [[British Isles]], covering {{Convert|244376|km2|sqmi|order=flip}}.{{efn|name=ONSArea}} It shares [[Republic of Ireland–United Kingdom border|a land border]] with the [[Republic of Ireland]] and is surrounded by the [[Atlantic Ocean]], the [[North Sea]], the [[English Channel]], the [[Celtic Sea]] and the [[Irish Sea]], while maintaining sovereignty over the [[Crown Dependencies]] and the [[British Overseas Territories]]. The capital and largest city of England and the UK is [[London]]; [[Edinburgh]], [[Cardiff]] and [[Belfast]] are the national capitals of Scotland, Wales and Northern Ireland, respectively.
The British Isles have been continuously inhabited since the [[Neolithic]]. In AD 43 the [[Roman conquest of Britain]] began. The [[end of Roman rule in Britain|Roman departure]] between 383 and 410 was followed by [[Anglo-Saxon settlement of Britain|Anglo-Saxon settlement]] beginning around 450. In 1066 the [[Norman Conquest|Normans conquered England]]. Over the 17th century the role of the [[British monarchy]] was reduced, particularly as a result of the [[English Civil War]]. In 1707 the Kingdom of England and the [[Kingdom of Scotland]] united under the [[Treaty of Union]] to create the [[Kingdom of Great Britain]]. The [[Acts of Union 1800]] incorporated the [[Kingdom of Ireland]] to create the [[United Kingdom of Great Britain and Ireland]] in 1801. Most of Ireland [[Partition of Ireland|seceded]] from the UK in 1922 as the [[Irish Free State]], and the [[Royal and Parliamentary Titles Act 1927]] created the present United Kingdom.
The UK [[History of industrialisation#Industrial Revolution in Europe|became the first industrialised country]] and was the world's [[foremost power]] for the majority of the 19th and early 20th centuries, particularly during the ''[[Pax Britannica]]'' between 1815 and 1914. The [[British Empire]] was the leading [[economic power]] for most of the 19th century, a position supported by [[British Agricultural Revolution|its agricultural prosperity]], its role as a dominant [[trading nation]], a massive industrial capacity, [[List of British innovations and discoveries in the 19th century|significant technological achievements]], and the rise of [[19th-century London]] as the world's principal financial centre. At its height in the 1920s, the empire encompassed around a quarter of the world's landmass and population, and was the [[List of largest empires#Empires at their greatest extent|largest in history]]. However, [[History of the United Kingdom during the First World War|its involvement in the First World War]] and [[Military history of the United Kingdom during World War II|in the Second World War]] damaged [[Economy of the British Empire|Britain's economic power]], and a global wave of [[decolonisation]] led to the independence of most British colonies.
The UK is a [[constitutional monarchy]] and [[parliamentary democracy]]{{Efn|The United Kingdom does not have a codified constitution but an unwritten one formed of Acts of Parliament, court judgments, traditions, and conventions.<ref>{{Citation |title=What is the UK Constitution? |date=9 August 2018 |url=https://www.ucl.ac.uk/constitution-unit/what-uk-constitution/what-uk-constitution |publisher=The Constitution Unit of UCL |access-date=6 February 2020 |archive-date=7 November 2018 |archive-url=https://web.archive.org/web/20181107060057/http://www.ucl.ac.uk/constitution-unit/whatis/uk-constitution |url-status=live}}</ref>}} with three distinct jurisdictions: [[English law|England and Wales]], [[Scots law|Scotland]], and [[Law of Northern Ireland|Northern Ireland]]. Scotland, Wales and Northern Ireland have their own governments and parliaments which control various [[Devolution in the United Kingdom|devolved]] matters. A [[developed country]] with [[Economy of the United Kingdom|an advanced economy]], the UK ranks amongst the [[List of countries by GDP (nominal)|largest economies by nominal GDP]] and is one of the world's [[List of countries by exports|largest exporters]] and [[List of countries by imports|importers]]. As a [[nuclear state]] with one of the [[List of countries by military expenditures|highest defence budgets]], the UK maintains [[British Armed Forces|one of the strongest militaries in Europe]]. [[Culture of the United Kingdom|British culture]] is globally influential, notably in the [[Anglosphere]] and [[Commonwealth of Nations|the Commonwealth]]; [[Anglicisation|its soft power influence]] is observable in the legal and political systems of many [[List of countries that have gained independence from the United Kingdom|former colonies]], and in its exports [[English-speaking world|of language]], [[British literature|literature]], [[Theatre of the United Kingdom|theatre]], [[Cinema of the United Kingdom|cinema]], [[Music of the United Kingdom|music]], [[Mass media in the United Kingdom|media]], [[Art of the United Kingdom|art]] and [[Sport in the United Kingdom|sport]]. A [[great power]], the UK is part of [[Foreign relations of the United Kingdom#International organisations|numerous international organisations]].
== Etymology and terminology ==
{{Anchor|Etymology}}<!--linked-->
{{See also|Britain (place name)|Terminology of the British Isles}}
The [[Acts of Union 1707]] declared that the [[Kingdom of England]] and the [[Kingdom of Scotland]] were "United into One Kingdom by the Name of Great Britain".{{Efn|Compare to section 1 of both of the 1800 [[Acts of Union (1800)|Acts of Union]] which reads: "the kingdoms of Great Britain and Ireland shall{{spaces}}... be united into one kingdom, by the name of the United Kingdom of Great Britain and Ireland".}}<ref name="Acts of Union 1707">{{Cite web |title=The Treaty (act) of the Union of Parliament 1706 |url=http://www.scotshistoryonline.co.uk/union.html |archive-url=https://web.archive.org/web/20190527074630/http://www.scotshistoryonline.co.uk/union.html |archive-date=27 May 2019 |access-date=23 August 2011 |publisher=Scots History Online |postscript=;}} {{Cite book |last1=Barnett, Hilaire |url=https://books.google.com/books?id=LYc1tSYonrQC&pg=PA165 |title=Constitutional & Administrative Law |last2=Jago, Robert |publisher=Routledge |year=2011 |isbn=978-0-415-56301-7 |edition=8th |location=Abingdon |page=165 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140722/https://books.google.com/books?id=LYc1tSYonrQC&pg=PA165 |url-status=live}}</ref> The term "United Kingdom" has occasionally been used for the former [[Kingdom of Great Britain]], although its official name from 1707 to 1800 was simply "Great Britain".<ref>"After the political union of England and Scotland in 1707, the nation's official name became 'Great Britain{{'"}}, ''The American Pageant, Volume 1'', Cengage Learning (2012); "From 1707 until 1801 ''Great Britain'' was the official designation of the kingdoms of England and Scotland". ''The Standard Reference Work: For the Home, School and Library, Volume 3'', Harold Melvin Stanford (1921); "In 1707, on the union with Scotland, 'Great Britain' became the official name of the British Kingdom, and so continued until the union with Ireland in 1801". ''United States Congressional serial set, Issue 10; Issue 3265'' (1895); {{Cite web |last=Gascoigne, Bamber |author-link=Bamber Gascoigne |title=History of Great Britain (from 1707) |url=http://www.historyworld.net/wrldhis/PlainTextHistories.asp?historyid=ab07 |access-date=18 July 2011 |publisher=History World |archive-date=27 May 2019 |archive-url=https://web.archive.org/web/20190527205230/http://www.historyworld.net/wrldhis/PlainTextHistories.asp?historyid=ab07 |url-status=live}}</ref> The [[Acts of Union 1800]] formed the [[United Kingdom of Great Britain and Ireland]]. Following the [[partition of Ireland]] and the independence of the [[Irish Free State]] in 1922, which left [[Northern Ireland]] as the only part of the island of Ireland within the United Kingdom, the name was changed in 1927 to the "United Kingdom of Great Britain and Northern Ireland".<ref>{{Cite book |last=Cottrell, P. |url=https://archive.org/details/irishcivilwar00cott_573 |title=The Irish Civil War 1922–23 |year=2008 |isbn=978-1-84603-270-7 |page=[https://archive.org/details/irishcivilwar00cott_573/page/n85 85] |publisher=Bloomsbury USA |url-access=limited}}</ref>
Although the United Kingdom is a sovereign country, England, Scotland, Wales and Northern Ireland are widely referred to as [[Countries of the United Kingdom|countries]].<ref>{{Citation |last1=S. Dunn |title=An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict |year=2000 |place=[[Lewiston, New York]] |publisher=[[Edwin Mellen Press]] |quote=One specific problem – in both general and particular senses – is to know what to call Northern Ireland itself: in the general sense, it is not a country, or a province, or a state – although some refer to it contemptuously as a statelet: the least controversial word appears to be jurisdiction, but this might change. |last2=H. Dawson |postscript=;}} {{Cite web |date=15 December 2011 |title=Changes in the list of subdivision names and code elements |url=http://www.iso.org/iso/iso_3166-2_newsletter_ii-3_2011-12-13.pdf |access-date=28 May 2012 |website=ISO 3166-2 |publisher=International Organization for Standardization |archive-date=19 September 2016 |archive-url=https://web.archive.org/web/20160919073956/http://www.iso.org/iso/iso_3166-2_newsletter_ii-3_2011-12-13.pdf |url-status=live}}</ref> The UK Prime Minister's website has used the phrase "countries within a country" to describe it.<ref name="page823">{{Cite web |date=10 January 2003 |title=Countries within a country |url=http://www.number10.gov.uk/Page823 |archive-url=http://webarchive.nationalarchives.gov.uk/20080909013512/http://www.number10.gov.uk/Page823 |archive-date=9 September 2008 |access-date=8 March 2015 |publisher=Prime Minister's Office}}</ref> Some statistical summaries, such as those for the twelve [[NUTS of the United Kingdom|NUTS 1 regions]], refer to Scotland, Wales and Northern Ireland as "regions".<ref>{{Cite web |title=Statistical bulletin: Regional Labour Market Statistics |url=http://www.ons.gov.uk/ons/dcp171778_346117.xml |archive-url=https://web.archive.org/web/20141224045523/http://www.ons.gov.uk/ons/dcp171778_346117.xml |archive-date=24 December 2014 |access-date=5 March 2014 |postscript=;}} {{Cite web |title=13.4% Fall In Earnings Value During Recession |url=http://www.gmb.org.uk/newsroom/fall-in-earnings-value-during-recession |archive-url=https://web.archive.org/web/20140103194604/http://www.gmb.org.uk/newsroom/fall-in-earnings-value-during-recession |archive-date=3 January 2014 |access-date=5 March 2014}}</ref> Northern Ireland is also referred to as a "province".<ref>{{Cite book |last1=Dunn, Seamus |title=An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict |last2=Dawson, Helen |publisher=[[Edwin Mellen Press]] |year=2000 |isbn=978-0-7734-7711-7 |location=[[Lewiston, New York]] |postscript=;}} {{Cite book |last=Murphy, Dervla |title=[[A Place Apart (Murphy book)|A Place Apart]] |publisher=Penguin |year=1979 |isbn=978-0-14-005030-1 |location=London}}</ref> With regard to Northern Ireland, the descriptive name used "can be controversial, with the choice often revealing one's political preferences".<ref>{{Cite book |last1=Whyte |first1=John |title=Interpreting Northern Ireland |last2=FitzGerald |first2=Garret |publisher=Clarendon Press |year=1991 |isbn=978-0-19-827380-6 |location=Oxford |author-link=John Henry Whyte |author-link2=Garret FitzGerald}}</ref>
The term "Great Britain" conventionally refers to the island of Great Britain, or politically to England, Scotland and Wales in combination.<ref>{{Cite news |date=19 December 2008 |title=Guardian Unlimited Style Guide |publisher=Guardian News and Media Limited |location=London |url=https://www.theguardian.com/styleguide/page/0,,184840,00.html |access-date=23 August 2011 |postscript=;}} {{Cite news |date=19 August 2002 |title=BBC style guide (Great Britain) |work=BBC News |url=http://news.bbc.co.uk/1/hi/programmes/radio_newsroom/1099593.stm#g |access-date=23 August 2011 |archive-date=15 February 2009 |archive-url=https://web.archive.org/web/20090215074832/http://news.bbc.co.uk/1/hi/programmes/radio_newsroom/1099593.stm#g |url-status=live |postscript=;}} {{Cite web |title=Key facts about the United Kingdom |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |archive-url=http://webarchive.nationalarchives.gov.uk/20121015000000/http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |archive-date=15 October 2012 |access-date=8 March 2015 |website=Government, citizens and rights |publisher=HM Government}}</ref> It is sometimes used as a loose synonym for the United Kingdom as a whole.<ref>[[New Oxford American Dictionary]]: "Great Britain: England, Wales, and Scotland considered as a unit. The name is also often used loosely to refer to the United Kingdom."</ref> The word ''England'' is occasionally used incorrectly to refer to the United Kingdom as a whole, a mistake principally made by people from outside the UK.<ref>"When people say England, they sometimes mean Great Britain, sometimes the United Kingdom, sometimes the British Isles — but never England." — {{Citation |last=George Mikes |title=How To Be An Alien |year=1946 |publisher=Penguin}} {{ISBN|978-0-582-41686-4|postscript=;}} {{Cite web |title=England OR United Kingdom (UK)? {{!}} Vocabulary {{!}} EnglishClub |url=https://www.englishclub.com/vocabulary/cw-uk-england.htm |access-date=16 October 2022 |website=englishclub.com |archive-date=16 October 2022 |archive-url=https://web.archive.org/web/20221016192638/https://www.englishclub.com/vocabulary/cw-uk-england.htm |url-status=live}}</ref>
The term "Britain" is used as a synonym for [[Great Britain]],<ref>{{Cite web |title=Britain Meaning in the Cambridge English Dictionary |url=https://dictionary.cambridge.org/dictionary/english/britain |website=dictionary.cambridge.org |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024348/https://dictionary.cambridge.org/dictionary/english/britain |url-status=live |postscript=;}} {{Cite web |title=Definition of Britain in English by Oxford Dictionaries |url=https://en.oxforddictionaries.com/definition/britain |archive-url=https://web.archive.org/web/20160926204707/https://en.oxforddictionaries.com/definition/britain |archive-date=26 September 2016 |website=Oxford Dictionaries – English}}</ref><ref name="Britain-Col">{{Cite web |title=Britain definition and meaning |url=https://www.collinsdictionary.com/dictionary/english/britain |website=collinsdictionary.com |publisher=Collins English Dictionary |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024837/https://www.collinsdictionary.com/dictionary/english/britain |url-status=live}}</ref> but also sometimes for the United Kingdom.<ref>{{Cite web |title=Britain – Definition for English-Language Learners |url=http://learnersdictionary.com/definition/Britain |website=learnersdictionary.com |publisher=Merriam-Webster's Learner's Dictionary |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024648/http://learnersdictionary.com/definition/Britain |url-status=live}}</ref><ref name="Britain-Col" /> Usage is mixed: the [[style guide]] of the [[Government of the United Kingdom|UK Government]] prefers the term "UK" rather than "Britain" or "British" (except when referring to embassies{{Efn|"UK" embassies became "British" embassies in 1961.<ref>{{Cite news |date=21 October 1961 |title='Cold U.K.' Becomes British |work=[[The Times]] |page=8}}</ref>}}),<ref>{{Cite web |date=21 November 2024 |orig-date=23 February 2016 |title=Style guide: A to Z |url=https://www.gov.uk/guidance/style-guide/a-to-z |url-status=live |archive-url=https://web.archive.org/web/20241122222025/https://www.gov.uk/guidance/style-guide/a-to-z |archive-date=22 November 2024 |publisher=UK Government}}</ref> while other government documents acknowledge that both terms refer to the United Kingdom and that elsewhere "British government" is used at least as frequently as "United Kingdom government".<ref name="PCGN-uk-guide">{{Cite web |last=Permanent Committee on Geographical Names |title=Toponymic guidelines for the United Kingdom |url=https://www.gov.uk/government/publications/toponymic-guidelines |website=gov.uk |date=17 May 2023 |publisher=UK Government |access-date=17 June 2018 |archive-date=17 June 2018 |archive-url=https://web.archive.org/web/20180617165832/https://www.gov.uk/government/publications/toponymic-guidelines |url-status=live}}</ref> The UK [[Permanent Committee on Geographical Names for British Official Use|Permanent Committee on Geographical Names]] recognises "United Kingdom", "UK" and "U.K." as shortened and abbreviated geopolitical terms for the United Kingdom of Great Britain and Northern Ireland in its toponymic guidelines; it does not list "Britain" but notes that "it is only the one specific nominal term 'Great Britain' which invariably excludes Northern Ireland".<ref name="PCGN-uk-guide" /> The [[BBC]] historically preferred to use "Britain" as shorthand only for Great Britain, though the present style guide does not take a position except that "Great Britain" excludes Northern Ireland.<ref>{{Cite web |title=BBC News style guide – Names |url=https://www.bbc.co.uk/academy/en/articles/art20130702112133537 |archive-url=https://web.archive.org/web/20191110082858/https://www.bbc.co.uk/academy/en/articles/art20130702112133537 |archive-date=10 November 2019 |access-date=9 November 2019 |website=BBC Academy |publisher=BBC |postscript=;}} {{Cite web |title=Alphabetical checklist |url=https://www.bbc.co.uk/academy/journalism/news-style-guide/article/art20130702112133551 |archive-url=https://web.archive.org/web/20180326162901/http://www.bbc.co.uk/academy/journalism/news-style-guide/article/art20130702112133551 |archive-date=26 March 2018 |access-date=17 June 2018 |website=BBC News |publisher=BBC}}</ref>
The adjective "British" is commonly used to refer to matters relating to the United Kingdom and is used in law to refer to United Kingdom citizenship and [[British nationality law|nationality]].<ref>{{Cite book |last1=Bradley, Anthony Wilfred |url=https://books.google.com/books?id=HT_GS2zgN5QC&pg=PA36 |title=Constitutional and administrative law |last2=Ewing, Keith D. |publisher=Pearson Longman |year=2007 |isbn=978-1-4058-1207-8 |edition=14th |volume=1 |location=Harlow |page=36 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140723/https://books.google.com/books?id=HT_GS2zgN5QC&pg=PA36 |url-status=live}}</ref>{{Efn|Historically, the term ''British'' was used to refer to members and institutions within the British Empire and later Commonwealth and was not limited to the geographical British Isles. The UK Government adopted the term for its exclusive use only in 1961, but in recognition of its wider usage first sought the prior consent of Australia, Canada and New Zealand.<ref>{{Cite book |last1=Curran |first1=James |title=The Unknown Nation: Australia after Empire |last2=Ward |first2=Stuart |date=2010 |publisher=Melbourne University Publishing |isbn=978-0-522-85645-3 |location=Carlton, Vic |pages=26–7}}</ref><ref>{{Cite book |last=Ward |first=Stuart |title=Untied kingdom: A Global History of the End of Britain |date=2023 |publisher=Cambridge University Press |isbn=978-1-107-14599-3 |at=Chapter 1}}</ref>}} People of the United Kingdom use several different terms to describe their national identity and may identify themselves as being [[British people|British]], [[English people|English]], [[Scottish people|Scottish]], [[Welsh people|Welsh]], [[People of Northern Ireland|Northern Irish]] or [[Irish people|Irish]];<ref>{{Cite web |year=2010 |title=Which of these best describes the way you think of yourself? |url=http://www.ark.ac.uk/nilt/2010/Community_Relations/NINATID.html |access-date=1 July 2010 |website=Northern Ireland Life and Times Survey 2010 |publisher=ARK – Access Research Knowledge |archive-date=23 September 2015 |archive-url=https://web.archive.org/web/20150923175111/http://www.ark.ac.uk/nilt/2010/Community_Relations/NINATID.html |url-status=live}}</ref> or as having a combination of different national identities.<ref>{{Cite web |title=Ethnicity and National Identity in England and Wales |url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/ethnicity/articles/ethnicityandnationalidentityinenglandandwales/2012-12-11 |access-date=25 June 2020 |website=Office for National Statistics |archive-date=21 January 2022 |archive-url=https://web.archive.org/web/20220121012603/https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/ethnicity/articles/ethnicityandnationalidentityinenglandandwales/2012-12-11 |url-status=live |postscript=;}} {{Cite book |last=Schrijver, Frans |url=https://books.google.com/books?id=u8gZklxHTMUC&pg=PA275 |title=Regionalism after regionalisation: Spain, France and the United Kingdom |publisher=Amsterdam University Press |year=2006 |isbn=978-90-5629-428-1 |pages=275–277 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140905/https://books.google.com/books?id=u8gZklxHTMUC&pg=PA275#v=onepage&q&f=false |url-status=live}}</ref>
== History ==
{{Main|Formation of the United Kingdom of Great Britain and Northern Ireland|History of the British Isles}}
{{Further|History of the constitution of the United Kingdom|Timeline of British history}}
=== Prior to the Treaty of Union ===
{{Main|History of England|History of Wales|History of Scotland|History of Ireland}}
{{further|Kingdom of England|Kingdom of Scotland}}
[[File:Stonehenge2007 07 30.jpg|thumb|[[Stonehenge]] in [[Wiltshire]] is a ring of stones, each about {{Cvt|13|ft|0|order=flip}} high, {{Cvt|7|ft|0|order=flip}} wide and 25 [[tonne]]s, erected 2400–2200 BC.]]
Settlement by [[Cro-Magnon]]s of what is now the United Kingdom occurred in waves beginning by about 30,000 years ago.<ref>[http://news.bbc.co.uk/1/hi/wales/south_west/7069001.stm "Ancient skeleton was 'even older'] {{Webarchive|url=https://web.archive.org/web/20210213081240/http://news.bbc.co.uk/2/hi/uk_news/wales/south_west/7069001.stm |date=13 February 2021}}". [[BBC News]]. 30 October 2007. Retrieved 27 April 2011.</ref> The island has been continuously inhabited since the last retreat of ice around 11,500 years ago.<ref>{{Cite web |date=9 February 2018 |title=A 12,000-year story - revealing the history of settlers in Britain from the end of the Ice Age to the present day {{!}} University of Oxford |url=https://www.ox.ac.uk/news/2018-02-09-12000-year-story-revealing-history-settlers-britain-end-ice-age-present-day |access-date=6 July 2025 |website=ox.ac.uk |language=en }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref> By the end of the [[Prehistoric Britain|region's prehistoric period]], the population is thought to have belonged largely to a culture termed [[Insular Celts|Insular Celtic]], comprising [[Britons (historical)|Brittonic Britain]] and [[Gaelic Ireland]].<ref>{{Cite book |last=Koch, John T. |url=https://archive.org/details/celticculturehis00koch_128 |title=Celtic culture: A historical encyclopedia |publisher=ABC-CLIO |year=2006 |isbn=978-1-85109-440-0 |location=Santa Barbara, CA |page=[https://archive.org/details/celticculturehis00koch_128/page/n1016 973] |url-access=limited}}</ref>
The [[Roman conquest of Britain|Roman conquest]], beginning in AD 43, and the 400-year [[Roman Britain|rule of southern Britain]], was followed by an invasion by [[Germanic peoples|Germanic]] [[Anglo-Saxon]] settlers, reducing the Brittonic area mainly [[Wales#Post-Roman era|to what was to become Wales]], [[Cornwall]] and, until the latter stages of the Anglo-Saxon settlement, the [[Hen Ogledd]] (northern England and parts of southern Scotland).<ref>{{Cite book |title=[[Encyclopaedia of Wales|The Welsh Academy Encyclopaedia of Wales]] |publisher=University of Wales Press |year=2008 |isbn=978-0-7083-1953-6 |editor-last=Davies |editor-first=John |editor-link=John Davies (historian) |location=Cardiff |page=915 |editor-last2=Jenkins |editor-first2=Nigel |editor-link2=Nigel Jenkins |editor-last3=Baines |editor-first3=Menna |editor-last4=Lynch |editor-first4=Peredur I. |editor-link4=Peredur Lynch}}</ref> Most of the [[Anglo-Saxon England|region settled by the Anglo-Saxons]] became unified as the Kingdom of England in the 10th century.<ref>{{Cite magazine |title=Short Athelstan biography |url=https://www.bbc.co.uk/history/historic_figures/athelstan.shtml |magazine=BBC History |access-date=9 April 2013 |archive-date=13 February 2007 |archive-url=https://web.archive.org/web/20070213191353/http://www.bbc.co.uk/history/historic_figures/athelstan.shtml |url-status=live}}</ref> [[Dál Riata|Gaelic speakers in north-west Britain]] (with connections to the north-east of Ireland and traditionally supposed to have migrated from there in the 5th century)<ref>{{Cite book |last=Mackie, J.D. |url=https://archive.org/details/historyofscotlan00mack_0/page/18 |title=A History of Scotland |publisher=Penguin |year=1991 |isbn=978-0-14-013649-4 |location=London |pages=[https://archive.org/details/historyofscotlan00mack_0/page/18 18–19] |author-link=J.D. Mackie |postscript=;}} {{Cite book |last=Campbell |first=Ewan |title=Saints and Sea-kings: The First Kingdom of the Scots |publisher=Canongate |year=1999 |isbn=978-0-86241-874-8 |location=Edinburgh |pages=8–15}}</ref> united with the [[Picts]] to create the [[Kingdom of Scotland]] in the 9th century.<ref>{{Cite book |last=Haigh |first=Christopher |url=https://archive.org/details/cambridgehistori0000unse_a9n8/page/30 |title=The Cambridge Historical Encyclopedia of Great Britain and Ireland |publisher=Cambridge University Press |year=1990 |isbn=978-0-521-39552-6 |page=[https://archive.org/details/cambridgehistori0000unse_a9n8/page/30 30]}}</ref>
[[File:Roman Baths in Bath Spa, England - July 2006.jpg|alt=Photograph of the Baths showing a rectangular area of greenish water surrounded by yellow stone buildings with pillars. In the background is the tower of the abbey.|thumb|The [[Roman Baths (Bath)|Roman Baths]] in [[Bath, Somerset]], are a well-preserved ''[[thermae]]'' from [[Roman Britain]].]]
In 1066, the [[Normans]] invaded England from northern France. After [[Norman conquest of England|conquering England]] they seized [[Norman invasion of Wales|large parts of Wales]], [[Norman invasion of Ireland|conquered much of Ireland]] and were invited to settle in Scotland, bringing to each country [[feudalism]] on the Northern French model and [[Norman-French]] culture.<ref>{{Cite book |last=Ganshof, F.L. |url=https://archive.org/details/feudalism0000gans_j4b5 |title=Feudalism |publisher=University of Toronto |year=1996 |isbn=978-0-8020-7158-3 |page=165 |url-access=registration}}</ref> The [[Anglo-Normans|Anglo-Norman]] [[ruling class]] greatly influenced, but eventually assimilated with, the local cultures.<ref>{{Cite book |last=Chibnall, Marjorie |url=https://books.google.com/books?id=qJl5Jm-IndUC&pg=PA115 |title=The Debate on the Norman Conquest |publisher=Manchester University Press |year=1999 |isbn=978-0-7190-4913-2 |pages=115–122 |author-link=Marjorie Chibnall |access-date=20 March 2023 |archive-date=26 March 2023 |archive-url=https://web.archive.org/web/20230326164802/https://books.google.com/books?id=qJl5Jm-IndUC&pg=PA115 |url-status=live}}</ref> Subsequent [[House of Plantagenet|medieval English kings]] completed the [[conquest of Wales]] and tried unsuccessfully [[Wars of Scottish Independence|to annex Scotland]]. Asserting its independence in the 1320 [[Declaration of Arbroath]], Scotland maintained its independence thereafter, albeit in [[Anglo-Scottish Wars|near-constant conflict with England]].<ref>{{Cite web |date=3 June 2023 |title=The Declaration of Arbroath |url=https://www.nms.ac.uk/past-exhibitions/the-declaration-of-arbroath |access-date=6 July 2025 |website=NMS |language=en}}</ref>
In 1215, [[Magna Carta]] was the first document to state that no government was above the law and that citizens have rights protecting them.<ref>{{Cite web |title=Magna Carta |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/ |access-date=27 May 2024 |publisher=parliament.uk}} {{Cite web |title=The contents of Magna Carta |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/magnacartaclauses/ |access-date=27 May 2024 |publisher=parliament.uk |archive-date=28 August 2022 |archive-url=https://web.archive.org/web/20220828101448/https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/magnacartaclauses/ |url-status=live}} {{Cite web |title=Magna Carta Key Facts |url=https://www.britannica.com/summary/Magna-Carta-Key-Facts |access-date=27 May 2024 |publisher=Britannica |archive-date=27 May 2024 |archive-url=https://web.archive.org/web/20240527191804/https://www.britannica.com/summary/Magna-Carta-Key-Facts |url-status=live}}</ref>
The English monarchs, through inheritance of [[Angevin Empire|substantial territories in France]] and claims to the French crown, were also heavily involved in conflicts in France, most notably the [[Hundred Years' War]], while the [[List of Scottish monarchs|Kings of Scots]] were in [[Auld Alliance|an alliance with the French]] during this period.<ref>Keen, Maurice. [https://www.bbc.co.uk/history/british/middle_ages/hundred_years_war_01.shtml "The Hundred Years' War"] {{Webarchive|url=https://web.archive.org/web/20131214092949/http://www.bbc.co.uk/history/british/middle_ages/hundred_years_war_01.shtml |date=14 December 2013 }}. BBC History.</ref> [[Early modern Britain]] saw religious conflict resulting from the [[Reformation]] and the introduction of [[Protestant]] state churches in each country.<ref>[https://www.britannica.com/EBchecked/topic/479892/Protestantism/41558/The-Reformation-in-England-and-Scotland The Reformation in England and Scotland] {{Webarchive|url=https://web.archive.org/web/20150515015218/https://www.britannica.com/EBchecked/topic/479892/Protestantism/41558/The-Reformation-in-England-and-Scotland |date=15 May 2015 }} and [https://www.britannica.com/EBchecked/topic/293754/Ireland/22978/The-Reformation-period Ireland: The Reformation Period & Ireland under Elizabeth I] {{Webarchive|url=https://web.archive.org/web/20150521133445/http://www.britannica.com/EBchecked/topic/293754/Ireland/22978/The-Reformation-period |date=21 May 2015 }}, Encyclopædia Britannica Online.</ref> The [[English Reformation]] ushered in political, constitutional, social and cultural change in the 16th century and [[State religion|established]] the [[Church of England]]. It defined a national identity for England and slowly, but profoundly, changed people's religious beliefs.<ref>{{Cite web |title=English Reformation c1527-1590 |url=https://www.nationalarchives.gov.uk/education/resources/the-english-reformation-c1527-1590/ |access-date=20 January 2023 |website=The National Archives |archive-date=2 December 2022 |archive-url=https://web.archive.org/web/20221202002512/https://www.nationalarchives.gov.uk/education/resources/the-english-reformation-c1527-1590/ |url-status=live}}</ref> Wales was [[Laws in Wales Acts 1535 and 1542|fully incorporated into the Kingdom of England]],<ref>{{Cite magazine |date=5 November 2009 |title=British History in Depth – Wales under the Tudors |url=https://www.bbc.co.uk/history/british/tudors/wales_tudors_01.shtml |magazine=BBC History |access-date=21 September 2010 |archive-date=7 February 2012 |archive-url=https://web.archive.org/web/20120207145836/http://www.bbc.co.uk/history/british/tudors/wales_tudors_01.shtml |url-status=live}}</ref> and Ireland was constituted as a kingdom in personal union with the English crown.<ref>{{Cite book |last=Nicholls |first=Mark |url=https://archive.org/details/historyofmodernb0000nich |title=A history of the modern British Isles, 1529–1603: The two kingdoms |publisher=Blackwell |year=1999 |isbn=978-0-631-19334-0 |location=Oxford |pages=171–172 |url-access=registration}}</ref> During the [[Plantation of Ulster]] in the 17th century, the lands of the Catholic Gaelic nobility were confiscated by the Crown and granted to Protestant settlers from England and Scotland.<ref>{{Cite book |last=Canny |first=Nicholas P. |url=https://archive.org/details/makingirelandbri00cann |title=Making Ireland British, 1580–1650 |publisher=Oxford University Press |year=2003 |isbn=978-0-19-925905-2 |pages=189–200 |url-access=registration}}</ref>
[[File:Bayeux Tapestry WillelmDux.jpg|thumb|The [[Bayeux Tapestry]] depicts the [[Battle of Hastings]], 1066, and the events leading to it.]]
The [[Union of the Crowns]] occurred in 1603 when [[James VI of Scotland]] inherited the thrones of England and Ireland, subsequently moving his court from Edinburgh to London. Although unified under a single monarch, the three realms remained entirely separate political entities, preserving their respective parliaments, judicial systems, and established churches.<ref>Ross, D. (2002). ''[[iarchive:chronologyofscot0000ross|Chronology of Scottish History]]''. Glasgow: Geddes & Grosset. p. 56. {{ISBN|978-1-85534-380-1}}; Hearn, J. (2002). ''Claiming Scotland: National Identity and Liberal Culture''. Edinburgh University Press. p. 104. {{ISBN|978-1-902930-16-9}}.</ref>
In the mid-17th century, all three kingdoms [[Wars of the Three Kingdoms|were involved in a series of connected wars]] (including the [[English Civil War]]) which led to the temporary overthrow of the monarchy, with [[Execution of Charles I|the execution]] of [[Charles I of England|King Charles I]], and the establishment of the short-lived [[unitary republic]] of the [[Commonwealth of England]], Scotland and Ireland.<ref>{{Cite encyclopedia |title=English Civil Wars |encyclopedia=Encyclopædia Britannica |url=https://www.britannica.com/EBchecked/topic/187936/English-Civil-Wars |access-date=28 April 2013 |archive-date=2 May 2015 |archive-url=https://web.archive.org/web/20150502204708/https://www.britannica.com/EBchecked/topic/187936/English-Civil-Wars |url-status=live}}; {{Cite web |date=14 March 2010 |title=Scotland and the Commonwealth: 1651–1660 |url=http://www.archontology.org/nations/uk/scotland/01_laws.php |access-date=9 March 2015 |publisher=Archontology.org |archive-date=16 July 2012 |archive-url=https://web.archive.org/web/20120716194016/http://www.archontology.org/nations/uk/scotland/01_laws.php |url-status=live}}</ref>
Although the [[Restoration (1660)|monarchy was restored]], the [[Interregnum (1649–1660)|Interregnum]] along with the [[Glorious Revolution]] of 1688 and the subsequent [[Bill of Rights 1689]] in England and [[Claim of Right Act 1689]] in Scotland ensured that, unlike much of the rest of Europe, [[royal absolutism]] would not prevail, and a professed Catholic could never accede to the throne. The [[British constitution]] would develop on the basis of [[constitutional monarchy]] and the [[parliamentary system]].<ref>{{Cite book |last=Lodge |first=Richard |url=https://books.google.com/books?id=EBSpvBxGyqcC |title=The History of England – From the Restoration to the Death of William III (1660–1702) |publisher=Read Books |year=2007 |isbn=978-1-4067-0897-4 |page=8 |orig-date=1910 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140723/https://books.google.com/books?id=EBSpvBxGyqcC |url-status=live}}</ref> With the founding of the [[Royal Society]] in 1660, science was greatly encouraged. During this period, particularly in England, the development of [[English navy|naval power]] and an interest in [[Age of Discovery|voyages of discovery]] led to the acquisition and settlement of overseas colonies, particularly in North America and the Caribbean.<ref>{{Cite web |title=Tudor Period and the Birth of a Regular Navy |url=http://www.royal-navy.org/lib/index.php?title=Tudor_Period_and_the_Birth_of_a_Regular_Navy_Part_Two |archive-url=https://web.archive.org/web/20111103013901/http://www.royal-navy.org/lib/index.php?title=Tudor_Period_and_the_Birth_of_a_Regular_Navy_Part_Two |archive-date=3 November 2011 |access-date=8 March 2015 |website=Royal Navy History |url-status=usurped |publisher=Institute of Naval History}}; {{Cite book |last=Canny |first=Nicholas |url=https://books.google.com/books?id=eQHSivGzEEMC |title=The Origins of Empire, The Oxford History of the British Empire Volume I |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924676-2 |ref=refOHBEv1 |access-date=29 September 2020 |archive-date=11 January 2023 |archive-url=https://web.archive.org/web/20230111135256/https://books.google.com/books?id=eQHSivGzEEMC |url-status=live}}</ref>
Though previous attempts at uniting the two kingdoms within Great Britain in 1606, 1667 and 1689 had proved unsuccessful, the attempt initiated in 1705 led to the [[Treaty of Union]] of 1706 being agreed and ratified by both parliaments.
{{Clear left}}
=== Union of England and Scotland ===
{{Main|Treaty of Union|Kingdom of Great Britain}}
[[File:Articles of Union between England and Scotland 28 Jan 1707.png|thumb|right|170px|The [[Treaty of Union]] which unified the [[Kingdom of England]] and [[Kingdom of Scotland]] on 1 May 1707]]
On 1 May 1707 the Kingdom of Great Britain was formed, the result of the [[Acts of Union 1707]] between the [[Kingdom of England]] and [[Kingdom of Scotland]].<ref>{{Cite web |title=Articles of Union with Scotland 1707 |url=http://www.nationalarchives.gov.uk/pathways/citizenship/rise_parliament/docs/articles_union.htm |access-date=19 October 2008 |publisher=UK Parliament |archive-date=8 June 2012 |archive-url=https://web.archive.org/web/20120608152446/http://www.nationalarchives.gov.uk/pathways/citizenship/rise_parliament/docs/articles_union.htm |url-status=live}}; {{Cite web |title=Acts of Union 1707 |url=http://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny |access-date=6 January 2011 |publisher=UK Parliament |archive-date=27 December 2010 |archive-url=https://web.archive.org/web/20101227033859/http://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny/ |url-status=live}}; {{Cite web |title=Treaty (act) of Union 1706 |url=http://www.scotshistoryonline.co.uk/union.html |archive-url=https://web.archive.org/web/20190527074630/http://www.scotshistoryonline.co.uk/union.html |archive-date=27 May 2019 |access-date=3 February 2011 |publisher=Scottish History online}}</ref> In the 18th century cabinet government developed under [[Robert Walpole]], who is considered the ''[[de facto]]'' first [[Prime Minister of the United Kingdom|prime minister]] from 1721 to 1742. A series of [[Jacobite uprisings]] sought to remove the Protestant [[House of Hanover]] from the throne and restore the Catholic [[House of Stuart]]. In 1746, the Jacobites were defeated at the [[Battle of Culloden]], after which the [[Scottish Highlanders]] were forcibly assimilated into Scotland by revoking the feudal independence of [[Scottish clan chief|clan chiefs]]. The British colonies in North America that broke away in the [[American Revolutionary War|American War of Independence]] became the [[United States]]. British imperial ambition turned towards Asia, particularly to [[British Raj|India]].<ref>Library of Congress, [https://books.google.com/books?id=BQDgr_XvsHoC&pg=PA73 ''The Impact of the American Revolution Abroad''] {{Webarchive|url=https://web.archive.org/web/20240328140724/https://books.google.com/books?id=BQDgr_XvsHoC&pg=PA73 |date=28 March 2024 }}, p. 73.</ref>
British merchants played a leading part in the [[Atlantic slave trade]], mainly between 1662 and 1807 when British or British-colonial [[slave ships]] transported nearly 3.3 million slaves from Africa.<ref>{{Cite book |last=Morgan |first=Kenneth |url=https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA12 |title=Slavery and the British Empire: From Africa to America |publisher=Oxford University Press, USA |year=2007 |isbn=978-0-19-156627-1 |page=12 |access-date=5 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141229/https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA12#v=onepage&q&f=false |url-status=live}}</ref> The slaves were taken to [[Plantation economy|work on plantations]], principally [[History of the British West Indies|in the Caribbean]] but also [[British America|in North America]].<ref>{{Cite book |last=Morgan |first=Kenneth |url=https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA15 |title=Slavery and the British Empire: From Africa to America |publisher=Oxford University Press, US |year=2007 |isbn=978-0-19-156627-1 |page=15 |access-date=5 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141229/https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA15#v=onepage&q&f=false |url-status=live}}</ref> However, with pressure from the [[Abolitionism in the United Kingdom|abolitionist movement]], Parliament banned the trade in 1807, banned slavery in the British Empire in 1833, and Britain took a leading role in the movement to abolish slavery worldwide through the [[blockade of Africa]] and pressing other nations to end their trade with a series of treaties.<ref>[https://www.bbc.co.uk/devon/content/articles/2007/03/20/abolition_navy_feature.shtml Sailing against slavery] {{Webarchive|url=https://web.archive.org/web/20081103004954/https://www.bbc.co.uk/devon/content/articles/2007/03/20/abolition_navy_feature.shtml |date=3 November 2008 }}. BBC Devon. 2007.; {{Cite book |last=Lovejoy |first=Paul E. |url=https://archive.org/details/transformationsi0000love/page/290 |title=Transformations in Slavery: A History of Slavery in Africa |publisher=Cambridge University Press |year=2000 |isbn=978-0-521-78012-4 |edition=2nd |location=New York |page=[https://archive.org/details/transformationsi0000love/page/290 290]}}</ref>
=== United Kingdom of Great Britain and Ireland ===
{{Main|History of the United Kingdom|Acts of Union 1800|United Kingdom of Great Britain and Ireland}}
[[File:Victoria in her Coronation robes.jpg|upright|thumb|[[Queen Victoria|Victoria]] reigned as [[Monarchy of the United Kingdom|Queen of the United Kingdom]] and [[Empress of India]] during the 19th century.]]
In 1800, the parliaments of Great Britain and Ireland each passed an Act of Union, uniting the two kingdoms and creating the United Kingdom of Great Britain and Ireland on 1 January 1801.<ref>{{Cite web |title=The Act of Union |url=http://www.actofunion.ac.uk/actofunion.htm#act |archive-url=https://web.archive.org/web/20120415061235/http://www.actofunion.ac.uk/actofunion.htm#act |archive-date=15 April 2012 |access-date=15 May 2006 |publisher=Act of Union Virtual Library}}</ref>
After the defeat of France at the end of the [[French Revolutionary Wars]] and [[Napoleonic Wars]] (1792–1815), the United Kingdom emerged as the principal naval and imperial power (with London the [[List of largest cities throughout history|largest city in the world from about 1830]]).<ref>Tellier, L.-N. (2009). ''Urban World History: an Economic and Geographical Perspective''. Quebec: PUQ. p. 463. {{ISBN|978-2-7605-1588-8}}.</ref> [[History of the Royal Navy (after 1707)#Pax Britannica, 1815–1914|Unchallenged at sea]], British dominance was later described as the ''[[Pax Britannica]]'' ("British Peace"), a period of [[International relations of the Great Powers (1814–1919)|relative peace amongst the great powers]] (1815–1914) during which the British Empire became the global [[hegemon]]<ref>{{Cite book |last=Mathias |first=P. |title=The First Industrial Nation: the Economic History of Britain, 1700–1914 |publisher=Routledge |year=2001 |isbn=978-0-415-26672-7 |location=London}}; {{Cite book |last=Ferguson |first=Niall |url=https://archive.org/details/empire00nial |title=Empire: The rise and demise of the British world order and the lessons for global power |publisher=Basic Books |year=2004 |isbn=978-0-465-02328-8 |location=New York |url-access=registration}}</ref><ref>{{Cite encyclopedia |title=20th-century international relations |encyclopedia=[[Encyclopædia Britannica]] |url=https://www.britannica.com/topic/20th-century-international-relations-2085155 |access-date=6 May 2023 |last=McDougall |first=Walter A. |date=4 May 2023 |author-link=Walter A. McDougall |archive-url=https://web.archive.org/web/20190712124130/https://www.britannica.com/topic/20th-century-international-relations-2085155 |archive-date=12 July 2019 |url-status=live}}</ref> and adopted the role of [[global policeman]].<ref>Sondhaus, L. (2004). ''Navies in Modern World History''. London: Reaktion Books. p. 9. {{ISBN|978-1-86189-202-7}}.</ref><ref>{{Cite book |last=Porter |first=Andrew |url=https://books.google.com/books?id=oo3F2X8IDeEC |title=The Nineteenth Century, The Oxford History of the British Empire Volume III |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924678-6 |page=332 |ref=refOHBEv3}}</ref> From 1853 to 1856 Britain took part in the [[Crimean War]], allied with the [[Ottoman Empire]] against [[Russian Empire|Tsarist Russia]].<ref>{{Cite journal |last=Benn |first=David Wedgwood |title=The Crimean War and its lessons for today |journal=[[International Affairs (journal)|International Affairs]] |volume=88 |issue=2 |date=March 2012 |pages=387–391 |jstor=41428613 |publisher=Oxford University Press |doi=10.1111/j.1468-2346.2012.01078.x}}</ref> Following the [[Indian Rebellion of 1857]] the British government led by [[Henry John Temple, 3rd Viscount Palmerston|Lord Palmerston]] assumed [[direct rule]] over [[British Raj|India]]. Alongside the formal control it exerted over its own colonies, British dominance of much of world trade meant that it [[Informal empire|effectively controlled]] the economies of regions such as [[East Asia]] and [[Latin America]].<ref>{{Cite book |last=Porter |first=Andrew |url=https://books.google.com/books?id=oo3F2X8IDeEC |title=The Nineteenth Century, The Oxford History of the British Empire Volume III |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924678-6 |page=8 |ref=refOHBEv3}}; {{Cite book |last=Marshall |first=P.J. |url=https://books.google.com/books?id=S2EXN8JTwAEC |title=The Cambridge Illustrated History of the British Empire |publisher=Cambridge University Press |year=1996 |isbn=978-0-521-00254-7 |pages=156–157 |ref=refMarshall |access-date=29 September 2020 |archive-date=16 January 2023 |archive-url=https://web.archive.org/web/20230116094154/https://books.google.com/books?id=S2EXN8JTwAEC |url-status=live}}</ref>
Throughout the [[Victorian era]] (1837–1901) political attitudes favoured [[free trade]] and ''[[laissez-faire]]'' policies. Beginning with the [[Great Reform Act]] in 1832, Parliament gradually [[Reform Acts|widened the voting franchise]], with the [[Representation of the People Act 1884|1884 Reform Act]] championed by [[William Ewart Gladstone|William Gladstone]] granting [[suffrage]] to a majority of males for the first time. The British population increased at a dramatic rate, accompanied by rapid [[urbanisation]], causing significant social and economic stresses.<ref>{{Cite book |last=Tompson |first=Richard S. |url=https://books.google.com/books?id=H5kcJqmXk2oC&pg=PA63 |title=Great Britain: a reference guide from the Renaissance to the present |publisher=Facts on File |year=2003 |isbn=978-0-8160-4474-0 |location=New York |page=63}}</ref> By the late 19th century, [[Conservative Party (UK)|Conservative governments]] under [[Benjamin Disraeli]] and [[Robert Gascoyne-Cecil, 3rd Marquess of Salisbury|Lord Salisbury]] accelerated [[Scramble for Africa|imperial expansion in Africa]], sustained a foreign policy of "[[splendid isolation]]" from European alliances, and intensified strategic containment of the [[Russian Empire]] in [[Central Asia]], a competition known as the [[Great Game]].<ref>{{Cite journal |last=Fromkin |first=David |date=1980 |title=The Great Game in Asia |url=https://www.jstor.org/stable/20040512 |journal=Foreign Affairs |volume=58 |issue=4 |pages=936–951 |doi=10.2307/20040512 |jstor=20040512 |issn=0015-7120 |access-date=4 June 2023 |archive-date=12 April 2021 |archive-url=https://web.archive.org/web/20210412053528/https://www.jstor.org/stable/20040512 |url-status=live |url-access=subscription}}</ref> During this time, [[Canada]], [[Australia]] and [[New Zealand]] were granted self-governing [[dominion]] status.<ref>{{Cite book |last=Hosch, William L. |title=World War I: People, Politics, and Power |publisher=Britannica Educational Publishing |year=2009 |isbn=978-1-61530-048-8 |series=America at War |location=New York |page=21}}</ref> At the turn of the 20th century, Britain's industrial dominance became challenged by the [[German Empire]] and the [[United States]].<ref>{{Cite book |last=Zarembka |first=Paul |url=https://books.google.com/books?id=NSrwpggmHigC&pg=PP1 |title=Contradictions: Finance, Greed, and Labor Unequally Paid |date=2013 |publisher=Emerald Group Publishing |isbn=978-1-78190-670-5 |access-date=21 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141231/https://books.google.com/books?id=NSrwpggmHigC&pg=PP1#v=onepage&q&f=false |url-status=live}}</ref> The [[Edwardian era]] (1901–1910) saw [[Liberal welfare reforms|social reform]] and [[Irish Home Rule movement|home rule for Ireland]] become important domestic issues, while the [[Labour Party (UK)|Labour Party]] emerged from an alliance of [[Trade unions in the United Kingdom|trade unions]] and small socialist groups in 1900, and [[suffragettes]] campaigned for women's right to vote.<ref>Sophia A. Van Wingerden, ''The women's suffrage movement in Britain, 1866–1928'' (1999) ch 1.</ref>
=== World wars and partition of Ireland ===
{{Main|History of the United Kingdom during the First World War|Partition of Ireland|Interwar Britain|United Kingdom home front during the Second World War|Military history of the United Kingdom during World War II}}
[[File:Wreaths Are Laid at the Cenotaph, London During Remembrance Sunday Service MOD 45152052.jpg|thumb|Wreaths being laid during the [[Remembrance Sunday]] service at the [[The Cenotaph|Cenotaph]] in [[Whitehall]], London]]
[[File:Spitfire and Hurricane in the Battle of Britain Memorial Flight.jpg|thumb|A [[Supermarine Spitfire|Spitfire]] and a [[Hawker Hurricane|Hurricane]] as flown in the [[Battle of Britain]] during the [[Second World War]]]]
Britain was one of the principal [[Allies of World War I|Allies]] that defeated the [[Central Powers]] in the [[First World War]] (1914–1918). Alongside their French, Russian and (after 1917) American counterparts,<ref>Turner, John (1988). ''Britain and the First World War''. London: Unwin Hyman. pp. 22–35. {{ISBN|978-0-04-445109-9}}.</ref> British armed forces were engaged across much of the British Empire and in several regions of Europe, particularly on the [[Western Front (World War I)|Western Front]].<ref name="Westwell&Cove" /> The high fatalities of [[trench warfare]] caused the loss of much of a generation of men, with lasting social effects in the nation and a great disruption in the social order. Britain had suffered 2.5 million casualties and finished the war with a huge national debt.<ref name="Westwell&Cove">Westwell, I.; Cove, D. (eds) (2002). ''History of World War I, Volume 3''. London: Marshall Cavendish. pp. 698, 705. {{ISBN|978-0-7614-7231-5}}.</ref>
The consequences of the war persuaded the government to expand the right to vote in national and local elections to all adult men and most adult women with the [[Representation of the People Act 1918]].<ref name="Westwell&Cove" /> After the war Britain became a permanent member of the Executive Council of the [[League of Nations]] and received [[League of Nations mandate|a mandate]] over a number of former German and [[Ottoman Empire|Ottoman]] colonies. Under the leadership of [[David Lloyd George]], the British Empire reached its greatest extent, covering a fifth of the world's land surface and a quarter of its population.<ref>Turner, J. (1988). ''Britain and the First World War''. Abingdon: Routledge. p. 41. {{ISBN|978-0-04-445109-9}}.</ref>
By the mid-1920s most of the British population could listen to [[BBC]] radio programmes.<ref>{{Cite web |date=15 June 2020 |title=100 years of radio since Marconi's big breakthrough |url=https://www.ofcom.org.uk/about-ofcom/latest/features-and-news/100-years-of-radio |access-date=17 November 2020 |website=Ofcom |archive-date=4 August 2020 |archive-url=https://web.archive.org/web/20200804031332/https://www.ofcom.org.uk/about-ofcom/latest/features-and-news/100-years-of-radio |url-status=live}}</ref><ref>{{Cite web |title=History of the BBC: The origins of BBC Local Radio |url=https://www.bbc.com/historyofthebbc/research/local-radio |access-date=18 September 2022 |website=[[BBC]] |last=Linfoot |first=Matthew |archive-date=20 September 2022 |archive-url=https://web.archive.org/web/20220920232207/https://www.bbc.com/historyofthebbc/research/local-radio/ |url-status=live}}</ref> Experimental [[Television in the United Kingdom|television]] broadcasts [[History of television#United Kingdom|began in 1929]] and the [[First day of BBC television|first scheduled BBC Television Service]] commenced in 1936.<ref>{{Cite web |title=History of the BBC: 1920s |url=https://www.bbc.com/historyofthebbc/timelines/1920s |access-date=18 September 2022 |website=[[BBC]] |archive-date=26 September 2022 |archive-url=https://web.archive.org/web/20220926064808/https://www.bbc.com/historyofthebbc/timelines/1920s |url-status=live}}</ref> The rise of [[Irish nationalism]], and disputes within Ireland over the terms of [[Irish Home Rule]], led eventually to the [[Partition of Ireland|partition of the island]] in 1921.<ref>[[SR&O 1921]]/533 of 3 May 1921.</ref> [[The Troubles in Ulster (1920–1922)|A period of conflict in what is now Northern Ireland]] occurred from June 1920 until June 1922. The [[Irish Free State]] became independent, initially with [[Dominion]] status in 1922, and [[Statute of Westminster 1931#Irish Free State|unambiguously independent in 1931]]. Northern Ireland remained part of the United Kingdom.<ref>{{Cite web |title=The Anglo-Irish Treaty, 6 December 1921 |url=http://cain.ulst.ac.uk/issues/politics/docs/ait1921.htm |access-date=15 May 2006 |website=CAIN Web Service |archive-date=14 May 2012 |archive-url=https://web.archive.org/web/20120514145108/http://cain.ulst.ac.uk/issues/politics/docs/ait1921.htm |url-status=live}}</ref> The [[1928 Equal Franchise Act]] gave women electoral equality with men in national elections. Strikes in the mid-1920s culminated in the [[General Strike of 1926]]. Still suffering from the long-term economic effects of the First World War, Britain was severely impacted by the [[Great Depression in the United Kingdom|Great Depression]] (1929–1932), which intensified hardship in old industrial areas in traditional sectors, led to mass unemployment peaking near 3 million, and precipitated widespread political instability and social unrest. [[National Government (1931)|A coalition government]] was formed in 1931.<ref>Rubinstein, W.D. (2004). ''Capitalism, Culture, and Decline in Britain, 1750–1990''. Abingdon: Routledge. p. 11. {{ISBN|978-0-415-03719-8}}.</ref>
Nonetheless, Britain was described as "a very wealthy country, formidable in arms, ruthless in pursuit of its interests and sitting at the heart of a global production system."<ref name="Edgerton2012">{{Cite book |last=Edgerton |first=David |date=2012 |title=Britain's War Machine |url=https://www.penguin.co.uk/books/55731/britain-s-war-machine/9780141026107.html |access-date=10 May 2020 |publisher=Penguin |postscript=none |archive-date=28 April 2020 |archive-url=https://web.archive.org/web/20200428080558/https://www.penguin.co.uk/books/55731/britain-s-war-machine/9780141026107.html |url-status=live}}; {{Cite web |title=Britain's War Machine: Weapons, Resources and Experts in the Second World War |url=https://reviews.history.ac.uk/review/1114 |access-date=10 May 2020 |website=[[Reviews in History]] |archive-date=12 June 2020 |archive-url=https://web.archive.org/web/20200612173058/https://reviews.history.ac.uk/review/1114 |url-status=live}}</ref> After [[Nazi Germany]]'s [[invasion of Poland]] in 1939, Britain entered the [[Second World War]]. Despite the defeat of its European allies in the first year, Britain and its empire continued the war against Germany.<ref name="Edgerton2012" />
In 1940 the [[Royal Air Force]] successfully defended British airspace by repelling the German ''[[Luftwaffe]]'' in the [[Battle of Britain]]. Urban areas suffered heavy bombing during [[the Blitz]]. The [[Grand Alliance (World War II)|Grand Alliance]] of Britain, the United States and the [[Soviet Union]] formed in 1941, leading the [[Allies of World War II|Allies]] against the [[Axis powers]]. There were eventual hard-fought victories in the [[Battle of the Atlantic]], the [[North Africa campaign]] and the [[Italian campaign (World War II)|Italian campaign]]. British forces played important roles in the [[Normandy landings]] of 1944 and the [[liberation of Europe]]. The British Army led the [[Burma campaign]] against Japan, and the [[British Pacific Fleet]] fought Japan at sea. [[British contribution to the Manhattan Project|British scientists contributed]] to the American [[Manhattan Project]], whose task was to build a [[nuclear weapon]].<ref>{{cite book |author=Septimus H. Paul |url=https://books.google.com/books?id=fSZpgW-N628C&pg=PA1 |title=Nuclear Rivals: Anglo-American Atomic Relations, 1941–1952 |publisher=Ohio State U.P. |year=2000 |isbn=978-0-8142-0852-6 |pages=1–5}}</ref>
=== Post-war 20th century ===
{{Main|Post-war Britain (1945–1979)|Social history of post-war Britain (1945–1979)}}
[[File:British Empire 1921.png|thumb|right|upright=1.4|The [[British Empire]] at its territorial peak in 1921]]
The United Kingdom was one of the [[Big Three (World War II)|Big Three]] powers (with the United States and the Soviet Union) who met to plan the [[Aftermath of World War II|post-war world]];<ref>{{Cite book |last1=Doenecke |first1=Justus D. |url=https://books.google.com/books?id=xdMF9rX6mX8C&pg=PA62 |title=Debating Franklin D. Roosevelt's foreign policies, 1933–1945 |last2=Stoler |first2=Mark A. |year=2005 |publisher=Rowman & Littlefield |isbn=978-0-8476-9416-7 |access-date=19 March 2016 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141231/https://books.google.com/books?id=xdMF9rX6mX8C&pg=PA62#v=onepage&q&f=false |url-status=live|author-link=Justus Drew Doenecke}}; {{Cite book |last=Kelly |first=Brian |url=https://www.iup.edu/WorkArea/DownloadAsset.aspx?id=37681 |title=The Four Policemen and Postwar Planning, 1943–1945: The Collision of Realist and Idealist Perspectives |publisher=Indiana University of Pennsylvania |access-date=25 August 2015 |archive-date=22 October 2015 |archive-url=https://web.archive.org/web/20151022125442/https://www.iup.edu/WorkArea/DownloadAsset.aspx?id=37681 |url-status=live}}</ref> it drafted the [[Declaration by United Nations]] with the United States and became one of the five permanent members of the [[United Nations Security Council]]. It worked closely with the United States to establish the [[International Monetary Fund]], the [[World Bank]] and [[NATO]].<ref>{{Cite web |date=22 July 2010 |title=The "Special Relationship" between Great Britain and the United States Began with FDR |work=Roosevelt Institute |url=http://rooseveltinstitute.org/special-relationship-between-great-britain-and-united-states-began-fdr |archive-url=https://web.archive.org/web/20180125021103/http://rooseveltinstitute.org/special-relationship-between-great-britain-and-united-states-began-fdr |archive-date=25 January 2018 |access-date=24 January 2018 |quote=and the joint efforts of both powers to create a new post-war strategic and economic order through the drafting of the Atlantic Charter; the establishment of the International Monetary Fund and the World Bank; and the creation of the United Nations.}}; {{Cite press release |title=Remarks by the President Obama and Prime Minister Cameron in Joint Press Conference |date=22 April 2016 |publisher=The White House |url=https://obamawhitehouse.archives.gov/the-press-office/2016/04/22/remarks-president-obama-and-prime-minister-cameron-joint-press |quote=That's what we built after World War II. The United States and the UK designed a set of institutions – whether it was the United Nations, or the Bretton Woods structure, IMF, World Bank, NATO, across the board. |access-date=24 January 2018 |archive-date=8 June 2021 |archive-url=https://web.archive.org/web/20210608110653/https://obamawhitehouse.archives.gov/the-press-office/2016/04/22/remarks-president-obama-and-prime-minister-cameron-joint-press |url-status=live}}</ref> The war left the UK severely weakened and financially dependent on the American [[Marshall Plan]],<ref>{{Cite news |date=28 December 2006 |title=Britain to make its final payment on World War II loan from U.S. |work=The New York Times |url=https://www.nytimes.com/2006/12/28/business/worldbusiness/28iht-nazi.4042453.html |access-date=25 August 2011 |archive-date=20 August 2017 |archive-url=https://web.archive.org/web/20170820022220/http://www.nytimes.com/2006/12/28/business/worldbusiness/28iht-nazi.4042453.html |url-status=live}}</ref> but it was spared the total war that devastated [[eastern Europe]].<ref>{{Cite news |last=Reynolds |first=David |date=17 April 2011 |title=Britain's War Machine by David Edgerton – review |work=The Guardian |location=London |url=https://www.theguardian.com/books/2011/apr/17/britains-war-machine-david-edgerton-review |access-date=10 May 2020 |archive-date=12 June 2020 |archive-url=https://web.archive.org/web/20200612130213/https://www.theguardian.com/books/2011/apr/17/britains-war-machine-david-edgerton-review |url-status=live}}</ref>
In the immediate post-war years the [[Labour Government 1945–1951|Labour government]] under [[Clement Attlee]] initiated a radical programme of reforms, which significantly affected British society [[Post-war consensus|in the following decades]].<ref>{{Cite book |last=Francis |first=Martin |title=Ideas and policies under Labour, 1945–1951: Building a new Britain |publisher=Manchester University Press |year=1997 |isbn=978-0-7190-4833-3 |pages=225–233}}</ref> Major industries and public utilities were [[nationalised]], a [[welfare state]] was established, and a comprehensive, publicly funded healthcare system, the [[National Health Service]], was created.<ref>{{Cite book |last=Lee |first=Stephen J. |url=https://archive.org/details/aspectsbritishpo00lees |title=Aspects of British political history, 1914–1995 |publisher=Routledge |year=1996 |isbn=978-0-415-13103-2 |location=London; New York |pages=[https://archive.org/details/aspectsbritishpo00lees/page/n183 173]–199 |url-access=limited}}</ref> The rise of nationalism in the colonies coincided with Britain's much-diminished economic position after [[History of the United Kingdom during the First World War|its involvement in the First World War]] and [[Military history of the United Kingdom during World War II|in the Second World War]], so that a policy of [[decolonisation]] was unavoidable.<ref>{{cite book |last=Brown |first=Judith |author-link=Judith M. Brown |url=https://books.google.com/books?id=CpSvK3An3hwC |title=The Twentieth Century, The Oxford History of the British Empire Volume IV |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924679-3 |ref=refOHBEv4 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20140103114315/http://books.google.com/books?id=CpSvK3An3hwC |archive-date=3 January 2014 |url-status=live}} p. 319.</ref><ref>{{cite book |last=Louis |first=Wm. Roger |url=https://books.google.com/books?id=NQnpQNKeKKAC |title=Ends of British Imperialism: The Scramble for Empire, Suez and Decolonization |publisher=I.B. Tauris |year=2006 |isbn=978-1-84511-347-6 |ref=refLouis2006 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20170222045215/https://books.google.com/books?id=NQnpQNKeKKAC |archive-date=22 February 2017 |url-status=live}} p. 337.</ref><ref>{{cite book |last=Abernethy |first=David |url=https://books.google.com/books?id=ennqNS1EOuMC |title=The Dynamics of Global Dominance, European Overseas Empires 1415–1980 |publisher=Yale University Press |year=2000 |isbn=978-0-300-09314-8 |ref=refAbernethy2000 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20111214082531/http://books.google.com/books?id=ennqNS1EOuMC |archive-date=14 December 2011 |url-status=live}} p. 146.</ref> Independence was granted to India and Pakistan in 1947.<ref>{{Cite book |last=Larres |first=Klaus |url=https://books.google.com/books?id=7D66_9YOof4C&pg=PA118 |title=A companion to Europe since 1945 |publisher=Wiley-Blackwell |year=2009 |isbn=978-1-4051-0612-2 |location=Chichester |page=118 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141350/https://books.google.com/books?id=7D66_9YOof4C&pg=PA118 |url-status=live}}</ref> Over the next three decades, most colonies of the British Empire gained their independence, and many became members of the [[Commonwealth of Nations]].<ref>{{Cite web |date=19 March 2009 |title=Country List |url=http://www.thecommonwealth.org/Templates/System/YearbookHomePage.asp?NodeID=152099&load=countrylist |archive-url=https://web.archive.org/web/20130506071236/http://www.thecommonwealth.org/Templates/System/YearbookHomePage.asp?NodeID=152099&load=countrylist |archive-date=6 May 2013 |access-date=8 March 2015 |publisher=[[Commonwealth Secretariat]]}}</ref>
The UK was the third country to develop [[Nuclear weapons and the United Kingdom|a nuclear weapons arsenal]], with its first atomic bomb test, [[Operation Hurricane]], in 1952, although the post-war limitations of Britain's international role were illustrated by the [[Suez Crisis]] of 1956. As a result of a shortage of workers in the 1950s, the government [[Modern immigration to the United Kingdom|encouraged immigration]] from [[Commonwealth countries]]. In the following decades the UK became a more [[Multiracialism|multiracial]] and [[Multiculturalism|multicultural]] society.<ref>{{Cite book |last=Julios |first=Christina |url=https://books.google.com/books?id=s3RQ4dsFEkoC&pg=PA84 |title=Contemporary British identity: English language, migrants, and public discourse |publisher=Ashgate |year=2008 |isbn=978-0-7546-7158-9 |series=Studies in migration and diaspora |location=Aldershot |page=84 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141350/https://books.google.com/books?id=s3RQ4dsFEkoC&pg=PA84 |url-status=live}}</ref> Despite rising living standards in the late 1950s and 1960s, the United Kingdom's economic performance was less successful than many of its main competitors such as France, [[West Germany]] and Japan. In 1969, the United Kingdom was the first democratic nation to [[Representation of the People Act 1969|lower its voting age to 18]].<ref>{{Cite journal |last1=Loughran |first1=Thomas |last2=Mycock |first2=Andrew |last3=Tonge |first3=Jonathan |date=3 April 2021 |title=A coming of age: how and why the UK became the first democracy to allow votes for 18-year-olds |url=https://www.tandfonline.com/doi/full/10.1080/13619462.2021.1890589 |journal=Contemporary British History |volume=35 |issue=2 |pages=284–313 |doi=10.1080/13619462.2021.1890589 |issn=1361-9462 |s2cid=233956982 |access-date=24 May 2024 |archive-date=4 June 2023 |archive-url=https://web.archive.org/web/20230604093606/https://www.tandfonline.com/doi/full/10.1080/13619462.2021.1890589 |url-status=live |url-access=subscription}}</ref>
In the decades-long process of [[European integration]] the UK was a founding member of the [[Western European Union]], established with the [[London and Paris Conferences]] in 1954. In 1960 the UK was one of the seven founding members of the [[European Free Trade Association]] (EFTA), but in 1973 it left to join the [[European Communities]] (EC). In a [[1975 United Kingdom European Communities membership referendum|1975 referendum]] 67 per cent voted to stay in it.<ref>{{Cite news |title=1975: UK embraces Europe in referendum |work=BBC News |url=http://news.bbc.co.uk/onthisday/hi/dates/stories/june/6/newsid_2499000/2499297.stm |access-date=8 March 2015 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620044520/http://news.bbc.co.uk/onthisday/hi/dates/stories/june/6/newsid_2499000/2499297.stm |url-status=live}}</ref> When the EC became the [[European Union]] (EU) in 1993, the UK was one of the 12 founding member states.
From the late 1960s, Northern Ireland experienced communal and [[paramilitary]] violence, sometimes affecting other parts of the UK, known as [[the Troubles]]. It is usually considered to have ended with the 1998 [[Belfast Agreement|Belfast "Good Friday" Agreement]].<ref>{{Cite book |last=Aughey |first=Arthur |url=https://archive.org/details/politicsnorthern00augh |title=The Politics of Northern Ireland: Beyond the Belfast Agreement |publisher=Routledge |year=2005 |isbn=978-0-415-32788-6 |location=London |page=[https://archive.org/details/politicsnorthern00augh/page/n15 7] |url-access=limited}}; "The troubles were over, but the killing continued. Some of the heirs to Ireland's violent traditions refused to give up their inheritance." {{Cite book |last=Holland |first=Jack |url=https://archive.org/details/hopeagainsthisto00holl/page/221 |title=Hope against History: The Course of Conflict in Northern Ireland |publisher=Henry Holt |year=1999 |isbn=978-0-8050-6087-4 |location=New York |page=[https://archive.org/details/hopeagainsthisto00holl/page/221 221]}}; Elliot, Marianne (2007). ''The Long Road to Peace in Northern Ireland: Peace Lectures from the Institute of Irish Studies at Liverpool University.'' University of Liverpool Institute of Irish Studies, Liverpool University Press. p. 2. {{ISBN|978-1-84631-065-2}}.</ref> Following a period of widespread economic slowdown and industrial strife in the 1970s, the [[Conservative Party (UK)|Conservative]] government of the 1980s led by [[Margaret Thatcher]] initiated a radical policy of [[monetarism]], [[deregulation]], particularly of the financial sector (for example, the [[Big Bang (financial markets)|Big Bang]] in 1986) and labour markets, the sale of state-owned companies (privatisation), and the withdrawal of subsidies to others.<ref>{{Cite book |last=Dorey |first=Peter |title=British politics since 1945 |publisher=Blackwell |year=1995 |isbn=978-0-631-19075-2 |series=Making contemporary Britain |location=Oxford |pages=164–223}}</ref>
In 1982, [[Argentina]] invaded the British territories of [[South Georgia and the South Sandwich Islands|South Georgia]] and the [[Falkland Islands]], leading to the 10-week [[Falklands War]] in which Argentine forces were defeated. The inhabitants of the islands strongly favour British sovereignty, expressed in a [[2013 Falkland Islands sovereignty referendum|2013 referendum]]. From 1984 the British economy was helped by the inflow of substantial [[North Sea oil]] revenues.<ref>{{Cite book |last1=Griffiths, Alan |url=http://vig.pearsoned.co.uk/catalog/uploads/Griffiths_C01.pdf |title=Applied Economics |last2=Wall, Stuart |publisher=Financial Times Press |year=2007 |isbn=978-0-273-70822-3 |edition=11th |location=Harlow |page=6 |access-date=26 December 2010 |archive-date=23 August 2009 |archive-url=https://web.archive.org/web/20090823124048/http://vig.pearsoned.co.uk/catalog/uploads/Griffiths_C01.pdf |url-status=dead}}</ref> Another British Overseas Territory, [[Gibraltar]],<ref>{{cite wikisource |title=Peace and Friendship Treaty of Utrecht between Spain and Great Britain}}</ref> is [[Port of Gibraltar|a key military base]]; a [[2002 Gibraltar sovereignty referendum|referendum in 2002]] on shared sovereignty with Spain was rejected.
By the late 20th century, major changes were made to the governance of the UK with the establishment of [[devolution|devolved]] administrations for Scotland, Wales and Northern Ireland.<ref>{{Cite journal |last=Keating |first=Michael |date=1 January 1998 |title=Reforging the Union: Devolution and Constitutional Change in the United Kingdom |journal=Publius: The Journal of Federalism |volume=28 |issue=1 |pages=217–234 |doi=10.1093/oxfordjournals.pubjof.a029948}}</ref> [[Human Rights Act 1998|The statutory incorporation]] followed acceptance of the [[European Convention on Human Rights]]. The UK remained a [[List of modern great powers#United Kingdom|great power]] with global diplomatic and military influence and a leading role in the United Nations and NATO.<ref name="David M. McCourt">{{Cite book |last=McCourt |first=David |url=https://books.google.com/books?id=lwpOnwEACAAJ&q=Britain+and+World+Power+Since+1945:+Constructing+a+Nation%27s+Role+in+International+Politics |title=Britain and World Power Since 1945: Constructing a Nation's Role in International Politics |publisher=[[University of Michigan Press]] |year=2014 |isbn=978-0-472-07221-7 |access-date=21 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141741/https://books.google.com/books?id=lwpOnwEACAAJ&q=Britain+and+World+Power+Since+1945:+Constructing+a+Nation%27s+Role+in+International+Politics |url-status=live}}</ref>
=== 21st century ===
{{Main|Political history of the United Kingdom (1979–present)|Social history of the United Kingdom (1979–present)}}
[[File:Johnson signed Brexit Withdrawal Agreement.jpg|thumb|Prime Minister [[Boris Johnson]] signs the [[Brexit withdrawal agreement]] in 2020, formally [[Brexit|withdrawing the UK]] from the [[European Union]] (EU).]]
The United Kingdom broadly supported the United States' approach to the "[[war on terror]]" in the early 21st century.<ref>{{Cite news |last=McSmith |first=Andy |date=5 July 2016 |title=The inside story of how Tony Blair led Britain to war in Iraq |work=Independent |location=London |url=https://www.independent.co.uk/news/uk/politics/chilcot-report-iraq-war-inquiry-tony-blair-george-bush-us-uk-what-happened-a7119761.html |access-date=17 February 2022 |archive-date=4 July 2016 |archive-url=https://web.archive.org/web/20160704200931/https://www.independent.co.uk/news/uk/politics/chilcot-report-iraq-war-inquiry-tony-blair-george-bush-us-uk-what-happened-a7119761.html |url-status=live}}</ref> British troops fought in the [[War in Afghanistan (2001–2021)|war in Afghanistan]], but controversy surrounded Britain's [[Iraq War|military deployment in Iraq]], which saw the [[15 February 2003 anti-war protests|largest protest in British history]] in opposition to the government led by [[Tony Blair]].<ref>{{Cite news |last=Adams |first=Tim |date=11 February 2023 |title='A beautiful outpouring of rage': did Britain's biggest ever protest change the world? |work=The Observer |location=London |url=https://www.theguardian.com/uk-news/2023/feb/11/slugs-iraq-war-london-protest-2003-legacy |access-date=5 June 2023 |archive-date=6 April 2023 |archive-url=https://web.archive.org/web/20230406052000/https://www.theguardian.com/uk-news/2023/feb/11/slugs-iraq-war-london-protest-2003-legacy |url-status=live}}</ref>
The [[Great Recession]] (2007–2010) severely affected the British economy,<ref name="Latest UK GDP data">{{cite web |date=20 December 2013 |title=Quarterly National Accounts – National accounts aggregates (ABMI Gross Domestic Product: chained volume measures: Seasonally adjusted £m, constant prices) |url=http://www.ons.gov.uk/ons/datasets-and-tables/data-selector.html?cdid=ABMI&dataset=qna&table-id=A2 |publisher=Office for National Statistics |access-date=28 July 2023 |archive-date=29 September 2015 |archive-url=https://web.archive.org/web/20150929150429/http://www.ons.gov.uk/ons/datasets-and-tables/data-selector.html?cdid=ABMI&dataset=qna&table-id=A2 |url-status=live}}</ref> and was followed by a period of weak growth and stagnation.<ref>{{Cite web |last=Harari |first=Daniel |date=16 July 2024 |title=Low growth: The economy's biggest challenge |url=https://commonslibrary.parliament.uk/low-growth-the-economys-biggest-challenge/#:~: |access-date=16 April 2025 |website=House of Commons Library}}</ref><ref>{{Cite news |last1=Rees |first1=Tom |last2=Atkinson |first2=Andrew |last3=Aldrick |first3=Philip |date=12 March 2023 |title=A Lost Decade Worse Than Japan's Threatens to Change UK Forever |url=https://www.bloomberg.com/news/articles/2023-03-12/a-lost-decade-worse-than-japan-s-threatens-to-change-uk-forever |access-date=16 April 2025 |work=[[Bloomberg News]] |archive-date=13 March 2023 |archive-url=https://web.archive.org/web/20230313051724/https://www.bloomberg.com/news/articles/2023-03-12/a-lost-decade-worse-than-japan-s-threatens-to-change-uk-forever |url-status=live }}</ref> The [[Cameron–Clegg coalition]] government of 2010 introduced [[United Kingdom government austerity programme|austerity measures]] intended to tackle the substantial public deficits.<ref>{{Cite news |date=7 November 2022 |title=What is austerity and where could 'eye-watering' cuts fall now? |work=BBC News |url=https://www.bbc.com/news/63304224 |access-date=28 July 2023 |archive-date=28 July 2023 |archive-url=https://web.archive.org/web/20230728105646/https://www.bbc.com/news/63304224 |url-status=live}}</ref> [[2014 Scottish independence referendum|A referendum]] on [[Scottish independence]] in 2014 resulted in the Scottish electorate voting by 55.3 to 44.7 per cent to remain part of the United Kingdom.<ref>{{Cite web |title=Scottish independence referendum – Results |url=https://www.bbc.co.uk/news/events/scotland-decides/results |access-date=18 February 2022 |website=BBC News |archive-date=18 September 2014 |archive-url=https://web.archive.org/web/20140918212409/https://www.bbc.co.uk/news/events/scotland-decides/results |url-status=live}}</ref>
In 2016, 51.9 per cent of voters in the UK [[2016 United Kingdom European Union membership referendum|voted to leave the European Union]] (EU).<ref>{{Cite news |date=24 June 2016 |title=In stunning decision, Britain votes to leave the E.U. |newspaper=[[The Washington Post]] |url=https://www.washingtonpost.com/world/britons-head-to-the-polls-for-historic-vote-on-eu/2016/06/23/0d466fb0-34a7-11e6-ab9d-1da2b0f24f93_story.html |access-date=24 June 2016 |first1=Griff |last1=Witte |first2=Karla |last2=Adam |first3=Dan |last3=Balz |archive-date=30 November 2022 |archive-url=https://web.archive.org/web/20221130215030/https://www.washingtonpost.com/world/britons-head-to-the-polls-for-historic-vote-on-eu/2016/06/23/0d466fb0-34a7-11e6-ab9d-1da2b0f24f93_story.html |url-status=live}}</ref> The [[Brexit|UK left the EU]] in 2020.<ref>{{Cite news |date=1 January 2021 |title=Brexit: New era for UK as it completes separation from European Union |work=BBC News |url=https://www.bbc.com/news/uk-politics-55502781 |access-date=18 February 2022 |archive-date=14 January 2021 |archive-url=https://web.archive.org/web/20210114212309/https://www.bbc.com/news/uk-politics-55502781 |url-status=live}}</ref> On 1 May 2021 the [[EU–UK Trade and Cooperation Agreement]], a free trade agreement between the UK and the EU, came into force.<ref name="commission.europa.eu">{{Cite web |title=The EU-UK Trade and Cooperation Agreement |url=https://commission.europa.eu/strategy-and-policy/relations-non-eu-countries/relations-united-kingdom/eu-uk-trade-and-cooperation-agreement_en |archive-url=https://web.archive.org/web/20230325155905/https://commission.europa.eu/strategy-and-policy/relations-non-eu-countries/relations-united-kingdom/eu-uk-trade-and-cooperation-agreement_en |archive-date=25 March 2023 |access-date=25 March 2023}}</ref><ref>{{Cite web |access-date=12 September 2025 |title=Free Trade Agreements EU-UK |url=https://rtais.wto.org/UI/PublicShowRTAIDCard.aspx?rtaid=1137}}</ref>
The [[COVID-19 pandemic in the United Kingdom|COVID-19 pandemic]] had a severe [[Economic impact of the COVID-19 pandemic in the United Kingdom|impact on the British economy]], caused major [[Impact of the COVID-19 pandemic on education in the United Kingdom|disruptions to education]] and had [[Social impact of the COVID-19 pandemic in the United Kingdom|far-reaching impacts on society and politics]] in 2020 and 2021.<ref name="GOVUK">{{cite web |url=https://coronavirus.data.gov.uk/ |title=Coronavirus (COVID-19) in the UK |website=[[gov.uk]] |publisher=Government of the United Kingdom |access-date=15 April 2020 |archive-url=https://web.archive.org/web/20210501022145/https://coronavirus.data.gov.uk/ |archive-date=1 May 2021}}</ref><ref>{{Cite web |title=Coronavirus and the impact on output in the UK economy: April 2020 |url=https://www.ons.gov.uk/economy/grossdomesticproductgdp/articles/coronavirusandtheimpactonoutputintheukeconomy/april2020 |access-date=2 August 2020 |publisher=Government of the United Kingdom |website=ons.gov.uk |archive-date=2 August 2020 |archive-url=https://web.archive.org/web/20200802031859/https://www.ons.gov.uk/economy/grossdomesticproductgdp/articles/coronavirusandtheimpactonoutputintheukeconomy/april2020 |url-status=live}}</ref><ref>{{Cite news |last=Walker |first=Andrew |date=10 June 2020 |title=Coronavirus: UK economy could be among worst hit of leading nations, says OECD |work=BBC News |url=https://www.bbc.com/news/business-52991913 |access-date=2 August 2020 |archive-date=18 August 2020 |archive-url=https://web.archive.org/web/20200818031423/https://www.bbc.com/news/business-52991913 |url-status=live}}</ref> The United Kingdom was the first country in the world to use an approved [[COVID-19 vaccine]]. Developing a [[Oxford–AstraZeneca COVID-19 vaccine|vaccine in the UK]] allowed the rollout to be amongst the fastest in the world.<ref>{{Cite web |title=Landmark moment as first NHS patient receives COVID-19 vaccination |url=https://www.england.nhs.uk/2020/12/landmark-moment-as-first-nhs-patient-receives-covid-19-vaccination/ |archive-url=https://web.archive.org/web/20230225194320/https://www.england.nhs.uk/2020/12/landmark-moment-as-first-nhs-patient-receives-covid-19-vaccination/ |archive-date=25 February 2023 |website=NHS |date=8 December 2020}}</ref><ref>{{Cite web |title=Oxford University/AstraZeneca COVID-19 vaccine approved |url=https://www.gov.uk/government/news/oxford-universityastrazeneca-covid-19-vaccine-approved |archive-url=https://web.archive.org/web/20230225194442/https://www.gov.uk/government/news/oxford-universityastrazeneca-covid-19-vaccine-approved |archive-date=25 February 2023 |website=UK Government}}</ref>
== Geography ==
{{Main|Geography of the United Kingdom|Fauna of Great Britain|Flora of Great Britain and Ireland}}
[[File:MODIS - Great Britain and Northern Ireland - 2012-06-04 during heat wave (cropped).jpg|thumb|upright|A satellite image of the United Kingdom excluding [[Shetland]]]]
The total area of the United Kingdom is approximately {{Convert|244376|km2|sqmi|order=flip}},{{efn|name=ONSArea}}<ref name="ONS Standard Area Measurement" /> with a land area of {{convert|242741|km2|sqmi|order=flip}}.<ref name="ONS Standard Area Measurement" /> It occupies the major part of the [[British Isles]]<ref>[[Oxford English Dictionary]]: "British Isles: a geographical term for the islands comprising Great Britain and Ireland with all their offshore islands including the Isle of Man and the Channel Islands."</ref> and includes the island of Great Britain, the north-eastern one-sixth of the island of Ireland and [[List of islands of the United Kingdom|some smaller surrounding islands]], meaning it comprises [[England]], [[Scotland]], [[Wales]] and [[Northern Ireland]].<ref name="ONS Geography Guide">{{cite web |url=https://geoportal.statistics.gov.uk/datasets/d1f39e20edb940d58307a54d6e1045cd/about |title=A Beginner's Guide to UK Geography (2023) |author=<!--Not stated--> |date=4 February 2025 |website=Open Geography Portal |publisher=Office for National Statistics |access-date=14 May 2025}}</ref>
Geographically, the United Kingdom lies between the [[North Atlantic Ocean]] and the [[North Sea]] with the southeast coast coming within {{Convert|35|km|mi|0|order=flip}} of the coast of northern France, from which it is separated by the [[English Channel]].<ref name="factbook">{{Cite web |title=United Kingdom |url=https://www.cia.gov/the-world-factbook/countries/united-kingdom |access-date=21 January 2007 |website=[[The World Factbook]] |publisher=Central Intelligence Agency |archive-date=9 January 2021 |archive-url=https://web.archive.org/web/20210109221834/https://www.cia.gov/the-world-factbook/countries/united-kingdom |url-status=dead}}</ref>
The nearby island polities of the [[Isle of Man]], [[Jersey]] and [[Guernsey]] are [[Crown Dependencies]], in union with the [[Monarchy of the United Kingdom|British monarch]], but do not strictly form part of the United Kingdom or any of its three jurisdictions or four countries, although the British government retains responsibility for their external affairs. The Isle of Man lies roughly midway between Great Britain and the [[Ireland|island of Ireland]] in the [[Irish Sea]], while the Channel Islands lie just off the northern French coast.
The [[Royal Observatory, Greenwich|Royal Greenwich Observatory]] in London was chosen as the defining point of the [[Prime Meridian]]<ref>{{Cite web |last=ROG Learning Team |date=23 August 2002 |title=The Prime Meridian at Greenwich |url=http://www.rmg.co.uk/explore/astronomy-and-time/astronomy-facts/history/the-prime-meridian-at-greenwich |archive-url=https://web.archive.org/web/20151107023957/http://www.rmg.co.uk/explore/astronomy-and-time/astronomy-facts/history/the-prime-meridian-at-greenwich |archive-date=7 November 2015 |access-date=11 September 2012 |website=Royal Museums Greenwich}}</ref> at the [[International Meridian Conference]] in 1884.<ref>{{Cite news |date=13 August 2015 |title=Greenwich Royal Observatory: How the Prime Meridian line is actually 100 metres away from where it was believed to be |work=Independent |location=London |url=https://www.independent.co.uk/news/science/greenwich-royal-observatory-how-the-prime-meridian-line-is-actually-100-metres-away-from-where-it-10452386.html |access-date=13 December 2018 |archive-date=23 March 2019 |archive-url=https://web.archive.org/web/20190323081414/https://www.independent.co.uk/news/science/greenwich-royal-observatory-how-the-prime-meridian-line-is-actually-100-metres-away-from-where-it-10452386.html |url-status=live}}</ref>
The UK lies between latitudes [[49th parallel north|49°]] and [[61st parallel north|61° N]], and longitudes [[9th meridian west|9° W]] and [[2nd meridian east|2° E]]. Northern Ireland shares a {{Convert|499|km|mi|0|adj=on|order=flip}} land boundary with the Republic of Ireland<ref name="factbook" /> and has a {{Convert|650|km|mi|0|adj=on|order=flip}} coastline.<ref name="NI coastline">{{Cite web |title=Northern Ireland Coastal and Marine Forum |url=https://library2.nics.gov.uk/pdf/dard/2014/EEUD.pdf |archive-url=https://web.archive.org/web/20241123094028/https://library2.nics.gov.uk/pdf/dard/2014/EEUD.pdf |archive-date=23 November 2024 |access-date=13 March 2025 |publisher=Northern Ireland Coastal and Marine Forum}}</ref> The length of coastline of Great Britain plus its principal islands is about {{Convert|31368|km|mi|0|order=flip}} long, with the coastline of the main island Great Britain being {{Convert|17820|km|mi|0|order=flip}} of that,<ref name="UK coastline">{{Cite web |last=Darkes |first=Giles |date=January 2008 |title=How long is the UK coastline? |url=http://www.cartography.org.uk/default.asp?contentID=749 |archive-url=https://web.archive.org/web/20120522042745/http://www.cartography.org.uk/default.asp?contentID=749 |archive-date=22 May 2012 |access-date=24 January 2015 |publisher=The [[British Cartographic Society]]}}</ref> though measurements can vary greatly due to the [[coastline paradox]].<ref>{{Cite web |last=Weiner |first=Sophie |date=3 March 2018 |title=Why it's Impossible to Accurately Measure a Coastline |url=https://www.popularmechanics.com/science/environment/a19068718/why-its-impossible-to-accurately-measure-a-coastline/ |access-date=29 June 2024 |website=Popular Mechanics |archive-date=29 June 2024 |archive-url=https://web.archive.org/web/20240629025825/https://www.popularmechanics.com/science/environment/a19068718/why-its-impossible-to-accurately-measure-a-coastline/ |url-status=live}}</ref> It is connected to continental Europe by the [[Channel Tunnel]], which at {{Convert|50|km|mi|0|order=flip}} ({{Convert|38|km|mi|0|order=flip}} underwater) is the longest underwater tunnel in the world.<ref>{{Cite web |title=The Channel Tunnel |url=http://www.eurotunnel.com/ukcP3Main/ukcCorporate/ukcTunnelInfrastructure/ukcInfrastructure |archive-url=https://web.archive.org/web/20101218114514/http://www.eurotunnel.com/ukcP3Main/ukcCorporate/ukcTunnelInfrastructure/ukcInfrastructure |archive-date=18 December 2010 |access-date=8 March 2015 |publisher=Eurotunnel}}</ref>
The UK contains four terrestrial [[ecoregion]]s: [[Celtic broadleaf forests]], [[English Lowlands beech forests]], [[North Atlantic moist mixed forests]], and [[Caledonian Forest|Caledonian conifer forests]].<ref>{{Cite journal |last1=Dinerstein |first1=Eric |last2=Olson |first2=David |last3=Joshi |first3=Anup |last4=Vynne |first4=Carly |last5=Burgess |first5=Neil D. |last6=Wikramanayake |first6=Eric |last7=Hahn |first7=Nathan |last8=Palminteri |first8=Suzanne |last9=Hedao |first9=Prashant |last10=Noss |first10=Reed |last11=Hansen |first11=Matt |last12=Locke |first12=Harvey |last13=Ellis |first13=Erle C |last14=Jones |first14=Benjamin |last15=Barber |first15=Charles Victor |display-authors=1 |year=2017 |title=An Ecoregion-Based Approach to Protecting Half the Terrestrial Realm |journal=BioScience |volume=67 |issue=6 |pages=534–545 |doi=10.1093/biosci/bix014 |issn=0006-3568 |pmc=5451287 |pmid=28608869 |doi-access=free |last16=Hayes |first16=Randy |last17=Kormos |first17=Cyril |last18=Martin |first18=Vance |last19=Crist |first19=Eileen |last20=Sechrest |first20=Wes |last21=Price |first21=Lori |last22=Baillie |first22=Jonathan E. M. |last23=Weeden |first23=Don |last24=Suckling |first24=Kierán |last25=Davis |first25=Crystal |last26=Sizer |first26=Nigel |last27=Moore |first27=Rebecca |last28=Thau |first28=David |last29=Birch |first29=Tanya |last30=Potapov |first30=Peter |last31=Turubanova |first31=Svetlana |last32=Tyukavina |first32=Alexandra |last33=de Souza |first33=Nadia |last34=Pintea |first34=Lilian |last35=Brito |first35=José C. |last36=Llewellyn |first36=Othman A. |last37=Miller |first37=Anthony G. |last38=Patzelt |first38=Annette |last39=Ghazanfar |first39=Shahina A. |last40=Timberlake |first40=Jonathan |last41=Klöser |first41=Heinz |last42=Shennan-Farpón |first42=Yara |last43=Kindt |first43=Roeland |last44=Lillesø |first44=Jens-Peter Barnekow |last45=van Breugel |first45=Paulo |last46=Graudal |first46=Lars |last47=Voge |first47=Maianna |last48=Al-Shammari |first48=Khalaf F. |last49=Saleem |first49=Muhammad}}</ref> The area of woodland in the UK was estimated to be 3.25 million hectares in 2023, which represents 13 per cent of its land area.<ref>{{Cite web |url=https://www.forestresearch.gov.uk/tools-and-resources/statistics/statistics-by-topic/woodland-statistics/ |title=Woodland Statistics, Key findings |work=Forest Research |access-date=8 July 2023 |archive-date=2 August 2023 |archive-url=https://web.archive.org/web/20230802030149/https://www.forestresearch.gov.uk/tools-and-resources/statistics/statistics-by-topic/woodland-statistics/ |url-status=live}}</ref>
=== Climate ===
{{Main|Climate of the United Kingdom|Climate change in the United Kingdom}}
{{Further|Climate of England|Climate of Scotland|Climate of Wales|Climate of Northern Ireland}}
Most of the United Kingdom has a temperate climate, with generally cool temperatures and plentiful rainfall all year round.<ref name="factbook" /> The temperature varies with the seasons rarely dropping below {{Convert|0|C|lk=on}} or rising above {{Convert|30|C}}.<ref>{{Cite web |title=Hottest day of each year from 1900 |url=https://www.trevorharley.com/hottest-day-of-each-year-from-1900.html |website=trevorharley.com |access-date=23 November 2019 |archive-date=16 June 2023 |archive-url=https://web.archive.org/web/20230616173152/https://www.trevorharley.com/hottest-day-of-each-year-from-1900.html |url-status=live}}; {{Cite web |title=Coldest day of each year from 1900 |url=https://www.trevorharley.com/coldest-days-of-each-year-from-1900.html |website=trevorharley.com |access-date=23 November 2019 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709173537/https://www.trevorharley.com/coldest-days-of-each-year-from-1900.html |url-status=live}}</ref> Some parts, away from the coast, of upland England, Wales, Northern Ireland and most of Scotland, experience a [[subpolar oceanic climate]]. Higher elevations in Scotland experience a [[Subarctic climate|continental subarctic climate]] and the mountains experience a [[tundra climate]].<ref>{{Cite web |date=9 August 2016 |title=English: A map of Köppen climate types in the United Kingdom (SVG version) |url=https://commons.wikimedia.org/wiki/File:UK_K%C3%B6ppen.svg |access-date=23 November 2019 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709202702/https://commons.wikimedia.org/wiki/File:UK_K%C3%B6ppen.svg |url-status=live}}</ref>
The prevailing wind is from the southwest and bears frequent spells of mild and wet weather from the Atlantic Ocean,<ref name="factbook" /> although the eastern parts are mostly sheltered from this wind. Since the majority of the rain falls over the western regions, the eastern parts are the driest. Atlantic currents, warmed by the [[Gulf Stream]], bring mild winters, especially in the west where winters are wet and even more so over high ground. Summers are warmest in the southeast of England and coolest in the north. Heavy snowfall can occur in winter and early spring on high ground, and occasionally settles to great depth away from the hills.<ref>{{Cite web |title=Atlantic Ocean Circulation (Gulf Stream) |url=http://ukclimateprojections.metoffice.gov.uk/23152 |access-date=8 March 2015 |website=UK Climate Projections |publisher=Met Office |archive-date=17 October 2018 |archive-url=https://web.archive.org/web/20181017162552/http://ukclimateprojections.metoffice.gov.uk/23152 |url-status=live}}</ref>
The average total annual sunshine in the United Kingdom was 1,339.7 hours between 1971 and 2000.<ref name="ukaverages">{{cite web |title=UK 1971–2000 averages |url=http://www.metoffice.gov.uk/climate/uk/averages/19712000/areal/uk.html |url-status=dead |archive-url=https://web.archive.org/web/20090705140124/http://www.metoffice.gov.uk/climate/uk/averages/19712000/areal/uk.html |archive-date=5 July 2009 |access-date=4 August 2007 |publisher=Met Office}}</ref> The hours of sunshine vary from 1,200 to about 1,580 hours per year.<ref name="met off climate series">{{Cite web |url=https://www.metoffice.gov.uk/research/climate/maps-and-data/uk-temperature-rainfall-and-sunshine-time-series |title=UK temperature, rainfall and sunshine time series |website=Met Office |access-date=31 December 2022 |archive-date=17 October 2019 |archive-url=https://web.archive.org/web/20191017203556/https://www.metoffice.gov.uk/research/climate/maps-and-data/uk-temperature-rainfall-and-sunshine-time-series |url-status=live}}</ref>
Climate change has serious impacts on the country. A third of food price rise in 2023 was attributed to it.<ref>{{cite web |last1=Smeeton |first1=George |title=Families hit by £605 food bill as extreme weather and energy crisis bites |url=https://eciu.net/media/press-releases/2023/families-hit-by-605-food-bill-as-extreme-weather-and-energy-crisis-bites |website=Energy & Climate Intelligence Unit |date=28 November 2023 |access-date=19 July 2024 |archive-date=16 July 2024 |archive-url=https://web.archive.org/web/20240716124143/https://eciu.net/media/press-releases/2023/families-hit-by-605-food-bill-as-extreme-weather-and-energy-crisis-bites |url-status=live}}</ref> In 2024 the United Kingdom ranked 5th out of 180 countries in the [[Environmental Performance Index]].<ref>{{Cite web |title=2024 Environmental Performance Index |url=https://epi.yale.edu/measure/2024/EPI |access-date=27 May 2025 |website=Environmental Performance Index |language=en |archive-date=10 July 2024 |archive-url=https://web.archive.org/web/20240710023935/https://epi.yale.edu/measure/2024/EPI |url-status=live }}</ref> A law has been passed that [[Greenhouse gas emissions by the United Kingdom|UK greenhouse gas emissions]] will be [[net zero]] by 2050.<ref>{{Cite web |title=UK net zero target |url=https://www.instituteforgovernment.org.uk/explainers/net-zero-target#:~:text=In%20June%202019%2C%20parliament%20passed,to%201990%20levels%20by%202050.&text=Prior%20to%20this%2C%20the%20UK,1990%20levels%2C%20also%20by%202050. |access-date=20 March 2024 |website=Institute for Government |date=20 April 2020|last=Shepheard|first=Marcus}}</ref>{{Update after|2050|01|01|category|reason=Hello from 2024! By the time you're reading this, that law will be a little older than 30 years old. Could you check if the UK ever ended up hitting that net zero GHG target?}}
=== Topography ===
[[File:uk topo en.jpg|thumb|right|The United Kingdom's topography]]
[[Geography of England|England]] accounts for 53 per cent of the UK, covering {{Convert|130395|km2|sqmi|order=flip|-1}}.<ref>{{Cite news |date=11 February 2010 |title=England – Profile |work=BBC News |url=http://news.bbc.co.uk/2/hi/europe/country_profiles/7327029.stm |access-date=9 October 2010 |archive-date=15 April 2018 |archive-url=https://web.archive.org/web/20180415064122/http://news.bbc.co.uk/1/hi/world/europe/country_profiles/7327029.stm |url-status=live}}</ref> Most of the country consists of lowland terrain,<ref name="Atlapedia">{{Cite web |last=Latimer Clarke Corporation Pty Ltd |title=United Kingdom – Atlapedia Online |url=http://www.atlapedia.com/online/countries/unitedki.htm |access-date=26 October 2010 |website=Atlapedia.com |archive-date=21 March 2012 |archive-url=https://web.archive.org/web/20120321191308/http://www.atlapedia.com/online/countries/unitedki.htm |url-status=live}}{{better source needed|date=July 2023}}</ref> with upland and mountainous terrain northwest of the [[Tees–Exe line]] which roughly divides the UK into [[lowland and upland]] areas. Lowland areas include [[Cornwall]], the [[New Forest]], the [[South Downs]] and the [[The Broads|Norfolk Broads]]. Upland areas include the [[Lake District]], the [[Pennines]], the [[Yorkshire Dales]], [[Exmoor]] and [[Dartmoor]]. The main rivers and estuaries are the [[River Thames|Thames]], [[River Severn|Severn]], and the [[Humber]]. England's highest mountain is [[Scafell Pike]], at {{Convert|978|m|ft|0}} in the Lake District; its largest island is the [[Isle of Wight]].
[[Geography of Scotland|Scotland]] accounts for 32 per cent of the UK, covering {{Convert|78772|km2|sqmi|order=flip|-1}}.<ref>{{Cite web |title=Scotland Facts |url=http://www.scotland.org/about/fact-file/index.html |archive-url=https://web.archive.org/web/20080621045248/http://www.scotland.org/about/fact-file/index.html |archive-date=21 June 2008 |access-date=16 July 2008 |publisher=Scotland Online Gateway}}</ref> This includes [[List of islands of Scotland|nearly 800 islands]],<ref>{{Cite news |last=Winter |first=Jon |date=1 June 2000 |title=The complete guide to the ... Scottish Islands |work=Independent |location=London |url=https://www.independent.co.uk/travel/uk/the-complete-guide-to-the--scottish-islands-633851.html |access-date=8 March 2015 |archive-date=2 April 2015 |archive-url=https://web.archive.org/web/20150402164423/http://www.independent.co.uk/travel/uk/the-complete-guide-to-the--scottish-islands-633851.html |url-status=live}}</ref> notably the [[Hebrides]], [[Orkney]] Islands and [[Shetland Islands]]. Scotland is the most mountainous constituent country of the UK. The [[Scottish Highlands|Highlands]] to the north and west are the more rugged region containing the majority of Scotland's mountainous land, including the [[Cairngorms]], [[Loch Lomond and The Trossachs]] and [[Ben Nevis]] which at {{Convert|1345|m|ft|0}}<ref>{{Cite web |date=18 March 2016 |title=Great Britain's tallest mountain is taller |work=Ordnance Survey Blog |url=https://www.ordnancesurvey.co.uk/blog/2016/03/britains-tallest-mountain-is-taller |access-date=9 September 2018 |publisher=Ordnance Survey |archive-date=9 September 2018 |archive-url=https://web.archive.org/web/20180909000504/https://www.ordnancesurvey.co.uk/blog/2016/03/britains-tallest-mountain-is-taller/ |url-status=live}}</ref> is the highest point in the British Isles.<ref>{{Cite web |title=Ben Nevis Weather |url=http://www.bennevisweather.co.uk/index.asp |archive-url=https://web.archive.org/web/20120510193022/http://www.bennevisweather.co.uk/index.asp |archive-date=10 May 2012 |access-date=26 October 2008 |publisher=Ben Nevis Weather}}</ref>
[[Geography of Wales|Wales]] accounts for less than 9 per cent of the UK, covering {{Convert|20779|km2|sqmi|order=flip|-1}}.<ref>{{Cite news |date=9 June 2010 |title=Profile: Wales |work=BBC News |url=http://news.bbc.co.uk/2/hi/europe/country_profiles/6233450.stm |access-date=7 November 2010 |archive-date=26 August 2018 |archive-url=https://web.archive.org/web/20180826085704/http://news.bbc.co.uk/2/hi/europe/country_profiles/6233450.stm |url-status=live}}</ref> It is mostly mountainous, though [[South Wales]] is less mountainous than [[North Wales|North]] and [[Mid Wales]]. The highest mountains in Wales are in [[Snowdonia]] and include [[Snowdon]] ({{Langx|cy|Yr Wyddfa}}) which, at {{Convert|1085|m|ft|0}}, is the highest peak in Wales.<ref name="Atlapedia" /> Wales has over {{Convert|1680|mi|0|abbr=off}} of coastline including the [[Pembrokeshire Coast]].<ref name="UK coastline" /> Several islands lie off the Welsh mainland, the largest of which is [[Anglesey]] (''Ynys Môn'').
[[Geography of Ireland|Northern Ireland]], separated from Great Britain by the [[Irish Sea]] and [[North Channel (Great Britain and Ireland)|North Channel]], has an area of {{Convert|14160|km2|sqmi|order=flip|-1}} and is mostly hilly. It includes [[Lough Neagh]] which, at {{Convert|388|km2|sqmi|order=flip|0}}, is the largest lake in the British Isles by area,<ref>{{Cite web |title=Geography of Northern Ireland |url=http://cain.ulst.ac.uk/ni/geog.htm |access-date=22 May 2006 |publisher=University of Ulster |archive-date=18 January 2012 |archive-url=https://web.archive.org/web/20120118133131/http://cain.ulst.ac.uk/ni/geog.htm |url-status=live}}</ref> [[Lough Erne]], which has over 150 islands, and the [[Giant's Causeway]], which is listed by [[UNESCO]] as a [[World Heritage Site]]. The highest peak in Northern Ireland is [[Slieve Donard]] in the [[Mourne Mountains]] at {{Convert|852|m|ft|0}}.<ref name="Atlapedia" />
== Government and politics ==
{{Main|Politics of the United Kingdom|Government of the United Kingdom|Monarchy of the United Kingdom}}
{{Further|Constitution of the United Kingdom}}{{Multiple image
| direction = horizontal
| align = right
| caption_align = center
| total_width = 320
| image1 = King Charles III (July 2023).jpg
| image2 = Prime Minister Andy Burnham portrait (cropped).jpg
| caption1 = {{nowrap|[[Charles III]]}}<br>[[Monarch of the United Kingdom|King]]
| caption2 = {{nowrap|[[Andy Burnham]]}}<br>{{nowrap|[[Prime Minister of the United Kingdom|Prime Minister]]}}
| alt1 =
| alt2 =
}}
The United Kingdom is a [[constitutional monarchy]] and a [[parliamentary democracy]]<ref>[http://www.royal.gov.uk/MonarchUK/HowtheMonarchyworks/Whatisconstitutionalmonarchy.aspx The British Monarchy, "What is constitutional monarchy?"] {{Webarchive|url=https://web.archive.org/web/20190604151257/http://www.royal.gov.uk/MonarchUK/HowtheMonarchyworks/Whatisconstitutionalmonarchy.aspx|date=4 June 2019}}. Retrieved 17 July 2013; [https://www.cia.gov/the-world-factbook/countries/united-kingdom/ "United Kingdom"] {{Webarchive|url=https://web.archive.org/web/20210109221834/https://www.cia.gov/the-world-factbook/countries/united-kingdom/|date=9 January 2021}} CIA ''The World Factbook''. Retrieved 17 July 2013</ref> operating under the [[Westminster system]], otherwise known as a "democratic parliamentary monarchy".<ref>{{Cite journal |last1=Stepan |first1=Alfred |last2=Linz |first2=Juan J. |last3=Minoves |first3=Juli F. |date=2014 |title=Democratic Parliamentary Monarchies |url=http://muse.jhu.edu/content/crossref/journals/journal_of_democracy/v025/25.2.stepan.html |journal=Journal of Democracy |volume=25 |issue=2 |pages=35–36 |doi=10.1353/jod.2014.0032 |issn=1086-3214 |s2cid=154555066 |url-access=subscription |archive-date=31 January 2026 |access-date=11 January 2023 |archive-url=https://web.archive.org/web/20260131155632/https://muse.jhu.edu/content/crossref/journals/journal_of_democracy/v025/25.2.stepan.html |url-status=live }}</ref> It is a [[Centralized government|centralised]], [[unitary state]]<ref>{{Cite web |last=Lewer |first=Andrew |date=5 May 2021 |title=The UK is one of the most centralised advanced democracies – it's time that changed |url=https://www.newstatesman.com/spotlight/2021/05/the-uk-is-one-of-the-most-centralised-advanced-democracies-its-time-that-changed |access-date=3 July 2023 |website=[[New Statesman]] |archive-date=3 July 2023 |archive-url=https://web.archive.org/web/20230703131907/https://www.newstatesman.com/spotlight/2021/05/the-uk-is-one-of-the-most-centralised-advanced-democracies-its-time-that-changed |url-status=live|author-link=Andrew Lewer}}</ref><ref>{{Cite web |title=Centralisation Nation: Britain's system of local government and its impact on the national economy |url=https://www.centreforcities.org/?post_type=publication&p=40951 |access-date=3 July 2023 |website=Centre for Cities |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141833/https://www.centreforcities.org/publication/centralisation-nation/ |url-status=live}}</ref> wherein the [[Parliament of the United Kingdom]] is [[Parliamentary sovereignty in the United Kingdom|sovereign]].<ref>{{Cite web |title=Parliamentary Sovereignty |url=https://www.parliament.uk/site-information/glossary/parliamentary-sovereignty |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=11 August 2021 |archive-url=https://web.archive.org/web/20210811195135/https://www.parliament.uk/site-information/glossary/parliamentary-sovereignty/ |url-status=live}}</ref> Parliament is made up of the elected [[House of Commons of the United Kingdom|House of Commons]], the appointed [[House of Lords]] and [[the Crown]] (as personified by [[Monarchy of the United Kingdom|the monarch]]).{{Efn|British [[sovereignty]] derives from the Crown, a [[corporation sole]] occupied by the monarch. It is therefore by and through the monarch that Parliament exercises supreme legislative authority over both the executive and judiciary. Distinguished Professor of [[Public Law]] Maurice Sunkin opined the Crown symbolically occupies "...what in other places would be a core element of a written constitution."<ref>{{Cite web |url=https://www.ibanet.org/Relationship-between-UK-Crown-and-law-in-focus-as-Carolean-era-begins |title=Relationship between UK Crown and law in focus as Carolean era begins |author=Polly Botsford |publisher=International Bar Association |publication-date=22 September 2022 |access-date=4 July 2023 |archive-date=6 May 2023 |archive-url=https://web.archive.org/web/20230506211218/https://www.ibanet.org/Relationship-between-UK-Crown-and-law-in-focus-as-Carolean-era-begins |url-status=live}}</ref> As a result of this state of constitutional affairs, the monarch is formally referred to as "[[Sovereign|the Sovereign]]" in legislation.<ref>{{Cite web |url=https://www.legislation.gov.uk/ukpga/1978/30/section/10 |title=Interpretation Act 1978 (c. 30, s. 10) |publisher=The National Archives |access-date=4 July 2023 |archive-date=30 July 2023 |archive-url=https://web.archive.org/web/20230730073659/https://www.legislation.gov.uk/ukpga/1978/30/section/10 |url-status=live}}</ref>}}<ref name="parliament.uk">{{Cite web |title=Parliament |url=https://www.parliament.uk/about/how/role |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=18 February 2026 |archive-url=https://web.archive.org/web/20260218150954/https://www.parliament.uk/about/how/role/ |url-status=live }}</ref> The main business of Parliament takes place in the two houses,<ref name="parliament.uk" /> but [[royal assent]] is required for a bill to become an [[Act of Parliament (UK)|act of Parliament]] (that is, [[statute law]]).<ref>{{Cite web |title=Royal Assent |url=https://www.parliament.uk/about/how/laws/passage-bill/lords/lrds-royal-assent |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=16 July 2021 |archive-url=https://web.archive.org/web/20210716022947/https://www.parliament.uk/about/how/laws/passage-bill/lords/lrds-royal-assent/ |url-status=live}}</ref> As a result of parliamentary sovereignty, the [[Constitution of the United Kingdom|British constitution]] is [[Uncodified constitution|uncodified]], consisting mostly of disparate written sources, including parliamentary [[statute]]s, judge-made [[case law]] and international treaties, together with [[British Constitution#Conventions|constitutional conventions]].<ref>{{Cite web |last=Carter, Sarah |title=A Guide To the UK Legal System |url=http://www.llrx.com/features/uk2.htm#UK%20Legal%20System |archive-url=https://web.archive.org/web/20120505115306/http://www.llrx.com/features/uk2.htm |archive-date=5 May 2012 |access-date=16 May 2006 |publisher=[[University of Kent]] at Canterbury}}</ref> Nevertheless, the [[Supreme Court of the United Kingdom|Supreme Court]] recognises a number of principles underlying the British constitution, such as parliamentary sovereignty, the [[rule of law]], [[democracy]] and upholding [[Internationalism (politics)|international law]].<ref>See ''[[R (Miller) v Prime Minister]]'' [2019] UKSC 41 (Parliamentary sovereignty), ''[[R (UNISON) v Lord Chancellor]]'' [2017] [http://www.bailii.org/uk/cases/UKSC/2017/51.html UKSC 51] {{Webarchive|url=https://web.archive.org/web/20230104095357/https://www.bailii.org/uk/cases/UKSC/2017/51.html|date=4 January 2023}}, [67] ff (rule of law), ''[[R (Animal Defenders International) v Secretary of State for Culture Media and Sport]]'' [2008] UKHL 15, [48] (democracy), ''[[R v Lyons]]'' [2002] [https://www.bailii.org/uk/cases/UKHL/2002/44.html UKHL 44] {{Webarchive|url=https://web.archive.org/web/20230122064021/https://www.bailii.org/uk/cases/UKHL/2002/44.html|date=22 January 2023}}, [27] (international law).</ref>
[[Charles III|King Charles III]] is the [[monarch]] and [[head of state]] of the United Kingdom and 14 other independent [[sovereign state]]s, referred to as "[[Commonwealth realm]]s". The monarch is formally vested with all executive authority as the personal embodiment of [[the Crown]] and is "fundamental to the law and working of government in the UK".<ref>{{Cite journal |url=https://kclpure.kcl.ac.uk/portal/en/publications/the-constitutional-role-and-working-of-the-monarchy-in-the-united |title=The Constitutional Role and Working of the Monarchy in the United Kingdom |author=Robert Blackburn |journal=Jahrbuch des Öffentlichen Rechts der Gegenwart |series=Neue Folge |year=2022 |volume=70 |pages=181–201 |editor=O. Lepsius |editor2=A. Nußberger |editor3=C. Schönberger |editor4=C. Waldhoff |editor5=C. Walter |name-list-style=amp |publisher=Mohr Siebeck |doi=10.1628/joer-2022-0009 |s2cid=257830288 |publication-date=2 June 2022 |access-date=19 June 2023 |archive-date=19 June 2023 |archive-url=https://web.archive.org/web/20230619174428/https://kclpure.kcl.ac.uk/portal/en/publications/the-constitutional-role-and-working-of-the-monarchy-in-the-united |url-status=live}}</ref> The disposition of such powers however, including those belonging to the [[Royal prerogative in the United Kingdom|royal prerogative]], is generally exercised only on the [[Advice (constitutional law)|advice]] of [[ministers of the Crown]] responsible to Parliament and thence to the electorate. Nevertheless, in the performance of official duties the monarch has "the right to be consulted, the right to encourage, and the right to warn".<ref>[[Walter Bagehot|Bagehot, Walter]] (1867). ''The English Constitution''. London: Chapman and Hall. p. 103.</ref> In addition the monarch has a number of [[Reserve power#United Kingdom|reserve powers]] at his disposal to uphold [[responsible government]] and prevent [[constitutional crisis|constitutional crises]].{{Efn|For instance, the monarch alone appoints the prime minister and confers [[Orders, decorations, and medals of the United Kingdom|state honours]] in the personal gift of the Crown. When necessary, the monarch may also refuse a [[dissolution of Parliament|dissolution]] or [[Prorogation in the United Kingdom|prorogation of Parliament]], withhold [[royal assent]] to [[Act of Parliament (UK)|primary legislation]], and prevent illegal use of the [[British Armed Forces]], amongst other reserve powers.<ref>{{Cite web |url=https://researchbriefings.files.parliament.uk/documents/CBP-8885/CBP-8885.pdf |title=The Crown and the Constitution |author=David Torrance |publisher=House of Commons Library |publication-date=11 January 2023 |access-date=19 June 2023 |pages=22 |archive-date=2 March 2023 |archive-url=https://web.archive.org/web/20230302033737/https://researchbriefings.files.parliament.uk/documents/CBP-8885/CBP-8885.pdf |url-status=live}}</ref>}}
The prime minister is the [[head of government]] in the United Kingdom.<ref>{{Cite web |title=The Government, Prime Minister and Cabinet |url=http://direct.gov.uk/en/Governmentcitizensandrights/UKgovernment/Centralgovernmentandthemonarchy/DG_073444 |archive-url=https://web.archive.org/web/20120921004951/http://www.direct.gov.uk/en/Governmentcitizensandrights/UKgovernment/Centralgovernmentandthemonarchy/DG_073444 |archive-date=21 September 2012 |access-date=9 March 2015 |website=Public services all in one place |publisher=[[Directgov]]}}</ref> Acting under the direction and supervision of a [[Cabinet of the United Kingdom|Cabinet]] of senior ministers selected and led by the prime minister, [[His Majesty's Government]] serves as the principal instrument for public policymaking, administers public services and, through the [[Privy Council of the United Kingdom|Privy Council]], promulgates [[statutory instrument (UK)|statutory instruments]] and tenders advice to the monarch.<ref>{{Cite web |url=https://www.instituteforgovernment.org.uk/explainer/cabinet |title=Cabinet |author=Tim Durrant |date=25 March 2020 |publisher=Institute for Government |publication-date=25 March 2020 |access-date=4 July 2023 |archive-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704112925/https://www.instituteforgovernment.org.uk/explainer/cabinet |url-status=live}}</ref><ref>{{Cite web |url=https://www.parliament.uk/about/how/role/relations-with-other-institutions/parliament-government/ |title=Parliament and Government |publisher=UK Parliament |access-date=4 July 2023 |archive-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704112925/https://www.parliament.uk/about/how/role/relations-with-other-institutions/parliament-government/ |url-status=live}}</ref><ref>{{Cite book |url=https://books.google.com/books?id=mN6SzMefot4C |title=The Monarchy and the Constitution, Chapter 3 – The Basic Constitutional Rules: Influence and the Prerogative |author=Vernon Bogdanor |year=1995 |publisher=Clarendon Press |isbn=978-0-19-829334-7 |publication-date=1995 |access-date=4 July 2023}}</ref> Nearly all prime ministers have served concurrently as [[First Lord of the Treasury]]<ref>{{Cite web |last1=Blick |first1=Andrew |last2=Jones |first2=George |date=1 January 2012 |title=The Institution of Prime Minister – History of government |url=https://history.blog.gov.uk/2012/01/01/the-institution-of-prime-minister |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=21 July 2021 |archive-url=https://web.archive.org/web/20210721060401/https://history.blog.gov.uk/2012/01/01/the-institution-of-prime-minister/ |url-status=live}}</ref> and all prime ministers have continuously served as First Lord of the Treasury since 1905,<ref>{{Cite book |last=Brown |first=Jack |title=The Prime Ministers |publisher=[[Hodder & Stoughton]] |year=2020 |isbn=978-1-5293-1214-0 |editor-last=Dale |editor-first=Iain |page=303}}</ref> [[Minister for the Civil Service]] since 1968,<ref>{{Cite web |title=Minister for the Civil Service |url=https://www.gov.uk/government/ministers/minister-for-the-civil-service |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=2 September 2017 |archive-url=https://web.archive.org/web/20170902233116/https://www.gov.uk/government/ministers/minister-for-the-civil-service |url-status=live}}</ref> and [[Minister for the Union]] since 2019.<ref>{{Cite news |last=Woodcock |first=Andrew |date=26 July 2021 |title=Boris Johnson accused of 'cynical rebranding' after appointing himself 'Minister for the Union' |work=[[The Independent|Independent]] |url=https://www.independent.co.uk/news/uk/politics/boris-johnson-minister-union-scotland-independence-referendum-snp-a9022356.html |access-date=19 July 2021 |archive-date=27 July 2019 |archive-url=https://web.archive.org/web/20190727080405/https://www.independent.co.uk/news/uk/politics/boris-johnson-minister-union-scotland-independence-referendum-snp-a9022356.html |url-status=live}}; {{Cite web |title=Minister for the Union |url=https://www.gov.uk/government/ministers/minister-for-the-union |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=19 July 2020 |archive-url=https://web.archive.org/web/20200719053618/https://www.gov.uk/government/ministers/minister-for-the-union |url-status=live}}</ref> While appointed by the monarch, in modern times the prime minister is, by [[Constitutional conventions of the United Kingdom|convention]], an MP, the leader of the political party with the most seats in the House of Commons, and holds office by virtue of their ability to [[Confidence motions in the United Kingdom|command the confidence]] of the House of Commons.<ref>{{Cite web |date=October 2011 |title=The Cabinet Manual |url=https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/60641/cabinet-manual.pdf |access-date=19 July 2021 |website=[[gov.uk]] |pages=7, 21 |archive-date=15 April 2018 |archive-url=https://web.archive.org/web/20180415090557/https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/60641/cabinet-manual.pdf |url-status=live}}</ref><ref>{{Cite book |last=Norton |first=Philip |title=Governing Britain: Parliament, Ministers and Our Ambiguous Constitution |publisher=[[Manchester University Press]] |year=2020 |isbn=978-1-5261-4545-1 |page=130}}</ref> The prime minister as of 20 July 2026, is [[Andy Burnham]], the [[Leader of the Labour Party (UK)|leader of the Labour Party]].
Although not part of the United Kingdom, the three [[Crown Dependencies]] of [[Jersey]], [[Guernsey]] and the [[Isle of Man]], as well as the 14 [[British Overseas Territories]], are subject to the sovereignty of the British Crown.<ref>{{cite book |last=Palan |first=Rolen |editor-last1=Palan |editor-first1=Rolen |editor-last2=Halperin |editor-first2=Sandra |chapter=The second British Empire and the re-emergence of global finance |chapter-url=https://books.google.com/books?id=76QyCgAAQBAJ&dq=%22British+overseas+territories%22+%22crown+dependencies%22+UK+%22British+crown%22&pg=PA48 |title=Legacies of Empire: Imperial Roots of the Contemporary Global Order |year=2015 |publisher=Cambridge University Press |isbn=978-1-107-10946-9 |page=48 |access-date=13 April 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212946/https://books.google.com/books?id=76QyCgAAQBAJ&dq=%22British+overseas+territories%22+%22crown+dependencies%22+UK+%22British+crown%22&pg=PA48#v=onepage&q=%22British%20overseas%20territories%22%20%22crown%20dependencies%22%20UK%20%22British%20crown%22&f=false |url-status=live}}</ref>
[[Democratic backsliding]] was found by the 2026 [[V-Dem Institute#Democracy Report|V-Dem Democracy Report]] for the United Kingdom.<ref name="j496">{{cite web | title=Democracy Report 2026, Unraveling The Democratic Era? | url=https://v-dem.net/documents/75/V-Dem_Institute_Democracy_Report_2026_lowres.pdf | access-date=2026-03-17}}</ref>
===Elections===
{{Main|Elections in the United Kingdom}}
[[File:Houses of Parliament in 2022 (cropped).jpg|thumb|upright=1.25|alt=Large sand-coloured building of Gothic design beside brown river. The building has several large towers, including large clock tower.|The [[Palace of Westminster]] in London is the seat of both houses of the Parliament of the United Kingdom.]]
For [[General elections in the United Kingdom|general elections]] (elections to the House of Commons), the United Kingdom is divided into 650 [[United Kingdom constituencies|constituencies]], each of which is represented by one [[Member of Parliament (United Kingdom)|member of Parliament]] (MP) elected by the [[First-past-the-post voting|first-past-the-post]] system.<ref name="parliament.uk-2">{{Cite web |title=General elections |url=https://www.parliament.uk/about/how/elections-and-voting/general |access-date=19 July 2021 |website=[[parliament.uk]]}}</ref> MPs hold office for up to five years and must then stand for re-election if they wish to continue to be an MP.<ref name="parliament.uk-2" /> The [[Conservative Party (UK)|Conservative Party]], colloquially known as the Tory Party or the Tories, and the [[Labour Party (UK)|Labour Party]] have been the dominant political parties in the country since the 1920s, leading to the UK being described as a [[two-party system]]. However, since the 1920s other [[List of political parties in the United Kingdom|political parties]] have won seats in the House of Commons, although never more than the Conservatives or Labour.<ref>{{Cite web |last=Raymond |first=C |date=2016 |title=Why British Politics is Not a Two-Party System |url=https://pureadmin.qub.ac.uk/ws/portalfiles/portal/107735631/The_United_Kingdom_is_Not_a_Two_Party_System.pdf |website=Queen's University Belfast |access-date=3 July 2023 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709172832/https://pureadmin.qub.ac.uk/ws/portalfiles/portal/107735631/The_United_Kingdom_is_Not_a_Two_Party_System.pdf |url-status=live}}</ref> The 2020s marked the erosion of the two-party system and the growth of a multi-party system.<ref>{{Cite web |date=2026-05-08 |title=Sir John Curtice: Election results show politics in the UK has fragmented |url=https://www.bbc.com/news/articles/ce8p4yn448vo |access-date=2026-05-09 |website=[[BBC News]] |language=en-GB}}</ref>
=== Administrative divisions ===
{{Main|Countries of the United Kingdom|Administrative geography of the United Kingdom|List of counties in the United Kingdom}}
[[File:United Kingdom labelled map7 vector.svg|thumb|upright=0.8|The four countries of the United Kingdom]]
The geographical division of the United Kingdom into counties or [[shire]]s began in England and Scotland in the [[early Middle Ages]], and was completed throughout Great Britain and Ireland by the [[early modern period]].<ref>Hackwood Frederick William: ''The Story of the Shire, Being the Lore, History and Evolution of English County Institutions'' (1851)</ref> Modern [[local government]] by elected councils, partly based on the ancient counties, was established by separate Acts of Parliament: in England and Wales [[Local Government Act 1888|in 1888]], Scotland [[Local Government (Scotland) Act 1889|in 1889]] and Ireland [[Local Government (Ireland) Act 1898|in 1898]], meaning there is no consistent system of administrative or geographic demarcation across the UK,<ref>{{Cite web |last=United Nations Economic and Social Council |author-link=United Nations Economic and Social Council |date=August 2007 |title=Ninth UN Conference on the standardization of Geographical Names |url=http://unstats.un.org/unsd/geoinfo/UNGEGN/docs/9th-uncsgn-docs/report%20of%209th%20uncsgn%20n0750902%20en.pdf |url-status=live |archive-url=https://web.archive.org/web/20091211213055/http://unstats.un.org/unsd/geoinfo/9th-UNCSGN-Docs/E-CONF-98-48-Add1.pdf |archive-date=11 December 2009 |access-date=21 October 2008 |publisher=UN Statistics Division}}</ref> and [[English law|England and Wales]], [[Scots law|Scotland]] and [[Law of Northern Ireland|Northern Ireland]] each have their own distinct jurisdictions.<ref>{{Cite book |last1=Dewart |first1=Megan |url=https://books.google.com/books?id=XW_EtwEACAAJ |title=The Scottish Legal System |date=2019 |publisher=[[Bloomsbury Academic]] |isbn=978-1-5265-0633-7 |location=London |page=57 |quote=The laws and legal institutions of Scotland and of England and Wales were not merged by the Union of 1707. Thus, they remain separate 'law areas', with separate court systems (as does Northern Ireland), and it is necessary to distinguish Scots law and English law (and Northern Irish law). |access-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704040048/https://books.google.com/books?id=XW_EtwEACAAJ |archive-date=4 July 2023 |url-status=live}}; {{Cite web |title=The justice system and the constitution |url=https://www.judiciary.uk/about-the-judiciary/our-justice-system/jud-acc-ind/justice-sys-and-constitution/#:~:text=The%20United%20Kingdom%20has%20three,of%20Union%201707%20and%201800. |archive-url=https://web.archive.org/web/20230521180341/https://www.judiciary.uk/about-the-judiciary/our-justice-system/jud-acc-ind/justice-sys-and-constitution/ |archive-date=21 May 2023 |access-date=13 June 2023 |publisher=Courts and Tribunals Judiciary |quote=The United Kingdom has three separate legal systems; one each for England and Wales, Scotland and Northern Ireland. This reflects its historical origins and the fact that both Scotland and Ireland, and later Northern Ireland, retained their own legal systems and traditions under the Acts of Union 1707 and 1800.}}</ref> Until the 19th century there was little change to those arrangements, but there has since been a constant evolution of role and function.<ref>{{Cite book |last=Barlow |first=I.M. |title=Metropolitan Government |publisher=Routledge |year=1991 |isbn=978-0-415-02099-2 |location=London}}</ref>
[[Local government in England]] is complex, with the distribution of functions varying according to local arrangements. The upper-tier [[subdivisions of England]] are the nine [[Regions of England|regions]], used primarily for statistical purposes.<ref>{{Cite web |title=Welcome to the national site of the Government Office Network |url=http://www.gos.gov.uk/national |archive-url=https://web.archive.org/web/20090606073647/http://www.gos.gov.uk/national |archive-date=6 June 2009 |access-date=3 July 2008 |publisher=Government Offices}}</ref> One of the regions, [[Greater London Authority|Greater London]], has had a directly elected assembly and mayor since 2000 following popular support for the proposal in a [[1998 Greater London Authority referendum|1998 referendum]].<ref>{{Cite web |title=A short history of London government |url=http://www.london.gov.uk/london-life/city-government/history.jsp |archive-url=https://web.archive.org/web/20080421023053/http://www.london.gov.uk/london-life/city-government/history.jsp |archive-date=21 April 2008 |access-date=4 October 2008 |publisher=Greater London Authority}}</ref>
[[Local government in Scotland]] is divided into [[subdivisions of Scotland|32 council areas]] with a wide variation in size and population. The cities of [[Glasgow]], Edinburgh, [[Aberdeen]] and [[Dundee]] are separate council areas, as is the [[Politics of the Highland council area|Highland Council]], which includes a third of Scotland's area but only just over 200,000 people. Local councils are made up of elected councillors, of whom there are 1,223.<ref name="political-studies-association">{{Cite web |title=STV in Scotland: Local Government Elections 2007 |url=http://www.psa.ac.uk/2007/pps/Bennie.pdf |archive-url=https://web.archive.org/web/20110222124635/http://www.psa.ac.uk/2007/pps/Bennie.pdf |archive-date=22 February 2011 |access-date=2 August 2008 |publisher=Political Studies Association}}</ref>
[[Local government in Wales]] consists of 22 [[Unitary authority|unitary authorities]], each led by a leader and cabinet elected by the council itself. These include the cities of Cardiff, [[Swansea]] and [[Newport, Wales|Newport]], which are unitary authorities in their own right.<ref name="unitary">{{Cite web |year=2014 |title=Unitary authorities |url=http://gov.wales/topics/localgovernment/local-authorities/?lang=en |archive-url=https://web.archive.org/web/20150310210146/http://gov.wales/topics/localgovernment/local-authorities/?lang=en |archive-date=10 March 2015 |access-date=9 March 2015 |publisher=Welsh Government}}</ref> Elections are held every four years under the first-past-the-post system.<ref name="unitary" />
[[Local government in Northern Ireland]] since 2015 has been organised into 11 district councils, each elected by single transferable vote. Their powers are limited to services such as waste collection, dog control, and maintaining parks and cemeteries.<ref name="Devenport">{{Cite news |last=Devenport |first=Mark |date=18 November 2005 |title=NI local government set for shake-up |work=BBC News |url=http://news.bbc.co.uk/1/hi/northern_ireland/4449092.stm |access-date=15 November 2008 |archive-date=12 December 2008 |archive-url=https://web.archive.org/web/20081212221731/http://news.bbc.co.uk/1/hi/northern_ireland/4449092.stm |url-status=live}}</ref> This system was introduced after a 2008 decision by the executive to replace the previous structure of 26 districts which had been in place since 1973.<ref>{{Cite press release |title=Foster announces the future shape of local government |date=13 March 2008 |publisher=Northern Ireland Executive |url=http://www.northernireland.gov.uk/news/news-doe/news-doe-130308-foster-announces-the.htm |access-date=20 October 2008 |archive-url=https://web.archive.org/web/20080725002254/http://www.northernireland.gov.uk/news/news-doe/news-doe-130308-foster-announces-the.htm |archive-date=25 July 2008}}</ref>
=== Devolution ===
{{Main|Devolution in the United Kingdom}}
{{further|Devolved, reserved and excepted matters}}
[[File:Council of Nations and Regions (54059219744) (cropped).jpg|thumb|right|Prime Minister Keir Starmer meets with the first ministers of Scotland, Northern Ireland and Wales during the [[Council of Nations and Regions]] summit.]]
In the United Kingdom a process of devolution has transferred various powers from the UK Government to three of the four UK countries—Scotland, Northern Ireland and Wales—as well as to the regions of England, which since 1999 have their own governments and parliaments that control various devolved matters.<ref>{{Cite web |title=Devolution of powers to Scotland, Wales and Northern Ireland |url=https://www.gov.uk/devolution-of-powers-to-scotland-wales-and-northern-ireland#devolved-administrations |url-status=live |archive-url=https://web.archive.org/web/20130718065448/https://www.gov.uk/devolution-of-powers-to-scotland-wales-and-northern-ireland#devolved-administrations |archive-date=18 July 2013 |access-date=17 April 2013 |publisher=United Kingdom Government |quote=In a similar way to how the government is formed from members from the two Houses of Parliament, members of the devolved legislatures nominate ministers from amongst themselves to comprise executives, known as the devolved administrations...}}; {{Cite web |title=Country Overviews: United Kingdom |url=http://www.transport-research.info/web/countryprofiles/uk.cfm |archive-url=https://web.archive.org/web/20100404062853/http://www.transport-research.info/web/countryprofiles/uk.cfm |archive-date=4 April 2010 |access-date=28 March 2010 |url-status=usurped |publisher=Transport Research Knowledge Centre}}</ref> These powers vary and have been moved to the [[Scottish Government]], the [[Welsh Government]], the [[Northern Ireland Executive]] and (in England) to [[strategic authorities]]: the [[Greater London Authority]], [[Combined authorities and combined county authorities|combined authorities, and combined county authorities]].<ref>{{cite book |last1=Le Sueur |first1=Andrew |last2=Sunkin |first2=Maurice |last3=Murkens |first3=Jo Eric Khushal |title=Public Law: Text, Cases, and Materials |year=2023 |edition=5th |isbn=978-0-19-287061-2 |publisher=Oxford University Press |page=147 |url=https://books.google.com/books?id=6sLDEAAAQBAJ&dq=Le+sueur+Public+Law%C2%A0fifth+edition&pg=PR3 |access-date=13 April 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002213048/https://books.google.com/books?id=6sLDEAAAQBAJ&dq=Le+sueur+Public+Law%C2%A0fifth+edition&pg=PR3#v=onepage&q=Le%20sueur%20Public%20Law%C2%A0fifth%20edition&f=false |url-status=live}}</ref> Amongst the devolved parliaments across the United Kingdom, the [[Scottish Parliament]] has the most extensive responsibilities for [[Devolved, reserved and excepted matters|devolved powers]], and has been described as "one of the most powerful devolved parliaments in the world".<ref>{{cite web |title=The progress of devolution - Erskine May - UK Parliament |url=https://erskinemay.parliament.uk/section/4537/the-progress-of-devolution |website=erskinemay.parliament.uk |access-date=1 March 2025}}</ref><ref>{{cite web |title=David Mundell speech: 20 years of Scottish devolution |url=https://www.gov.uk/government/news/david-mundell-speech-20-years-of-scottish-devolution |website=GOV.UK |access-date=1 March 2025}}</ref>
The United Kingdom has an [[uncodified constitution]] and constitutional matters are not amongst the powers that have been devolved. Under the doctrine of [[Parliamentary sovereignty in the United Kingdom|parliamentary sovereignty]], the UK Parliament could, in theory, therefore, abolish the Scottish Parliament, Senedd or Northern Ireland Assembly.<ref>{{Cite journal |last=Burrows |first=N. |year=1999 |title=Unfinished Business: The Scotland Act 1998 |journal=The Modern Law Review |volume=62 |issue=2 |pages=241–260 [p. 249] |doi=10.1111/1468-2230.00203 |quote=The UK Parliament is sovereign and the Scottish Parliament is subordinate. The White Paper had indicated that this was to be the approach taken in the legislation. The Scottish Parliament is not to be seen as a reflection of the settled will of the people of Scotland or of popular sovereignty but as a reflection of its subordination to a higher legal authority. Following the logic of this argument, the power of the Scottish Parliament to legislate can be withdrawn or overridden...}}; {{Cite journal |last=Elliot |first=M. |year=2004 |title=United Kingdom: Parliamentary sovereignty under pressure |journal=International Journal of Constitutional Law |volume=2 |issue=3 |pages=545–627, 553–554 |doi=10.1093/icon/2.3.545 |quote=Notwithstanding substantial differences among the schemes, an important common factor is that the UK Parliament has not renounced legislative sovereignty in relation to the three nations concerned. For example, the Scottish Parliament is empowered to enact primary legislation on all matters, save those in relation to which competence is explicitly denied ... but this power to legislate on what may be termed "devolved matters" is concurrent with the Westminster Parliament's general power to legislate for Scotland on any matter at all, including devolved matters ... In theory, therefore, Westminster may legislate on Scottish devolved matters whenever it chooses... |doi-access=free}}</ref> Though in the [[Scotland Act 2016]] and the [[Wales Act 2017]] it states that the Scottish Government and the Welsh Government "are a permanent part of the United Kingdom's constitutional arrangements".<ref>{{cite web |title=Scotland Act 2016 |url=https://www.legislation.gov.uk/ukpga/2016/11/part/1/crossheading/the-scottish-parliament-and-the-scottish-government#:~:text=(1)The%20Scottish%20Parliament%20and,the%20United%20Kingdom's%20constitutional%20arrangements. |website=Gov.uk |access-date=28 June 2024 |archive-date=28 June 2024 |archive-url=https://web.archive.org/web/20240628211304/https://www.legislation.gov.uk/ukpga/2016/11/part/1/crossheading/the-scottish-parliament-and-the-scottish-government#:~:text=(1)The%20Scottish%20Parliament%20and,the%20United%20Kingdom's%20constitutional%20arrangements. |url-status=live}}</ref><ref>{{cite web |title=Wales Act 2017 |url=https://www.legislation.gov.uk/ukpga/2017/4/section/1/enacted |access-date=13 July 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212916/https://www.legislation.gov.uk/ukpga/2017/4/section/1/enacted |url-status=live}}</ref>
In practice it would be politically difficult for the UK Parliament to abolish devolution to the Scottish Parliament and the Senedd because these institutions were created by referendums.<ref>{{Cite journal |last=Gamble |first=A. |year=2006 |title=The Constitutional Revolution in the United Kingdom |journal=Publius |volume=36 |issue=1 |pages=19–35 [p. 29] |doi=10.1093/publius/pjj011 |quote=The British parliament has the power to abolish the Scottish parliament and the Welsh assembly by a simple majority vote in both houses, but since both were sanctioned by referenda, it would be politically difficult to abolish them without the sanction of a further vote by the people. In this way, several of the constitutional measures introduced by the Blair government appear to be entrenched and not subject to a simple exercise of parliamentary sovereignty at Westminster.}}</ref> The political constraints placed upon the UK Parliament's power to interfere with devolution in Northern Ireland are greater still, because devolution in Northern Ireland rests upon an international agreement with the [[Government of Ireland]].<ref>{{Cite journal |last=Meehan |first=E. |year=1999 |title=The Belfast Agreement – Its Distinctiveness and Points of Cross-Fertilization in the UK's Devolution Programme |journal=Parliamentary Affairs |volume=52 |issue=1 |pages=19–31 [p. 23] |doi=10.1093/pa/52.1.19 |quote=[T]he distinctive involvement of two governments in the Northern Irish problem means that Northern Ireland's new arrangements rest upon an intergovernmental agreement. If this can be equated with a treaty, it could be argued that the forthcoming distribution of power between Westminster and Belfast has similarities with divisions specified in the written constitutions of federal states...Although the Agreement makes the general proviso that Westminster's 'powers to make legislation for Northern Ireland' remains 'unaffected', without an explicit categorical reference to reserved matters, it may be more difficult than in Scotland or Wales for devolved powers to be repatriated. The retraction of devolved powers would not merely entail consultation in Northern Ireland backed implicitly by the absolute power of parliamentary sovereignty but also the renegotiation of an intergovernmental agreement. |doi-access=free}}</ref> The UK Parliament restricts the three devolved parliaments' legislative powers in economic policy matters through [[United Kingdom Internal Market Act 2020|an act]] passed in 2020.<ref name="UKIM" />
==== England ====
Unlike Scotland, Northern Ireland and Wales, England does not have a separate devolved government or national parliament,<ref>{{cite web |title=English devolution |url=https://www.instituteforgovernment.org.uk/explainer/english-devolution#:~:text=After%201997%20Labour%20governments%20devolved,assembly%20were%20created%20in%202000. |publisher=Institute for Government |access-date=30 August 2024 |date=21 June 2024 |archive-date=30 August 2024 |archive-url=https://web.archive.org/web/20240830150949/https://www.instituteforgovernment.org.uk/explainer/english-devolution#:~:text=After%201997%20Labour%20governments%20devolved,assembly%20were%20created%20in%202000. |url-status=live}}</ref> rather a process of devolution of powers from the central government to local authorities has taken place, first in 1998.<ref>{{cite web |title=Devolution explained |url=https://www.local.gov.uk/topics/devolution/devolution-hub/devolution-explained |publisher=Local Government Association |access-date=30 August 2024 |archive-date=30 August 2024 |archive-url=https://web.archive.org/web/20240830152450/https://www.local.gov.uk/topics/devolution/devolution-hub/devolution-explained |url-status=live}}</ref> The [[Greater London Authority]] was set up following a [[1998 Greater London Authority referendum|referendum in 1998]]. Colloquially known as City Hall, it is the devolved regional government body for Greater London. It consists of two political branches: a directly elected [[Mayor of London]] and the [[London Assembly]], which serves as a check and balance on the Mayor.
A [[Combined authorities and combined county authorities|combined authority]] is a type of local government institution introduced in England outside Greater London by the [[Local Democracy, Economic Development and Construction Act 2009]]. CAs allow a group of local authorities to pool appropriate responsibility and receive certain devolved functions from central government in order to deliver transport and economic policy more effectively over a wider area.<ref>{{Cite web |date=6 March 2023 |title=English devolution |url=https://www.instituteforgovernment.org.uk/explainer/english-devolution |access-date=4 February 2024 |publisher=Institute for Government |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212917/https://www.instituteforgovernment.org.uk/explainer/english-devolution |url-status=live}}</ref> A combined county authority is a similar type of local-government institution introduced in England outside Greater London by the [[Levelling-up and Regeneration Act 2023]], but may only be formed by upper-tier authorities: [[county council]]s and [[Unitary authority|unitary authorities]].<ref>{{Cite web |date=6 April 2023 |title=Combined County Authorities – key differences to Combined Authorities |url=https://www.localgovernmentlawyer.co.uk/governance/314-governance-a-risk-articles/53464-combined-county-authorities-key-differences-to-combined-authorities |access-date=4 February 2024 |website=Local Government Lawyer |archive-date=4 February 2024 |archive-url=https://web.archive.org/web/20240204170903/https://www.localgovernmentlawyer.co.uk/governance/314-governance-a-risk-articles/53464-combined-county-authorities-key-differences-to-combined-authorities |url-status=live}}</ref>
==== Scotland ====
{{main|Responsibilities of the Scottish Government}}
[[File:First Minister meets Prime Minister (53840421342).jpg|thumb|Prime Minister Keir Starmer meets with [[First Minister of Scotland]] [[John Swinney]], the head of the [[Scottish Government]], at [[Bute House]], Edinburgh.]]
Since 1999 Scotland has had a devolved national government and parliament with wide-ranging powers over any matter that has not been specifically [[Reserved and excepted matters|reserved]] to the UK Parliament.<ref name="Scottish Parliament">{{cite web |title=Devolved and Reserved Powers |url=https://www.parliament.scot/about/how-parliament-works/devolved-and-reserved-powers |website=parliament.scot |publisher=Scottish Parliament |access-date=28 December 2023 |archive-date=20 September 2023 |archive-url=https://web.archive.org/web/20230920053732/https://www.parliament.scot/about/how-parliament-works/devolved-and-reserved-powers |url-status=live}}</ref><ref>{{Cite news |date=8 April 1999 |title=Scotland's Parliament – powers and structures |work=BBC News |url=http://news.bbc.co.uk/1/hi/events/scotland_99/the_scottish_parliament/310036.stm |access-date=21 October 2008 |archive-date=18 February 2007 |archive-url=https://web.archive.org/web/20070218234816/http://news.bbc.co.uk/1/hi/events/scotland_99/the_scottish_parliament/310036.stm |url-status=live}}</ref> Scotland has the most devolved powers of any of the three devolved parliaments in the United Kingdom, with full legislative control over [[Education in Scotland|education]], [[Scots law|law and order]], [[Economy of Scotland|the economy]], [[Health in Scotland|healthcare]], [[Elections in Scotland|elections]], [[Crown Estate Scotland]], the [[Planning system in Scotland|planning system]] and [[Housing in Scotland|housing]].<ref>{{cite web |title=Devolved and Reserved Matters - Visit & Learn Scottish Parliament |url=http://www.parliament.scot/visitandlearn/Education/18642.aspx |archive-url=https://web.archive.org/web/20170722092046/http://www.parliament.scot/visitandlearn/Education/18642.aspx |url-status=dead |archive-date=22 July 2017 |access-date=1 March 2025 |date=22 July 2017}}</ref>
Additional powers were transferred to the Scottish Parliament via the [[Scotland Act 2012]] and the [[Scotland Act 2016]], such as [[Taxation in Scotland|some taxation powers]], including full control of [[Income tax in Scotland|income tax]] on income earned through employment, [[Land and Buildings Transaction Tax]], [[Scottish Landfill Tax|Landfill Tax]], Aggregates Levy, [[Air Departure Tax]] and [[Revenue Scotland]], as well as aspects of the [[Energy in Scotland|energy network]], including [[Renewable energy in Scotland|renewable energy]], energy efficiency and onshore [[Oil industry in Scotland|oil and gas licensing]].<ref name="Devolved Matters in Scotland">{{cite web |url=https://www.gov.scot/about/what-the-government-does/ |title=What the Scottish Government does |publisher=Scottish Government |access-date=8 August 2019 |archive-date=8 July 2019 |archive-url=https://web.archive.org/web/20190708045359/https://www.gov.scot/about/what-the-government-does/ |url-status=live}}</ref><ref name="Scottish Parliament" /> Their power over economic issues is significantly constrained by an [[United Kingdom Internal Market Act 2020|act of the UK Parliament]] passed in 2020.{{refn|name=UKIM|<ref name="Keating21">{{Cite journal |last=Keating |first=Michael |date=2 February 2021 |title=Taking back control? Brexit and the territorial constitution of the United Kingdom |journal=[[Journal of European Public Policy]] |location=Abingdon |publisher=[[Taylor & Francis]] |volume=28 |issue=4 |pages=6–7 |doi=10.1080/13501763.2021.1876156 |quote=The UK Internal Market Act gives ministers sweeping powers to enforce mutual recognition and non-discrimination across the four jurisdictions. Existing differences and some social and health matters are exempted but these are much less extensive than the exemptions permitted under the EU Internal Market provisions. Only after an amendment in the House of Lords, the Bill was amended to provide a weak and non-binding consent mechanism for amendments (equivalent to the Sewel Convention) to the list of exemptions. The result is that, while the devolved governments retain regulatory competences, these are undermined by the fact that goods and services originating in, or imported into, England can be marketed anywhere. |hdl-access=free |hdl=1814/70296 |s2cid=234066376}}</ref><ref name="KenMcEw21">{{Cite journal |last1=Kenny |first1=Michael |author-link=Michael Kenny (political scientist) |last2=McEwen |first2=Nicola |author-link2=Nicola McEwen |date=1 March 2021 |title=Intergovernmental Relations and the Crisis of the Union |journal=Political Insight |publisher=[[SAGE Publishing]] |volume=12 |issue=1 |pages=12–15 |doi=10.1177/20419058211000996 |quote=That phase of joint working was significantly damaged by the UK Internal Market Act, pushed through by the Johnson government in December 2020...the Act diminishes the authority of the devolved institutions, and was vehemently opposed by them. |doi-access=free |s2cid=232050477}}</ref><ref name="WolffeDevol">{{Cite journal |last=Wolffe |first=W James |author-link=James Wolffe |date=7 April 2021 |title=Devolution and the Statute Book |url=https://academic.oup.com/slr/advance-article/doi/10.1093/slr/hmab003/6213886 |journal=[[Statute Law Review]] |location=Oxford |publisher=[[Oxford University Press]] |doi=10.1093/slr/hmab003 |access-date=18 April 2021 |quote=the Internal Market Bill—a Bill that contains provisions which, if enacted, would significantly constrain, both legally and as a matter of practicality, the exercise by the devolved legislatures of their legislative competence; provisions that would be significantly more restrictive of the powers of the Scottish Parliament than either EU law or Articles 4 and 6 of the Acts of the Union...The UK Parliament passed the European Union (Withdrawal Agreement) Act 2020 and the Internal Market Act 2020 notwithstanding that, in each case, all three of the devolved legislatures had withheld consent. |archive-date=21 April 2021 |archive-url=https://web.archive.org/web/20210421145355/https://academic.oup.com/slr/advance-article/doi/10.1093/slr/hmab003/6213886 |url-status=live |url-access=subscription}}</ref><ref name="Wincott21">{{Cite journal |last1=Wincott |first1=Daniel |author-link=Daniel Wincott |last2=Murray |first2=C. R. G. |last3=Davies |first3=Gregory |date=17 May 2021 |title=The Anglo-British imaginary and the rebuilding of the UK's territorial constitution after Brexit: unitary state or union state? |journal=Territory, Politics, Governance |location=Abingdon/Brighton |publisher=[[Taylor & Francis]]; [[Regional Studies Association]] |volume=10 |issue=5 |pages=696–713 |doi=10.1080/21622671.2021.1921613 |quote=Taken as a whole, the Internal Market Act imposes greater restrictions upon the competences of the devolved institutions than the provisions of the EU Single Market which it replaced, in spite of pledges to use common frameworks to address these issues. [[David Hope, Baron Hope of Craighead|Lord Hope]], responsible for many of the leading judgments relating to the first two decades of devolution, regarded the legislation's terms as deliberately confrontational: 'this Parliament can do what it likes, but a different approach is essential if the union is to hold together'. |doi-access=free}}</ref><ref name="DouganMcEwen20">{{Cite report |url=https://www.centreonconstitutionalchange.ac.uk/publications/uk-and-internal-market-devolution-and-union |title=UK and the Internal Market, Devolution and the Union |last1=Dougan |first1=Michael |last2=Hayward |first2=Katy |date=2020 |publisher=[[University of Edinburgh]]; [[University of Aberdeen]] |pages=2–3 |last3=Hunt |first3=Jo |last4=McEwen |first4=Nicola |last5=McHarg |first5=Aileen |last6=Wincott |first6=Daniel |author-link=Michael Dougan |author-link2=Katy Hayward |access-date=16 October 2020 |author-link4=Nicola McEwen |author-link6=Daniel Wincott |department=Centre on Constitutional Change |archive-date=18 October 2020 |archive-url=https://web.archive.org/web/20201018185830/https://www.centreonconstitutionalchange.ac.uk/publications/uk-and-internal-market-devolution-and-union |url-status=live}}</ref><ref name="Dougan20Brief">{{Cite report |url=https://www.liverpool.ac.uk/media/livacuk/law/2-research/eull/UKIM,Briefing,Paper,-,Prof,Michael,Dougan,15,September,2020.pdf |title=Briefing Paper. United Kingdom Internal Market Bill: Implications for Devolution |last=Dougan |first=Michael |date=2020 |publisher=[[University of Liverpool]] |location=Liverpool |pages=4–5 |author-link=Michael Dougan |access-date=15 October 2020 |archive-date=26 October 2020 |archive-url=https://web.archive.org/web/20201026161836/https://www.liverpool.ac.uk/media/livacuk/law/2-research/eull/UKIM,Briefing,Paper,-,Prof,Michael,Dougan,15,September,2020.pdf |url-status=live}}</ref><ref name="DouHu22">{{cite journal |last1=Dougan |first1=Michael |last2=Hunt |first2=Jo |last3=McEwen |first3=Nicola |last4=McHarg |first4=Aileen |author-link1=Michael Dougan |author-link3=Nicola McEwen |title=Sleeping with an Elephant: Devolution and the United Kingdom Internal Market Act 2020 |journal=[[Law Quarterly Review]] |date=2022 |url=https://dro.dur.ac.uk/35167/ |location=London |publisher=[[Sweet & Maxwell]] |ssrn=4018581 |via=[[Durham University|Durham Research Online]] |access-date=4 March 2022 |quote=The Act has restrictive – and potentially damaging – consequences for the regulatory capacity of the devolved legislatures...This was not the first time since the Brexit referendum that the Convention had been set aside, but it was especially notable given that the primary purpose of the legislation was to constrain the capacity of the devolved institutions to use their regulatory autonomy...in practice, it constrains the ability of the devolved institutions to make effective regulatory choices for their territories in ways that do not apply to the choices made by the UK government and parliament for the English market. |issn=0023-933X |archive-date=2 August 2022 |archive-url=https://web.archive.org/web/20220802185022/https://dro.dur.ac.uk/35167/ |url-status=live}}</ref>}}
The [[Scottish Government]] is a [[Scottish National Party]] (SNP) [[minority government]],<ref>{{cite web |title=Humza Yousaf's precarious position puts the SNP – and Scotland – at a crossroads |url=https://www.instituteforgovernment.org.uk/comment/humza-yousaf-snp-scotland-crossroads |website=Institute for Government |access-date=26 April 2024 |date=26 April 2024 |archive-date=26 April 2024 |archive-url=https://web.archive.org/web/20240426221203/https://www.instituteforgovernment.org.uk/comment/humza-yousaf-snp-scotland-crossroads |url-status=live}}</ref> led by the [[First Minister of Scotland|first minister]], currently [[John Swinney]], the [[leader of the SNP]]. In 2014 the [[2014 Scottish independence referendum|Scottish independence referendum]] was held, with 55.3 per cent voting against independence from the United Kingdom and 44.7 per cent voting in favour, resulting in Scotland staying within the United Kingdom. [[Local government in Scotland]] is divided into [[subdivisions of Scotland|32 council areas]] with a wide variation in size and population. Local councils are made up of elected councillors, of whom there are 1,223.<ref name="political-studies-association" />
The Scottish Parliament is separate from the Scottish Government. It is made up of 129 elected [[members of the Scottish Parliament]] (MSPs). It is the law-making body of Scotland, and thus it scrutinises the work of the incumbent Scottish Government and considers any piece of proposed legislation through parliamentary debates, committees and parliamentary questions.<ref name="Devolved Matters in Scotland"/>
==== Wales ====
Since 1999 Wales has had a devolved national government and legislature, known as the [[Senedd]]. Elections to the Senedd used the [[additional member system]] until 2026 when the voting system was changed to [[closed list]] proportional representation. The number of elected members also increased from 60 to 96, representing 16 [[Senedd constituencies|six-member constituencies]]. The Senedd has more limited powers than those devolved to Scotland.<ref>{{Cite news |date=9 April 1999 |title=Structure and powers of the Assembly |work=BBC News |url=http://news.bbc.co.uk/1/hi/events/wales_99/the_welsh_assembly/309033.stm |access-date=21 October 2008 |archive-date=7 February 2004 |archive-url=https://web.archive.org/web/20040207162926/http://news.bbc.co.uk/1/hi/events/wales_99/the_welsh_assembly/309033.stm |url-status=live}}</ref> It can legislate on any matter not specifically reserved to the UK Parliament by [[Acts of Senedd Cymru]]. The [[Welsh Government]] is currently a [[Plaid Cymru]] minority government led by the [[First Minister of Wales|first minister]], [[Rhun ap Iorwerth]]. [[Local government in Wales]] consists of 22 unitary authorities, each led by a leader and cabinet elected by the council itself.
==== Northern Ireland ====
The devolved form of government in Northern Ireland is based on the 1998 [[Good Friday Agreement]], which brought to an end a 30-year period of [[Unionism in Ireland|unionist]]-[[Irish nationalism|nationalist]] communal conflict known as [[the Troubles]]. The Agreement was [[1998 Northern Ireland Good Friday Agreement referendum|confirmed by referendum]] and implemented later that year. It established [[power sharing]] arrangements for a devolved government and legislature, referred to as the [[Northern Ireland Executive]] and the [[Northern Ireland Assembly]] respectively.<ref>{{cite web |title=Good Friday Agreement: What is it? |url=https://www.bbc.co.uk/news/uk-northern-ireland-61968177 |website=BBC News |date=3 April 2023 |access-date=11 April 2024 |archive-date=15 May 2024 |archive-url=https://web.archive.org/web/20240515131233/https://www.bbc.co.uk/news/uk-northern-ireland-61968177 |url-status=live}}</ref> Elections to the Assembly use the [[single transferable vote]] system. The Executive and Assembly have powers similar to those devolved to Scotland.<ref>{{Cite web |date=8 May 2019 |title=Devolution of powers to Scotland, Wales and Northern Ireland |url=https://www.gov.uk/guidance/devolution-of-powers-to-scotland-wales-and-northern-ireland |access-date=11 June 2024 |website=GOV.UK |archive-date=7 March 2023 |archive-url=https://web.archive.org/web/20230307093336/https://www.gov.uk/guidance/devolution-of-powers-to-scotland-wales-and-northern-ireland |url-status=live}}</ref> The Executive is led by a [[diarchy]] representing [[Designated Unionist|unionist]] and [[Designated Nationalist|nationalist]] members of the Assembly.<ref name="northernireland1">{{Cite web |date=25 September 2015 |title=Your Executive |url=https://www.northernireland.gov.uk/topics/your-executive |publisher=Northern Ireland Executive |access-date=14 August 2016 |archive-date=21 August 2016 |archive-url=https://web.archive.org/web/20160821135048/https://www.northernireland.gov.uk/topics/your-executive |url-status=live}}</ref> The [[First Minister and Deputy First Minister of Northern Ireland|first minister and deputy first minister of Northern Ireland]] are the joint heads of government of Northern Ireland.<ref>{{Cite news |title=Stormont: Why were NI leaders given unequal job titles? |work=BBC News |date=15 May 2022 |url=https://www.bbc.co.uk/news/uk-northern-ireland-61393736 |access-date=2 February 2024 |archive-url=https://web.archive.org/web/20240202190001/https://www.bbc.com/news/uk-northern-ireland-61393736 |archive-date=2 February 2024}}</ref><ref>{{Cite web |title=Northern Ireland Executive: Ministerial Code |date=28 September 2015 |url=https://www.northernireland.gov.uk/topics/your-executive/ministerial-code |access-date=2 February 2024 |archive-url=https://web.archive.org/web/20240202191115/https://www.northernireland.gov.uk/topics/your-executive/ministerial-code |archive-date=2 February 2024}}</ref> [[Local government in Northern Ireland]] since 2015 has been divided between 11 councils with limited responsibilities.<ref name="Devenport" />
=== Foreign relations ===
{{Main|Foreign relations of the United Kingdom}}
[[File:Trump-Starmer bilateral 2025-02-27-16-07.jpg|thumb|right|UK prime minister Keir Starmer and US president [[Donald Trump]] shaking hands in a joint press conference in 2025. The UK and the US share a "[[Special Relationship]]".]]
The United Kingdom is [[Big Five (United Nations)|a permanent member]] of the [[United Nations Security Council]] and a member of [[NATO]], [[AUKUS]], the Commonwealth of Nations, the [[G7]], the [[G-20 major economies|G20]], the [[Organisation for Economic Co-operation and Development|OECD]], the [[World Trade Organization|WTO]], the [[Council of Europe]] and the [[Organization for Security and Co-operation in Europe|OSCE]].<ref>{{Cite web |last=May |first=Theresa |author-link=Theresa May |date=29 March 2017 |title=Prime Minister's letter to Donald Tusk triggering Article 50 |url=https://www.gov.uk/government/publications/prime-ministers-letter-to-donald-tusk-triggering-article-50/prime-ministers-letter-to-donald-tusk-triggering-article-50 |via=Gov.uk |access-date=19 June 2017 |archive-date=5 June 2017 |archive-url=https://web.archive.org/web/20170605184239/https://www.gov.uk/government/publications/prime-ministers-letter-to-donald-tusk-triggering-article-50/prime-ministers-letter-to-donald-tusk-triggering-article-50 |url-status=live}}</ref> It maintains the [[British Council]], an organisation specialising in international cultural and educational opportunities in over 100 countries. The UK remains a [[great power]] with considerable political, cultural, economic and military influence.<ref name="PaulWirtz2004">{{cite book |last1=Paul |first1=T.V. |url=https://books.google.com/books?id=9jy28vBqscQC&pg=PA59 |title=Balance of Power: Theory and Practice in the 21st century |last2=Wirtz |first2=James |last3=Fortmann |first3=Michel |date=2004 |publisher=Stanford University Press |isbn=978-0-8047-5017-2 |page=59}}</ref><ref>{{Cite news |date=10 May 2012 |title=United Kingdom country profile |url=https://www.bbc.com/news/world-europe-18023389 |access-date=6 July 2025 |work=BBC News |language=en-GB |archive-date=3 January 2023 |archive-url=https://web.archive.org/web/20230103160059/https://www.bbc.com/news/world-europe-18023389 |url-status=live }}</ref>
The United Kingdom is said to have a "[[Special Relationship]]" with the United States and a close partnership with France – the "[[Entente cordiale]]" – and shares nuclear weapons technology with both countries;<ref>{{Cite web |last=Swaine |first=Jon |date=13 January 2009 |title=Barack Obama presidency will strengthen special relationship, says Gordon Brown |url=https://www.telegraph.co.uk/news/worldnews/barackobama/4226246/Barack-Obama-presidency-will-strengthen-special-relationship-says-Gordon-Brown.html |url-access=subscription |access-date=30 May 2011 |website=[[The Daily Telegraph|The Telegraph]] |publication-place=[[London]] |archive-date=4 July 2020 |archive-url=https://web.archive.org/web/20200704192159/https://www.telegraph.co.uk/news/worldnews/barackobama/4226246/Barack-Obama-presidency-will-strengthen-special-relationship-says-Gordon-Brown.html |url-status=live}}</ref><ref>{{Cite book |last1=Kirchner |first1=Emil Joseph |title=Global Security Governance: Competing Perceptions of Security in the 21st century |last2=Sperling |first2=James |publisher=[[Routledge]] |year=2007 |isbn=978-0-415-39162-7 |edition=illustrated |location=London |page=100}}</ref> the [[Anglo-Portuguese Alliance]] is considered to be the oldest binding military alliance in the world. The UK is also closely linked with the Republic of Ireland; the two countries share a [[Common Travel Area]] and co-operate through the [[British-Irish Intergovernmental Conference]] and the [[British-Irish Council]]. Britain's global presence and influence is further amplified through its trading relations, foreign investments, [[official development assistance]] and military engagements.<ref>{{Cite web |last=The Committee Office, House of Commons |date=19 February 2009 |title=DFID's expenditure on development assistance |url=http://www.parliament.the-stationery-office.co.uk/pa/cm200809/cmselect/cmintdev/220/22007.htm |archive-url=https://web.archive.org/web/20130112222226/http://www.parliament.the-stationery-office.co.uk/pa/cm200809/cmselect/cmintdev/220/22007.htm |archive-date=12 January 2013 |access-date=28 April 2013 |publisher=UK Parliament}}</ref>
=== Military ===
{{Main|British Armed Forces|Military history of the United Kingdom}}
[[File:United Kingdom overseas military installations and operations.png|thumb|upright=1.4|
{{Legend|#0000FF|Overseas military installations of the United Kingdom, and locally raised units of the [[British Overseas Territories]]}}
{{Legend|#F0002B|Military interventions since 2000: [[British military intervention in the Sierra Leone Civil War|Palliser]] (Sierra Leone); [[Operation Herrick|Herrick]] (Afghanistan); [[Operation Enduring Freedom – Horn of Africa|Enduring Freedom]] (Horn of Africa); [[Operation Telic|Telic]] (Iraq); [[Operation Ellamy|Ellamy]] (Libya); and [[Operation Shader|Shader]] (Islamic State of Iraq and the Levant).}}]]
The British Armed Forces consist of three professional service branches: the [[Royal Navy]] and [[Royal Marines]] (forming the [[Naval Service (United Kingdom)|Naval Service]]), the [[British Army]] and the [[Royal Air Force]].<ref>{{Cite web |title=Ministry of Defence |url=http://www.mod.uk/DefenceInternet/Home |access-date=21 February 2012 |publisher=Ministry of Defence |archive-date=19 February 2012 |archive-url=https://web.archive.org/web/20120219194140/http://mod.uk/DefenceInternet/Home/ |url-status=live}}</ref> The armed forces of the United Kingdom are managed by the [[Ministry of Defence (United Kingdom)|Ministry of Defence]] and controlled by the [[Defence Council of the United Kingdom|Defence Council]], chaired by the [[Secretary of State for Defence]]. The [[Commander-in-Chief]] is the [[Monarchy of the United Kingdom|British monarch]], to whom members of the forces swear an oath of allegiance.<ref>{{Cite web |date=30 March 2012 |title=Speaker addresses Her Majesty Queen Elizabeth II |url=http://www.parliament.uk/business/news/2012/march/speaker-addresses-hm-the-queen |access-date=28 April 2013 |publisher=UK Parliament |archive-date=1 May 2013 |archive-url=https://web.archive.org/web/20130501221305/http://www.parliament.uk/business/news/2012/march/speaker-addresses-hm-the-queen/ |url-status=live}}</ref>
The armed forces are charged with protecting the United Kingdom and its overseas territories, promoting the UK's global security interests and supporting international peacekeeping efforts. They are active and regular participants in [[NATO]] (including the [[Allied Rapid Reaction Corps]]), the [[Five Power Defence Arrangements]], [[RIMPAC]] and other worldwide coalition operations. [[Overseas military bases of the United Kingdom|Overseas garrisons]] and facilities are maintained in [[RAF Ascension Island|Ascension Island]], [[Mina Salman|Bahrain]], [[Military of Belize|Belize]], [[Military Forces based in Brunei|Brunei]], [[British Army Training Unit Suffield|Canada]], [[British Forces Cyprus|Cyprus]], [[Diego Garcia]], the [[Military of the Falkland Islands|Falkland Islands]], [[British Forces Germany|Germany]], [[British Forces Gibraltar|Gibraltar]], [[British Army Training Unit Kenya|Kenya]], [[Oman]], [[Al Udeid Air Base|Qatar]] and [[Singapore]].<ref>{{Cite web |title=House of Commons Hansard |url=https://publications.parliament.uk/cgi-bin/newhtml_hl?DB=semukparl&STEMMER=en&WORDS=raf%20diego%20garcia&ALL=RAF&ANY=&PHRASE=%22Diego%20Garcia%20%22&CATEGORIES=&SIMPLE=&SPEAKER=&COLOUR=red&STYLE=s&ANCHOR=50221w33.html_spnew0&URL=/pa/cm200405/cmhansrd/vo050221/text/50221w33.htm#50221w33.html_spnew0 |archive-url=https://web.archive.org/web/20090309114107/http://www.publications.parliament.uk/cgi-bin/newhtml_hl?DB=semukparl&STEMMER=en&WORDS=raf%20diego%20garcia&ALL=RAF&ANY=&PHRASE=%22Diego%20Garcia%20%22&CATEGORIES=&SIMPLE=&SPEAKER=&COLOUR=red&STYLE=s&ANCHOR=50221w33.html_spnew0&URL=%2Fpa%2Fcm200405%2Fcmhansrd%2Fvo050221%2Ftext%2F50221w33.htm#50221w33.html_spnew0 |archive-date=9 March 2009 |access-date=23 October 2008 |publisher=UK Parliament}}; {{Cite web |title=House of Commons Hansard Written Answers for 17 Jun 2013 (pt 0002) |url=https://publications.parliament.uk/pa/cm201314/cmhansrd/cm130617/text/130617w0002.htm#13061746000236 |archive-url=https://web.archive.org/web/20150214025754/http://www.publications.parliament.uk/pa/cm201314/cmhansrd/cm130617/text/130617w0002.htm#13061746000236 |archive-date=14 February 2015 |access-date=4 March 2015 |publisher=Publications.parliament.uk}}</ref>
According to the [[Stockholm International Peace Research Institute]]<ref>{{Cite web |date=April 2026|title=Trends in Military Expenditure 2025|url=https://www.sipri.org/sites/default/files/2026-04/2604_milex_2025.pdf#page=2|access-date=31 May 2026|publisher=[[Stockholm International Peace Research Institute]]}}</ref> and the [[International Institute for Strategic Studies]],<ref>{{Cite web |title=The Military Balance 2026: Global defence spending|url=https://www.iiss.org/publications/the-military-balance/2026/the-military-balance-2026/global-defence-spending/|access-date=2026-05-31|website=IISS|language=en}}</ref> the UK had the world's [[List of countries by military expenditures|sixth- or fifth-highest military expenditures]] in 2025. Total defence spending in 2024 was estimated at 2.3 per cent of [[gross domestic product]].<ref>{{Cite web |title=Rishi Sunak vows to boost UK defence spending to 2.5% of GDP by 2030 |url=https://www.bbc.co.uk/news/uk-politics-68880171 |access-date=24 April 2024 |publisher=BBC News |date=24 April 2024 |archive-date=23 April 2024 |archive-url=https://web.archive.org/web/20240423233438/https://www.bbc.co.uk/news/uk-politics-68880171 |url-status=live}}</ref> Following the end of the [[Cold War]], defence policy has a stated assumption that "the most demanding operations" will be undertaken as part of a coalition.<ref>''UK 2005: The Official Yearbook of the United Kingdom of Great Britain and Northern Ireland''. Office for National Statistics. p. 89.</ref>
=== Law and criminal justice ===
<!-- Copyedit done to here -->
{{Main|Law of the United Kingdom|Crime in the United Kingdom}}
{{Further|English law|Northern Ireland law|Scots law}}
[[File:Middlesex Guildhall (cropped).jpg|thumb|The [[Supreme Court of the United Kingdom|Supreme Court]] is the final court of appeal for England, Wales and Northern Ireland, and for Scottish civil cases.]]
The United Kingdom does not have a single legal system as the [[Treaty of Union|1706 Treaty of Union]] provided for the continuation of Scotland's separate legal system.<ref name="Acts of Union 1707" /> The UK has three distinct [[Legal systems of the world|systems of law]]: English law, Northern Ireland law and Scots law. A new [[Supreme Court of the United Kingdom]] came into being in October 2009 to replace the [[judicial functions of the House of Lords|Appellate Committee of the House of Lords]].<ref>{{Cite news |date=1 October 2009 |title=UK Supreme Court judges sworn in |work=BBC News |url=http://news.bbc.co.uk/1/hi/uk/8283939.stm |access-date=6 October 2009 |archive-date=7 February 2020 |archive-url=https://web.archive.org/web/20200207160453/http://news.bbc.co.uk/1/hi/uk/8283939.stm |url-status=live}}; {{Cite web |date=July 2003 |title=Constitutional reform: A Supreme Court for the United Kingdom |url=http://www.dca.gov.uk/consult/supremecourt/supreme.pdf |archive-url=http://webarchive.nationalarchives.gov.uk/20090117132005/http://www.dca.gov.uk/consult/supremecourt/supreme.pdf |archive-date=17 January 2009 |access-date=13 May 2013 |publisher=Department for Constitutional Affairs}}</ref> The [[Judicial Committee of the Privy Council]], including the same members as the Supreme Court, is the highest court of appeal for several independent Commonwealth countries, the [[British Overseas Territories]] and the [[Crown Dependencies]].<ref>{{Cite web |title=Role of the JCPC |url=http://www.jcpc.uk/about/role-of-the-jcpc.html |access-date=28 April 2013 |publisher=Judicial Committee of the Privy Council |archive-date=14 January 2014 |archive-url=https://web.archive.org/web/20140114165910/http://www.jcpc.uk/about/role-of-the-jcpc.html |url-status=live}}</ref>
Both English law, which applies in England and Wales, and Northern Ireland law are based on [[common law]] (or [[case law]]) principles.<ref>{{Cite book |last=Bainham |first=Andrew |url=https://books.google.com/books?id=AF303DEl0MkC&pg=PA298 |title=The international survey of family law: 1996 |publisher=Martinus Nijhoff |year=1998 |isbn=978-90-411-0573-8 |location=The Hague |page=298 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141743/https://books.google.com/books?id=AF303DEl0MkC&pg=PA298#v=onepage&q&f=false |url-status=live}}</ref> It originated in England in the [[Middle Ages]] and is the basis for many legal systems around the world.<ref>{{Cite web |title=Common Law |url=https://www.britannica.com/topic/common-law |access-date=27 May 2024 |publisher=Britannica |date=19 May 2024 |archive-date=6 May 2021 |archive-url=https://web.archive.org/web/20210506134920/https://www.britannica.com/topic/common-law |url-status=live}}</ref> The [[courts of England and Wales]] are headed by the [[Senior Courts of England and Wales]], consisting of the [[Court of Appeal of England and Wales|Court of Appeal]], the [[High Court of Justice]] for civil cases and the [[Crown Court]] for criminal cases.<ref>{{Cite web |title=The Australian courts and comparative law |url=http://www.alpn.edu.au/node/66 |archive-url=https://web.archive.org/web/20130414202207/http://alpn.edu.au/node/66 |archive-date=14 April 2013 |access-date=9 March 2015 |publisher=Australian Law Postgraduate Network}}</ref> Scots law is a hybrid system based on common-law and [[Civil law (legal system)|civil-law]] principles. The chief courts are the [[Court of Session]], for civil cases,<ref>{{Cite web |title=Court of Session – Introduction |url=http://www.scotcourts.gov.uk/session/index.asp |archive-url=https://web.archive.org/web/20080731094308/http://www.scotcourts.gov.uk/session/index.asp |archive-date=31 July 2008 |access-date=8 March 2015 |publisher=Scottish Courts}}</ref> and the [[High Court of Justiciary]], for criminal cases.<ref>{{Cite web |title=High Court of Justiciary – Introduction |url=http://www.scotcourts.gov.uk/justiciary/index.asp |archive-url=https://web.archive.org/web/20080912204821/http://www.scotcourts.gov.uk/justiciary/index.asp |archive-date=12 September 2008 |access-date=9 March 2015 |publisher=Scottish Courts}}</ref> The Supreme Court of the United Kingdom serves as the highest court of appeal for civil cases under Scots law.<ref>{{Cite web |title=House of Lords – Practice Directions and Standing Orders Applicable to Civil Appeals |url=https://publications.parliament.uk/pa/ld199697/ldinfo/ld08judg/bluebook/bluebk03.htm |archive-url=https://web.archive.org/web/20131206120915/http://www.publications.parliament.uk/pa/ld199697/ldinfo/ld08judg/bluebook/bluebk03.htm |archive-date=6 December 2013 |access-date=8 March 2015 |publisher=UK Parliament}}</ref> The criminal justice system has been characterised by low [[conviction rate]]s and [[Justice delayed is justice denied|court delays]] for some crime types.<ref name="s576">{{cite journal | last1=Lovett | first1=Jo | last2=Hales | first2=Gavin | last3=Kelly | first3=Liz | last4=Khan | first4=Aneela | last5=Hardiman | first5=Margaret | last6=Trott | first6=Louise | title=What can We Learn from Police Data About Timeliness in Rape and Serious Sexual Offence Investigations in England and Wales? | journal=International Criminology | volume=2 | issue=3 | date=2022 | issn=2662-9976 | doi=10.1007/s43576-022-00069-8 | pages=286–298| pmc=9527390 }}</ref>
Crime in England and Wales increased between 1981 and 1995. Since that peak there has been an overall fall of 66% in recorded crime from 1995 to 2015,<ref>{{Cite web |url=http://www.ons.gov.uk/ons/dcp171778_419450.pdf |title=Crime in England and Wales, Year Ending June 2015 |publisher=Office for National Statistics |website=UK Government Web Archive |access-date=16 March 2023 |archive-date=16 March 2023 |archive-url=https://web.archive.org/web/20230316221317/https://webarchive.nationalarchives.gov.uk/ukgwa/20160105160709/http://www.ons.gov.uk/ons/dcp171778_419450.pdf |url-status=bot: unknown}}</ref> according to [[Crime statistics in the United Kingdom|UK crime statistics]].
[[United Kingdom labour law|UK labour laws]] establish employment rights including [[National Minimum Wage Act 1998|a minimum wage]], a minimum of 28 days annual holiday, parental leave, statutory sick pay and [[Pensions Act 2008|a pension]]. [[Same-sex marriage]] has been legal in England, Scotland, and Wales since 2014, and in [[Northern Ireland]] since 2020.<ref>{{cite web |last1=Wratten |first1=Marcus |title=Tom Allen to host vital new BBC show marking 10th anniversary of same-sex marriage |url=https://www.thepinknews.com/2023/07/03/tom-allen-bbc-my-big-gay-wedding-same-sex-marriage/ |website=PinkNews |date=3 July 2023 |access-date=2 September 2023 |archive-date=2 September 2023 |archive-url=https://web.archive.org/web/20230902195143/https://www.thepinknews.com/2023/07/03/tom-allen-bbc-my-big-gay-wedding-same-sex-marriage/ |url-status=live}}</ref> [[LGBT rights in the United Kingdom|LGBT equality]] in the United Kingdom is considered advanced by modern standards.<ref>{{Cite web |date=5 June 2023 |title=The 203 Worst (& Safest) Countries for LGBTQ+ Travel in 2023 |url=https://www.asherfergusson.com/lgbtq-travel-safety/ |access-date=20 August 2023 |website=Asher & Lyric |archive-date=10 September 2021 |archive-url=https://web.archive.org/web/20210910063408/https://www.asherfergusson.com/lgbtq-travel-safety/ |url-status=live}}</ref><ref>{{cite web |last1=R. Flores |first1=Andrew |title=Social Acceptance of LGBTI People in 175 Countries and Locations |url=https://williamsinstitute.law.ucla.edu/publications/global-acceptance-index-lgbt/ |website=Williams Institute |access-date=11 September 2023 |archive-date=13 September 2023 |archive-url=https://web.archive.org/web/20230913091254/https://williamsinstitute.law.ucla.edu/publications/global-acceptance-index-lgbt/ |url-status=live}}</ref>
Since leaving the [[European Union|EU]] most disputes under UK-EU agreements are addressed through consultation between the parties. If consultation fails to resolve the issue, either party can request [[arbitration]], typically at the [[Permanent Court of Arbitration|PCA]] in [[Peace Palace|The Hague]].<ref name="commission.europa.eu" /><ref>{{Cite web |title=Disputes under the Trade and Cooperation Agreement |date=November 2021 |url=https://www.instituteforgovernment.org.uk/explainer/disputes-trade-and-cooperation-agreement |access-date=26 January 2025 |publisher=Institute for Government}}</ref><ref>{{Cite web |title=Sandeel fishing ban to remain in place |date=2 May 2025 |url=https://www.bbc.co.uk/news/articles/ckgrwxxzxkjo |website=BBC |access-date=4 May 2025 |archive-url=https://web.archive.org/web/20250504203005/https://www.bbc.com/news/articles/ckgrwxxzxkjo |archive-date=4 May 2025}}</ref> The [[EU–UK Trade and Cooperation Agreement]] states that the UK and EU have to cooperate and negotiate with each other with 'full mutual respect and good faith', as defined by international law.<ref>{{Cite web |title=Good Faith in Public Law |date=20 January 2022 |url=https://www.law.ox.ac.uk/news/2022-01-20-good-faith-public-law |website=ox.ac.uk |access-date=13 May 2025 |archive-url=https://web.archive.org/web/20250513165454/https://www.law.ox.ac.uk/news/2022-01-20-good-faith-public-law |archive-date=13 May 2025}}</ref> Under the [[Windsor Framework]], [[Northern Ireland]] matters requiring interpretation of EU law go to the [[European Court of Justice|ECJ]], though the [[Stormont Brake]] can prevent new EU rules from taking effect.
== Economy ==
{{Main|Economy of the United Kingdom}}
{{Further|Economy of England|Economy of Scotland|Economy of Northern Ireland|Economy of Wales}}
[[File:Bank junction - 2020-09-20 (2).jpg|thumb|[[City of London]] skyline from at [[Bank Junction]]. [[London]] is Europe's largest financial centre.<ref>{{Cite web |last=Yanatma |first=Servet |date=16 March 2024 |title=Europe's top financial centres: Where's best to do business? |url=https://www.euronews.com/business/2024/03/16/europes-top-financial-centres-wheres-best-to-do-business |access-date=16 August 2025 |publisher=[[Euronews]] |quote=While the US dominates the upper end of the list, with New York taking the number one spot, London continues to lead in Europe.}}</ref>]]
The United Kingdom has a highly developed [[social market economy]].<ref>{{Cite journal |last1=Thane |first1=Pat |year=2019 |title=The Origins of the British Welfare State |journal=The Journal of Interdisciplinary History |volume=50 |issue=3 |pages=427–433 |doi=10.1162/jinh_a_01448 |s2cid=208223636 |doi-access=free}}</ref><ref name="ftms">{{cite web |last1=Griffiths |first1=Alan |last2=Wall |first2=Stuart |date=16 July 2011 |title=Applied Economics |url=http://www.ftms.edu.my/pdf/Download/UndergraduateStudent/BusinessEconomics/BC215001S%20-%20BE%20Key%20Text%20-%20Applied%20Economics.pdf |url-status=dead |archive-url=https://web.archive.org/web/20130620120524/http://www.ftms.edu.my/pdf/Download/UndergraduateStudent/BusinessEconomics/BC215001S%20-%20BE%20Key%20Text%20-%20Applied%20Economics.pdf |archive-date=20 June 2013 |access-date=25 September 2014}}</ref> With an estimated nominal [[gross domestic product]] (GDP) of £2.819 trillion in 2025,<ref name="IMFWEO.UK" /> it is the [[List of countries by GDP (nominal)|fifth-largest national economy]] in the world and the [[List of sovereign states in Europe by GDP (nominal)|second-largest]] in Europe. Its currency, the [[pound sterling]], is the [[Foreign exchange market#Most traded currencies by value|fourth-most-traded currency]] in the [[foreign exchange market]] and the world's fourth-largest [[reserve currency]], after the [[United States dollar]], the [[euro]] and the [[yen]].<ref>{{Cite web |title=World Currency Composition of Official Foreign Exchange Reserves |url=https://data.imf.org/regular.aspx?key=41175 |access-date=10 October 2021 |website=IMF Data |archive-date=12 May 2016 |archive-url=https://web.archive.org/web/20160512202858/https://data.imf.org/regular.aspx?key=41175 |url-status=live}}</ref> The pound sterling maintains its high nominal value through both its long history of stability and by never undergoing formal [[redenomination]]. Since 2022 the UK has been both the world's [[List of countries by exports|fourth-largest exporter]]<ref>{{Cite web |title=Exports of goods and services (BoP, current US$) |url=https://data.worldbank.org/indicator/BX.GSR.GNFS.CD?end=2024&most_recent_value_desc=true |access-date=22 September 2025 |website=[[World Bank]]}}</ref> and [[List of countries by imports|fourth-largest importer]]<ref>{{Cite web |title=Imports of goods and services (current US$) |url=https://data.worldbank.org/indicator/NE.IMP.GNFS.CD?most_recent_value_desc=true |access-date=22 September 2025 |website=[[World Bank]] |archive-date=13 September 2025 |archive-url=https://web.archive.org/web/20250913065521/https://data.worldbank.org/indicator/NE.IMP.GNFS.CD?most_recent_value_desc=true |url-status=live }}</ref> of goods and services. Despite having one of the highest levels of [[Income inequality in the United Kingdom|income inequality]] in the [[OECD]],<ref>{{Cite web |last1=Francis-Devine |first1=Brigid |title=House of Commons Research Briefing on Income inequality in the UK. |url=https://commonslibrary.parliament.uk/research-briefings/cbp-7484/ |url-status=live |archive-url=https://web.archive.org/web/20220210104536/https://commonslibrary.parliament.uk/research-briefings/cbp-7484/ |archive-date=10 February 2022 |access-date=1 July 2023 |website=UK Parliament}}</ref><ref>{{Cite web |title=Inequality – Income inequality – OECD Data |url=http://data.oecd.org/inequality/income-inequality.htm |archive-url=https://web.archive.org/web/20230629183322/https://data.oecd.org/inequality/income-inequality.htm |archive-date=29 June 2023 |access-date=3 July 2023 |website=theOECD}}</ref> the UK has a very high [[Human Development Index|HDI]] ranking, including when [[List of countries by inequality-adjusted Human Development Index|adjusted for inequality]]. As of 2025 the [[Unemployment in the United Kingdom|UK unemployment rate]] is 4.7%<ref>{{Cite web |last1=Labiak |first1=Mitchell |last2=Smith |first2=Oliver |date=17 July 2025 |title=UK jobs market weakens as unemployment rate rises |url=https://www.bbc.com/news/articles/cg754negn75o |access-date=25 September 2025 |website=www.bbc.com |language=en-GB |archive-date=15 September 2025 |archive-url=https://web.archive.org/web/20250915184829/https://www.bbc.com/news/articles/cg754negn75o |url-status=live }}</ref> and the annual [[List of countries by real GDP per capita growth|real GDP per head growth]] was 1.1%.<ref name="f919">{{cite web | title=GDP quarterly national accounts, UK | website=Office for National Statistics | date=2026 | url=https://www.ons.gov.uk/economy/grossdomesticproductgdp/bulletins/quarterlynationalaccounts/octobertodecember2025 | access-date=2026-04-24}}</ref>
[[HM Treasury]], led by the [[Chancellor of the Exchequer]], is responsible for developing and executing the government's [[public finance]] and [[economic policy]]. The [[Department for Business and Trade]] is responsible for business, international trade, and enterprise. The [[Bank of England]] is the UK's [[central bank]] and responsible for issuing notes and coins in the pound sterling. Banks in Scotland and Northern Ireland retain the right to issue their own notes, subject to retaining enough Bank of England notes in reserve to cover their issue.
=== Industries and services ===
[[File:Bank-of-England.jpg|thumb|The [[Bank of England]] is the [[central bank]] of the United Kingdom and the model on which most modern central banks have been based.]]
[[File:British Airways Concorde G-BOAC 03.jpg|thumb|[[Concorde]] was a [[Supersonic speed|supersonic]] airliner that reduced transatlantic flight time from 8 hours to 3.5 hours.<ref>{{Cite web |title=Celebrating Concorde |url=https://www.britishairways.com/en-gb/information/about-ba/history-and-heritage/celebrating-concorde |archive-url=https://web.archive.org/web/20230317103939/https://www.britishairways.com/en-gb/information/about-ba/history-and-heritage/celebrating-concorde |archive-date=17 March 2023 |access-date=30 March 2023}}</ref>]]
The [[Tertiary sector of the economy|service sector]] made up around 80 per cent of the UK's [[Gross value added|GVA]] in 2023.<ref>{{Cite web |last=Hutton |first=Georgina |date=3 October 2024 |title=Industries in the UK |url=https://commonslibrary.parliament.uk/research-briefings/cbp-8353/ |access-date=19 May 2025 |website=UK Parliament: House of Commons Library |archive-date=7 October 2021 |archive-url=https://web.archive.org/web/20211007134640/https://commonslibrary.parliament.uk/research-briefings/cbp-8353/ |url-status=live }}</ref> As of 2023 it is the world's [[List of countries by service exports|second-largest exporter of services]]<ref>{{Cite web |title=Service exports (BoP, current US$) |url=https://data.worldbank.org/indicator/BX.GSR.NFSV.CD?most_recent_value_desc=true&year_high_desc=false |access-date=19 May 2025 |website=World Bank Open Data |archive-date=17 March 2023 |archive-url=https://web.archive.org/web/20230317140633/https://data.worldbank.org/indicator/BX.GSR.NFSV.CD?most_recent_value_desc=true&year_high_desc=false |url-status=live }}</ref> and in 2024 was the world's largest net exporter of [[Financial services in the United Kingdom|financial services]].<ref>{{Cite web |date=15 January 2025 |title=UK leads world in financial services trade surplus |url=https://www.thecityuk.com/news/uk-leads-world-in-financial-services-trade-surplus/ |access-date=2 June 2025 |website=TheCityUK |language=en}}</ref> [[London]] is the world capital for foreign exchange trading, with a market share of 37.8 per cent in 2022 of the global turnover.<ref>{{Cite web |date=30 September 2025 |title=BIS Triennial Survey of Foreign Exchange and Over-The-Counter Interest Rate Derivatives Markets in April 2025 – UK Data |url=https://www.bankofengland.co.uk/news/2025/september/bis-triennial-survey-of-foreign-exchange-and-over-the-counter-interest-rate-derivatives-markets |access-date=7 December 2025 |publisher=Bank of England}}</ref> It is the largest urban economy in Europe<ref>{{Cite web |last=Florida |first=Richard |date=16 March 2017 |title=The Economic Power of Cities Compared to Nations |url=https://www.bloomberg.com/news/articles/2017-03-16/top-metros-have-more-economic-power-than-most-nations |url-status=live |archive-url=https://web.archive.org/web/20240308074221/https://www.bloomberg.com/news/articles/2017-03-16/top-metros-have-more-economic-power-than-most-nations |archive-date=8 March 2024 |access-date=22 February 2024 |website=Bloomberg}}</ref> and, alongside [[New York City|New York]], the city in the world most integrated with the [[World economy|global economy]].<ref>{{Cite web |title=World Cities 2024 |url=https://gawc.lboro.ac.uk/gawc-worlds/the-world-according-to-gawc/world-cities-2024/ |access-date=21 September 2025 |website=GaWC |language=en-US |archive-date=3 July 2025 |archive-url=https://web.archive.org/web/20250703071437/https://gawc.lboro.ac.uk/gawc-worlds/the-world-according-to-gawc/world-cities-2024/ |url-status=live }}</ref> London is also one of the world's leading financial centres, ranking second in the 2025 [[Global Financial Centres Index]].<ref name="www.longfinance.net">{{Cite web |title=GFCI 36 Rank - Long Finance |url=https://www.longfinance.net/programmes/financial-centre-futures/global-financial-centres-index/gfci-36-explore-the-data/gfci-36-rank/ |access-date=19 May 2025 |website=www.longfinance.net |archive-date=25 September 2024 |archive-url=https://web.archive.org/web/20240925155927/https://www.longfinance.net/programmes/financial-centre-futures/global-financial-centres-index/gfci-36-explore-the-data/gfci-36-rank/ |url-status=live }}</ref> [[Edinburgh]], the UK's second-largest financial centre, ranks 29th in the world in the same index.<ref name="www.longfinance.net" />
The [[Manufacturing in the United Kingdom|UK's manufacturing sector]] in 2024 was the world's [[List of countries by manufacturing output|10th-largest]] and Europe's fourth-largest by value output.<ref>{{Cite web |title=World Bank Open Data |url=https://data.worldbank.org/indicator/NV.IND.MANF.CD?most_recent_value_desc=true |access-date=5 August 2025 |website=World Bank Open Data |archive-date=7 January 2020 |archive-url=https://web.archive.org/web/20200107135049/https://data.worldbank.org/indicator/NV.IND.MANF.CD?most_recent_value_desc=true |url-status=live }}</ref> At the end of 2024 manufacturing in the United Kingdom accounted for 8 per cent of the workforce and 8.6 per cent of national economic output.<ref>{{Cite web |date=22 May 2025 |title=Manufacturing industries: Economic indicators |url=https://commonslibrary.parliament.uk/research-briefings/sn05206/ |access-date=1 June 2025 |website=House of Commons Library}}</ref> As reported in 2017 the [[East Midlands Manufacturing|East Midlands]] and [[West Midlands Manufacturing|West Midlands]] (at 12.6 and 11.8 per cent respectively) were the regions with the highest proportion of employees in manufacturing. [[London manufacturing|London's manufacturing sector]] had the lowest at 2.8 per cent.<ref>Hennik Research. [http://www.themanufacturer.com/wp-content/uploads/2017/01/Annual-Manufacturing-Report-2017-Final-Version.pdf ''Annual Manufacturing Report: 2017'' (Dec. 2016)] {{Webarchive|url=https://web.archive.org/web/20170131192050/http://www.themanufacturer.com/wp-content/uploads/2017/01/Annual-Manufacturing-Report-2017-Final-Version.pdf|date=31 January 2017}}</ref>
The [[Tourism in the United Kingdom|country's tourism sector]] is important to the British economy;<ref>{{Cite web |last1=Chan |first1=Kelvin |date=25 April 2023 |title=King Charles' coronation is bringing millions of tourists and a cash infusion to London but it probably won't save the British economy |url=https://fortune.com/2023/04/25/king-charles-coronation-tourists-money-london-british-economy/ |archive-url=https://web.archive.org/web/20230502144950/https://fortune.com/2023/04/25/king-charles-coronation-tourists-money-london-british-economy/ |archive-date=2 May 2023 |access-date=9 May 2023 |website=[[fortune.com]] |agency=The Associated Press}}</ref> The [[creative industries]] accounted for 5.9 per cent of the UK's GVA in 2019,<ref>{{Cite web |title=DCMS Economic Estimates 2019 (provisional): Gross Value Added |url=https://www.gov.uk/government/statistics/dcms-economic-estimates-2019-gross-value-added/dcms-economic-estimates-2019-provisional-gross-value-added |access-date=31 January 2023 |website=gov.uk |archive-date=31 January 2023 |archive-url=https://web.archive.org/web/20230131001226/https://www.gov.uk/government/statistics/dcms-economic-estimates-2019-gross-value-added/dcms-economic-estimates-2019-provisional-gross-value-added |url-status=live}}</ref> and contributed £111 billion to the UK economy in 2018.<ref>{{Cite web |year=2020 |title=UK's Creative Industries contributes almost £13 million to the UK economy every hour |url=https://www.gov.uk/government/news/uks-creative-industries-contributes-almost-13-million-to-the-uk-economy-every-hour |access-date=21 February 2023 |publisher=UK Government |archive-date=21 February 2023 |archive-url=https://web.archive.org/web/20230221131518/https://www.gov.uk/government/news/uks-creative-industries-contributes-almost-13-million-to-the-uk-economy-every-hour |url-status=live}}</ref> [[Lloyd's of London]], located in London, is the world's largest [[insurance]] and [[reinsurance]] market.<ref>{{Cite web |title=Lloyd's of London – value proposition |url=https://www.lloyds.com/about-lloyds/value-proposition-coverholder |archive-url=https://web.archive.org/web/20230227100951/https://www.lloyds.com/about-lloyds/value-proposition-coverholder |archive-date=27 February 2023 |website=Lloyd's of London}}</ref> [[WPP plc]] is one of the world's biggest advertising companies and also based in London.<ref>{{Cite web |title=Rankings 2025 - Creative 100 |url=https://www.warc.com/creative/rankings/creative-100 |website=WARC |access-date=12 June 2025 |archive-url=https://web.archive.org/web/20250612162216/https://www.warc.com/creative/rankings/creative-100 |archive-date=12 June 2025}}</ref> The UK is one of Europe's leading retail markets and its largest [[e-commerce]] market.<ref>{{Cite web |url=https://www.great.gov.uk/international/content/investment/sectors/retail/ |access-date=18 January 2024 |title=Retail |publisher=great.gov.uk |archive-date=18 January 2024 |archive-url=https://web.archive.org/web/20240118084416/https://www.great.gov.uk/international/content/investment/sectors/retail/ |url-status=live}}</ref> With [[Consumer spending|consumption expenditures]] of over US$2 trillion in 2023, it has the [[List of largest consumer markets|second-largest consumer market]] in Europe.<ref>{{Cite web |title=Households and NPISHs Final consumption expenditure (current US$) |url=https://data.worldbank.org/indicator/NE.CON.PRVT.CD?year_high_desc=true |access-date=17 August 2024 |website=World Bank Group |archive-date=12 June 2018 |archive-url=https://web.archive.org/web/20180612143614/https://data.worldbank.org/indicator/NE.CON.PRVT.CD?year_high_desc=true |url-status=live}}</ref> [[John Lewis Partnership|John Lewis]] is the UK's largest employee-owned business.<ref>{{Cite web |url=https://employeeownership.co.uk/resources/what-the-evidence-tells-us/ |access-date=18 January 2024 |title=Employee owned businesses - What the evidence tells us |archive-date=2 December 2023 |archive-url=https://web.archive.org/web/20231202155249/https://employeeownership.co.uk/resources/what-the-evidence-tells-us/ |url-status=live}}</ref>
The [[Automotive industry in the United Kingdom|British automotive industry]] generates £47 billion of exports (12 per cent of the UK's total exports of goods).<ref name="Auto Output 2025" /> In 2024 the UK produced 779,584 passenger vehicles and 125,649 commercial vehicles; 8 out of 10 cars produced in the UK are exported overseas.<ref name="Auto Output 2025">{{Cite web |date=15 May 2025 |title=SMMT Motor Industry Facts 2025 |url=https://www.smmt.co.uk/smmt-motor-industry-facts-2025/ |access-date=26 May 2025 |website=SMMT |archive-date=26 May 2025 |archive-url=https://web.archive.org/web/20250526074751/https://www.smmt.co.uk/smmt-motor-industry-facts-2025/ |url-status=live}}</ref> Britain is known for iconic cars like [[Mini Hatch|Mini]] and [[Jaguar Cars|Jaguar]],<ref>{{Cite web |date=19 November 2020 |title=Best British cars: Top 50 all-time greatest British-built cars revealed - page 2 |url=https://www.autoexpress.co.uk/best-cars-vans/351729/best-british-cars-top-50-all-time-greatest-british-built-cars-revealed/page-2 |access-date=9 March 2024 |website=Auto Express |archive-date=16 March 2024 |archive-url=https://web.archive.org/web/20240316184015/https://www.autoexpress.co.uk/best-cars-vans/351729/best-british-cars-top-50-all-time-greatest-british-built-cars-revealed/page-2 |url-status=live}}</ref> as well as luxury cars such as [[Rolls-Royce Motor Cars|Rolls-Royce]], [[Bentley]] and [[Range Rover]]. The UK is a major centre for engine manufacturing: 1.59 million engines were produced in 2024.<ref name="Auto Output 2025" /> It was the world's [[List of countries by engine exports|third-largest exporter of engines]] by value in 2023.<ref>{{Cite web |title=Combustion Engines |url=https://oec.world/en/profile/hs/combustion-engines |access-date=26 May 2025 |website=OEC - The Observatory of Economic Complexity |archive-date=26 May 2025 |archive-url=https://web.archive.org/web/20250526073421/https://oec.world/en/profile/hs/combustion-engines |url-status=live}}</ref> The [[Motorsport in the United Kingdom|UK motorsport]] industry has an annual turnover of around £10 billion.<ref>{{Cite web |year=2020 |title=UK motorsport industry in pole position for F1's 70th anniversary |url=https://www.gov.uk/government/news/uk-motorsport-industry-in-pole-position-for-f1s-70th-anniversary |access-date=19 February 2023 |publisher=UK Government |archive-date=19 February 2023 |archive-url=https://web.archive.org/web/20230219100712/https://www.gov.uk/government/news/uk-motorsport-industry-in-pole-position-for-f1s-70th-anniversary |url-status=live}}</ref> Seven of the eleven [[Formula One]] teams are based in the UK, with their technology being used in supercars and hypercars from [[McLaren Automotive|McLaren]], [[Aston Martin]] and [[Lotus Cars|Lotus]].{{Efn|Car brands here are classed as British based on several of the following criteria: historical heritage, cultural significance, design and engineering base, manufacturing location, headquarters location, UK registered company (even with overseas investors).}} The [[Aerospace industry in the United Kingdom|aerospace industry of the UK]] is the second-largest in the world<ref>{{cite web |title=United Kingdom - Country Commercial Guide: Aerospace and Defense |url=https://www.trade.gov/country-commercial-guides/united-kingdom-aerospace-and-defense |website=[[International Trade Administration]] |date=3 November 2023 |access-date=17 December 2024 |archive-date=12 June 2023 |archive-url=https://web.archive.org/web/20230612142750/https://www.trade.gov/country-commercial-guides/united-kingdom-aerospace-and-defense |url-status=live }}</ref> and has an annual turnover of around £30 billion.<ref>{{Cite news |last=Tovey |first=Alan |date=29 June 2016 |title=Britain's aerospace sector soars amid fears Brexit could clip its wings |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/business/2016/06/29/britains-aerospace-sector-soars-amid-fears-brexit-could-clip-its |url-status=live |url-access=subscription |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/business/2016/06/29/britains-aerospace-sector-soars-amid-fears-brexit-could-clip-its |archive-date=10 January 2022}}{{Cbignore}}</ref> The [[British space programme|UK space industry]] was worth £17.5 billion in 2020/21 and employed around 48,800 people.<ref>{{cite web |title=UK space sector income reaches £17.5 billion as jobs and services grow |url=https://www.ukspace.org/uk-space-sector-income-reaches-17-5-billion-as-jobs-and-services-grow/ |website=UKspace |date=27 March 2023}}</ref><ref>{{cite web |title=UK space sector income reaches £17.5 billion as jobs and services grow |url=https://www.gov.uk/government/news/uk-space-sector-income-reaches-175-billion-as-jobs-and-services-grow |website=gov.uk |date=29 March 2023 |access-date=10 August 2025}}</ref> The [[UK Space Agency]] has stated in 2023 that it is investing £1.6 billion in space-related projects.<ref>{{Cite web |url=https://www.gov.uk/government/news/new-funding-to-support-space-exploration-using-moon-resources-and-nuclear-power |title=New funding to support space exploration using Moon resources and nuclear power |access-date=11 March 2023 |archive-date=11 March 2023 |archive-url=https://web.archive.org/web/20230311195622/https://www.gov.uk/government/news/new-funding-to-support-space-exploration-using-moon-resources-and-nuclear-power}} <!-- (last checked 2023-03-11) --></ref>
The [[Agriculture in the United Kingdom|British agriculture industry]] is intensive, highly mechanised and efficient by European standards, producing approximately 60 per cent of the country's overall food requirements and 73 per cent of its indigenous food needs, utilising around 0.9 per cent of the labour force (292,000 workers).<ref>{{Cite web |title=UK Food Security Index 2024 |url=https://www.gov.uk/government/publications/uk-food-security-index-2024/uk-food-security-index-2024 |access-date=19 May 2024 |publisher=Department for the Environment Food & Rural Affairs |archive-date=18 May 2024 |archive-url=https://web.archive.org/web/20240518072412/https://www.gov.uk/government/publications/uk-food-security-index-2024/uk-food-security-index-2024 |url-status=live}};{{Cite web |title=Agricultural workforce in England at 1 June 2023 |url=https://www.gov.uk/government/statistics/agricultural-workforce-in-england-at-1-june/agricultural-workforce-in-england-at-1-june-2023 |access-date=19 May 2024 |publisher=Department for the Environment Food & Rural Affairs |archive-date=19 May 2024 |archive-url=https://web.archive.org/web/20240519211112/https://www.gov.uk/government/statistics/agricultural-workforce-in-england-at-1-june/agricultural-workforce-in-england-at-1-june-2023 |url-status=live}}</ref> Around two-thirds of production is devoted to [[livestock]] and one-third to [[arable crops]]. The UK retains a significant though much reduced fishing industry, with at least 49 per cent of UK fish sustainably caught in 2020.<ref>{{Cite web |url=https://jncc.gov.uk/our-work/ukbi-b2-sustainable-fisheries |title=Sustainable fisheries: fish stocks harvested within safe limits |website=JNCC |access-date=14 December 2024}}</ref> The UK marine natural capital assets were estimated to have a value of £211 billion in 2021.<ref>{{Cite web |title=Marine accounts, natural capital, UK: 2021 |date=6 April 2021 |url=https://www.ons.gov.uk/economy/environmentalaccounts/bulletins/marineaccountsnaturalcapitaluk/2021 |website=ONS |access-date=21 May 2025 |archive-url=https://web.archive.org/web/20250521071820/https://www.ons.gov.uk/economy/environmentalaccounts/bulletins/marineaccountsnaturalcapitaluk/2021 |archive-date=21 May 2025}}</ref> It is rich in a variety of other natural resources including coal, [[petroleum]], [[natural gas]], tin, limestone, iron ore, salt, clay, chalk, [[gypsum]], lead, and silica and has an abundance of arable land.<ref>{{Cite web |url=http://www.bgs.ac.uk/mineralsuk/mines/coal/home.html |title=Coal |website=BGS Minerals UK |access-date=7 July 2015 |archive-date=26 April 2009 |archive-url=https://web.archive.org/web/20090426141109/http://www.bgs.ac.uk/ |url-status=live}}</ref>
=== Science and technology ===
{{Main|Science and technology in the United Kingdom|Telecommunications in the United Kingdom}}
[[File:Cambridge Science Park Napp.jpg|thumb|The [[Cambridge Cluster]] is the most intensive research cluster for science and technology in the world.<ref>{{Cite book |last=WIPO |url=https://www.wipo.int/global_innovation_index/en/2022/index.html |title=Global Innovation Index 2022, 15th Edition |publisher=World Intellectual Property Organization |year=2022 |isbn=978-92-805-3432-0 |doi=10.34667/tind.46596 |access-date=16 November 2022 |archive-date=3 December 2022 |archive-url=https://web.archive.org/web/20221203061259/https://www.wipo.int/global_innovation_index/en/2022/index.html |url-status=live}}; {{Cite web |title=Global Innovation Index 2021 |url=https://www.wipo.int/global_innovation_index/en/2021 |access-date=5 March 2022 |website=[[World Intellectual Property Organization]] |publisher=[[United Nations]] |archive-date=5 March 2022 |archive-url=https://web.archive.org/web/20220305010458/https://www.wipo.int/global_innovation_index/en/2021/ |url-status=live}}; {{Cite web |title=Release of the Global Innovation Index 2020: Who Will Finance Innovation? |url=https://www.wipo.int/global_innovation_index/en/2020/index.html |access-date=2 September 2021 |website=World Intellectual Property Organization |archive-date=3 June 2021 |archive-url=https://web.archive.org/web/20210603121259/https://www.wipo.int/global_innovation_index/en/2020/index.html |url-status=live}}; {{Cite web |title=Global Innovation Index 2019 |url=https://www.wipo.int/global_innovation_index/en/2019/index.html |access-date=2 September 2021 |website=World Intellectual Property Organization |archive-date=2 September 2021 |archive-url=https://web.archive.org/web/20210902101818/https://www.wipo.int/global_innovation_index/en/2019/index.html |url-status=live}}; {{Cite web |title=RTD – Item |url=https://ec.europa.eu/newsroom/rtd/items/691898 |access-date=2 September 2021 |website=ec.europa.eu |archive-date=2 September 2021 |archive-url=https://web.archive.org/web/20210902140715/https://ec.europa.eu/newsroom/rtd/items/691898 |url-status=live}}</ref>]]
England and Scotland were leading centres of the [[Scientific Revolution]] from the 17th century.<ref>Gascoin, J. "A reappraisal of the role of the universities in the Scientific Revolution", in Lindberg, David C. and Westman, Robert S., eds (1990), ''Reappraisals of the Scientific Revolution''. Cambridge University Press. p. 248. {{ISBN|978-0-521-34804-1}}.</ref> The United Kingdom led the [[Industrial Revolution]] from the 18th century, and has continued to produce scientists and [[List of British engineers|engineers]] credited with [[List of British innovations and discoveries|important advances]].<ref>Reynolds, E.E.; Brasher, N.H. (1966). ''Britain in the Twentieth Century, 1900–1964''. Cambridge University Press. p. 336. {{OCLC|474197910}}</ref> Major theorists from the 17th and 18th centuries include [[Isaac Newton]], whose [[Newton's laws of motion|laws of motion]] and illumination of [[gravitation|gravity]] have been seen as a keystone of modern science;<ref>Burtt, E.A. (2003) 1924.[https://books.google.com/books?id=G9WBMa1Rz_kC&pg=PA207 ''The Metaphysical Foundations of Modern Science''] {{Webarchive|url=https://web.archive.org/web/20230326164803/https://books.google.com/books?id=G9WBMa1Rz_kC&pg=PA207 |date=26 March 2023 }}. Mineola, NY: Courier Dover. p. 207. {{ISBN|978-0-486-42551-1}}.</ref> from the 19th century [[Charles Darwin]], whose theory of [[evolution]] by [[natural selection]] was fundamental to the development of modern biology, and [[James Clerk Maxwell]], who formulated classical [[electromagnetic theory]]; and more recently [[Stephen Hawking]], who advanced major theories in the fields of [[cosmology]], [[quantum gravity]] and the investigation of [[black holes]].<ref>Hatt, C. (2006). [https://books.google.com/books?id=BVBvehqrAPQC ''Scientists and Their Discoveries''] {{Webarchive|url=https://web.archive.org/web/20230326164803/https://books.google.com/books?id=BVBvehqrAPQC |date=26 March 2023 }}. London: Evans Brothers. pp. 16, 30 and 46. {{ISBN|978-0-237-53195-9}}.</ref>
The [[Department for Science, Innovation and Technology]] (DSIT) is responsible for helping to develop and manage the UK's scientific, research, and technological outputs. Scientific research and development remains important in [[Universities in the United Kingdom|British universities]], with many establishing [[science park]]s to facilitate production and co-operation with industry.<ref>Castells, M.; Hall, P.; Hall, P.G. (2004). ''Technopoles of the World: the Making of Twenty-First-Century Industrial Complexes''. London: Routledge. pp. 98–100. {{ISBN|978-0-415-10015-1}}.</ref> In 2022, the UK produced [[List of countries by number of scientific and technical journal articles|6.0 per cent of the world's scientific research papers]] and had an 8.8 per cent share of scientific citations, the fourth and third highest among <abbr>G7</abbr> countries and Brazil, China, India, Russia, and South Korea. The UK ranked 1st among these countries for Field-Weighted Citation Impact.<ref>{{Cite web |title=International comparison of the UK research base, 2025 |url=https://www.gov.uk/government/publications/international-comparison-of-the-uk-research-base-2025/international-comparison-of-the-uk-research-base-2025 |access-date=2025-12-07 |website=GOV.UK |language=en}}</ref> Scientific journals produced in the UK include publications by the [[Royal Society]], ''[[Nature (journal)|Nature]]'', the ''[[BMJ|British Medical Journal]]'' and ''[[The Lancet]]''.<ref>{{Cite journal |last=McCook, Alison |year=2006 |title=Is peer review broken? |url=http://gaia.pge.utexas.edu/Good/Materials/scientist_02_28_2006.htm |journal=The Scientist |volume=20 |issue=2 |page=26 |archive-url=https://web.archive.org/web/20110816230933/http://gaia.pge.utexas.edu/Good/Materials/scientist_02_28_2006.htm |archive-date=16 August 2011 |access-date=22 June 2011}}</ref>
By 2024 the UK tech sector reached a value of US$1.2 trillion surpassing the combined values of the French and German sectors.<ref>{{Cite web |last=Greenberg |first=Elizabeth |date=2025-01-14 |title=UK Innovation Economy Worth a Combined $1.2 trillion |url=https://www.digit.fyi/uk-innovation-economy-worth-a-combined-1-2-trillion/ |access-date=2026-05-26 |publisher=Digit News |language=en |quote=Valued at $1.2 trillion collectively, the UK innovation ecosystem is worth more than the French and German ecosystems combined.}}</ref> Cambridge was named the number one university in the world for producing successful technology founders.<ref>{{Cite web |title=UK tech sector retains #1 spot in Europe and #3 in world as sector resilience brings continued growth |date=21 December 2022 |url=https://www.gov.uk/government/news/uk-tech-sector-retains-1-spot-in-europe-and-3-in-world-as-sector-resilience-brings-continued-growth |website=gov.uk |access-date=27 May 2025 |archive-url=https://web.archive.org/web/20250527173044/https://www.gov.uk/government/news/uk-tech-sector-retains-1-spot-in-europe-and-3-in-world-as-sector-resilience-brings-continued-growth |archive-date=27 May 2025}}</ref> The [[Artificial intelligence industry in the United Kingdom|UK's artificial intelligence industry]] is the largest in Europe by value<ref>{{Cite web |date=11 June 2024 |title=UK AI sector most valuable in Europe, new report reveals |url=https://www.holyrood.com/news/view,uk-ai-sector-most-valuable-in-europe-new-report-reveals |access-date=20 July 2025 |website=[[Holyrood (magazine)|Holyrood]] |language=en}}</ref> and the country ranked fifth globally in a 2026 report on artificial intelligence development by [[Stanford University]].<ref>{{Cite web |title=Which countries are leading in AI? {{!}} Stanford HAI |url=https://hai.stanford.edu/ai-index/global-vibrancy-tool |access-date=2026-05-09 |website=hai.stanford.edu |language=en}}</ref> The UK ranked 6th in the 2025 [[Global Innovation Index]].<ref>{{Cite web |title=GII Innovation Ecosystems & Data Explorer 2025 |url=https://www.wipo.int/gii-ranking/en/united-kingdom |access-date=16 October 2025 |website=WIPO}}</ref><ref>{{Cite book |last1=Dutta |first1=Soumitra |url=https://www.wipo.int/web-publications/global-innovation-index-2025/en/index.html |title=Global Innovation Index 2025: Innovation at a Crossroads |last2=Lanvin |first2=Bruno |publisher=[[World Intellectual Property Organization]] |year=2025 |isbn=978-92-805-3797-0 |page=19 |language=en |doi=10.34667/tind.58864 |access-date=17 October 2025}}</ref>
=== Transport ===
{{Main|Transport in the United Kingdom}}
{{further|Transport in England|Transport in Scotland|Transport in Wales|Transport in Northern Ireland}}
[[File:An LNER Azuma train on the East Coast Railway Line, geograph 6275180 by Walter Baxter.jpg|thumb|A high-speed [[East Coast Main Line]] train in [[Northumberland]], England]]
[[File:London City Airport Sunset.jpg|thumb|A plane taking off from [[London City Airport]]. [[Airports of London|London's airports]] make it the city with the [[List of busiest city airport systems by passenger traffic|busiest airport system]] in the world.]]
In the UK, all traffic [[Left- and right-hand traffic|drives on the left]], with distance and speed being measured in miles, yards and miles per hour (mph). All vehicles manufactured for use in the UK have the steering wheel situated on the right side of the vehicle. A radial road network totals {{Convert|29145|mi|km}} of main roads, {{Convert|2173|mi|km}} of motorways and {{Convert|213750|mi|km}} of paved roads.<ref name="factbook" /> The [[M25 motorway|M25]], encircling London, is the largest and busiest bypass in the world.<ref>{{Cite book |last=Moran |first=Joe |url=https://archive.org/details/readingeveryday00mora |title=Reading the Everyday |date=16 November 2005 |publisher=Routledge |isbn=978-1-134-37216-4 |page=[https://archive.org/details/readingeveryday00mora/page/n107 95] |url-access=limited}}</ref> In 2024 there were 41.7 million licensed vehicles in the UK.<ref>{{cite web |title=General facts and figures about roads and road use |url=https://www.racfoundation.org/motoring-faqs/mobility |access-date=31 May 2025 |archive-date=18 May 2025 |archive-url=https://web.archive.org/web/20250518191035/https://www.racfoundation.org/motoring-faqs/mobility}}</ref>
The UK has an extensive railway network of {{Convert|10072|mi|0|abbr=out}}. In Great Britain, the [[British Rail]] network [[privatisation of British Rail|was privatised]] between 1994 and 1997, followed by a rapid rise in passengers. [[Great British Railways]] is a planned state-owned public body that will oversee [[rail transport in Great Britain]]. The UK was ranked eighth amongst national European rail systems in the 2017 European Railway Performance Index assessing intensity of use, quality of service and safety.<ref>{{Cite web |last1=Sylvain Duranton |last2=Agnès Audier |last3=Joël Hazan |last4=Mads Peter Langhorn |last5=Vincent Gauche |date=18 April 2017 |title=The 2017 European Railway Performance Index |url=https://www.bcg.com/en-ch/publications/2017/transportation-travel-tourism-2017-european-railway-performance-index.aspx |publisher=Boston Consulting Group |access-date=4 February 2019 |archive-date=31 May 2020 |archive-url=https://web.archive.org/web/20200531104458/https://www.bcg.com/en-ch/publications/2017/transportation-travel-tourism-2017-european-railway-performance-index.aspx |url-status=live}}</ref>
A train runs directly from London to [[Paris]].<ref>{{Cite web |title=London to Paris Trains |url=https://www.eurostar.com/uk-en/train/london-to-paris |access-date=11 May 2024 |publisher=Eurostar |archive-url=https://web.archive.org/web/20240511114452/https://www.eurostar.com/uk-en/train/london-to-paris |archive-date=11 May 2024}}</ref> Called the [[Eurostar]], it travels through the [[Channel Tunnel]] under the [[English Channel]]. At 23.5 miles long, it is the world's longest undersea tunnel.<ref>{{Cite web |title=Channel Tunnel, Tunnel, Europe |url=https://www.britannica.com/topic/Channel-Tunnel |access-date=11 May 2024 |publisher=Britannica |date=10 May 2024}}</ref> There is also a car service through the tunnel to France called [[LeShuttle]]. The [[Elizabeth line]], a rail link running between [[East London|East]] and [[West London]], was named in honour of [[Queen Elizabeth II]] in 2016 and opened in 2022.<ref>{{Cite news |date=2 January 2012 |title=Crossrail's giant tunnelling machines unveiled |work=BBC News |url=https://www.bbc.co.uk/news/av/uk-16289051 |access-date=20 June 2018 |archive-date=10 April 2016 |archive-url=https://web.archive.org/web/20160410034914/http://www.bbc.co.uk/news/uk-16289051 |url-status=live}}; {{Cite news |last=Leftly |first=Mark |date=29 August 2010 |title=Crossrail delayed to save £1bn |work=Independent |location=London |url=https://www.independent.co.uk/news/business/news/crossrail-delayed-to-save-1631bn-2064629.html |access-date=22 August 2017 |archive-date=16 November 2020 |archive-url=https://web.archive.org/web/20201116062835/https://www.independent.co.uk/news/business/news/crossrail-delayed-to-save-1631bn-2064629.html |url-status=live}}</ref><ref>{{Cite web |title=Crossrail to become the Elizabeth line in honour of Her Majesty the Queen |url=https://tfl.gov.uk/info-for/media/press-releases/2016/february/crossrail-to-become-the-elizabeth-line-in-honour-of-her-majesty-the-queen |archive-url=https://web.archive.org/web/20230225110413/https://tfl.gov.uk/info-for/media/press-releases/2016/february/crossrail-to-become-the-elizabeth-line-in-honour-of-her-majesty-the-queen |archive-date=25 February 2023 |website=Transport for London}}</ref> Another major infrastructure project is [[High Speed 2]] (HS2), a high-speed railway under construction since 2019. It will link London with [[Birmingham]], with the potential to extend further north and capable of speeds of up to 225 mph.<ref>{{Cite web |title=What is HS2 |url=https://www.hs2.org.uk/what-is-hs2 |website=HS2 |access-date=22 June 2022 |archive-date=21 June 2022 |archive-url=https://web.archive.org/web/20220621190841/https://www.hs2.org.uk/what-is-hs2/ |url-status=live}}</ref><ref>{{Cite web |title=HS2 Trains |url=https://www.hs2.org.uk/building-hs2/trains/ |website=HS2 |access-date=24 February 2023 |archive-date=24 February 2023 |archive-url=https://web.archive.org/web/20230224183953/https://www.hs2.org.uk/building-hs2/trains/ |url-status=live}}</ref>
In 2023 there were 4 billion bus journeys in the UK, 1.8 billion of which were in London.<ref>{{Cite web |title=Transport Statistics Great Britain: 2023 Domestic Travel |date=19 December 2024 |url=https://www.gov.uk/government/statistics/transport-statistics-great-britain-2024/transport-statistics-great-britain-2023-domestic-travel |website=gov.uk |access-date=14 March 2025}}</ref> The red [[Double-decker bus|double-decker]] bus has entered popular culture as an internationally recognised icon of London and England.<ref>{{Cite web |title=Our Collection |url=http://www.icons.org.uk/theicons/index.html |access-date=16 August 2014 |publisher=icons.org.uk}}</ref> The [[London Buses|London bus network]] is extensive, with over 6,800 scheduled services every weekday carrying about 6 million passengers on over 700 different routes, making it one of the most extensive bus systems in the world and the largest in Europe.<ref>[http://www.tfl.gov.uk/corporate/modesoftransport/1548.aspx London Buses], Transport for London. Accessed 10 May 2007.</ref>
During 2024 [[List of airports in the United Kingdom and the British Crown Dependencies|British airports]] handled nearly 292.5 million passengers.<ref name="caastats">{{Cite web |title=Size of Reporting Airports 2024 |url=https://www.caa.co.uk/Documents/Download/11910/4d230d1f-dab6-4c1a-992a-431b9cca89a2/16918 |access-date=17 January 2025 |publisher=Civil Aviation Authority}}</ref> In that period the three largest airports were [[London Heathrow Airport]] (83.9 million passengers), [[Gatwick Airport]] (43.2 million passengers) and [[Manchester Airport]] (30.8 million passengers).<ref name="caastats" /> London Heathrow Airport, located {{Convert|15|mi|km|}} west of the capital, is the world's [[List of busiest airports by passenger traffic|second-busiest airport by international passenger traffic]] and has the most international passenger traffic of any airport in the world;<ref>{{Cite news |date=25 June 2008 |title=Heathrow 'needs a third runway' |work=BBC News |url=http://news.bbc.co.uk/1/hi/business/7472432.stm |access-date=17 October 2008}}; {{Cite press release |title=Statistics: Top 30 World airports |date=July 2008 |publisher=Airports Council International |url=http://www.aci.aero/aci/aci/file/Press%20Releases/2008/TOP30_International%20Passengers_2007.pdf |access-date=15 October 2008}}</ref> it is the hub for the UK flag carrier [[British Airways]], as well as [[Virgin Atlantic]].<ref>{{Cite news |date=29 October 2008 |title=BMI being taken over by Lufthansa |work=BBC News |url=http://news.bbc.co.uk/2/hi/7697261.stm |access-date=23 December 2009}}</ref> During 2023, 18.3 million passengers travelled internationally by rail and 18.1 million by sea.<ref>{{Cite web |title=Transport Statistics Great Britain: 2023 International Travel |date=19 December 2024 |url=https://www.gov.uk/government/statistics/transport-statistics-great-britain-2024/transport-statistics-great-britain-2023-international-travel |website=gov.uk |access-date=4 March 2025}}</ref>
=== Energy ===
{{Main|Energy in the United Kingdom}}
{{further|Energy in England|Energy in Scotland|Energy in Wales|Energy in Northern Ireland}}
In 2021 the UK was the world's [[List of countries by energy consumption and production|14th-largest consumer and 22nd-largest producer of energy]].<ref name="United Kingdom Energy Profile">{{Cite web |title=United Kingdom Energy Profile |url=https://www.eia.gov/international/overview/country/GBR |archive-url=https://web.archive.org/web/20230228165225/https://www.eia.gov/international/overview/country/GBR |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=U.S. Energy Information Administration}}</ref> It is home to [[Big Six energy suppliers|many large energy companies]], including two of the six major oil and gas companies{{snd}}[[BP]] and [[Shell plc|Shell]].<ref>{{Cite news |last=Mason |first=Rowena |date=24 October 2009 |title=Let the battle begin over black gold |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/finance/newsbysector/energy/6424030/Let-the-battle-begin-over-black-gold.html |url-status=live |url-access=subscription |access-date=26 November 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/finance/newsbysector/energy/6424030/Let-the-battle-begin-over-black-gold.html |archive-date=10 January 2022}}{{Cbignore}}; {{Cite news |last=Heath |first=Michael |date=26 November 2010 |title=RBA Says Currency Containing Prices, Rate Level 'Appropriate' in Near Term |work=Bloomberg |location=New York |url=https://www.bloomberg.com/news/2010-11-25/rba-s-stevens-says-inflation-unlikely-to-fall-much-further.html |access-date=26 November 2010}}</ref>
[[File:Ardrossan's fan club. - panoramio.jpg|thumb|Wind turbines overlooking [[Ardrossan]] in Scotland. The UK is [[Wind power in the United Kingdom|a major producer of wind energy]] in Europe.<ref>{{Cite web |date=13 September 2023 |title='Success story': Which European countries are leading the way on wind? |url=https://www.euronews.com/green/2023/09/13/winds-of-change-which-european-countries-are-generating-the-most-energy-from-wind |access-date=15 August 2025 |website=[[Euronews]] |language=en}}</ref>]]
Renewable electricity sources provided 51 per cent of the electricity generated in the UK in 2024. [[Wind power in the United Kingdom|Wind power]] was the largest source of electricity in 2024, generating 30 per cent of the UK's total electricity.<ref name="2024 Energy">{{Cite report |title=Britain's Electricity Explained: 2024 Review |url=https://www.neso.energy/news/britains-electricity-explained-2024-review |archive-url=https://web.archive.org/web/20250126085830/https://www.neso.energy/news/britains-electricity-explained-2024-review |archive-date=26 January 2025 |access-date=26 January 2025 |publisher=NESO}}</ref> The UK has the largest offshore wind farm in the world, which is located off the coast of [[Yorkshire]].<ref>{{Cite report |date=14 June 2021 |title=Wind energy in the UK: June 2021 |work=UK Government |url=https://www.ons.gov.uk/economy/environmentalaccounts/articles/windenergyintheuk/june2021 |access-date=8 May 2023}}</ref>
In 2023 the UK had nine nuclear reactors generating about 15 per cent of the UK's electricity.<ref name="coal-ref">{{Cite web |title=Nuclear Power in the United Kingdom |url=https://world-nuclear.org/information-library/country-profiles/countries-t-z/united-kingdom.aspx |archive-url=https://web.archive.org/web/20230228175735/https://world-nuclear.org/information-library/country-profiles/countries-t-z/united-kingdom.aspx |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=World Nuclear Association}}</ref> There are two reactors under construction and more planned.<ref>{{Cite web |date=April 2013 |title=Nuclear Power in the United Kingdom |url=http://www.world-nuclear.org/info/inf84.html |archive-url=https://web.archive.org/web/20130214061431/http://www.world-nuclear.org/info/inf84.html |archive-date=14 February 2013 |access-date=9 April 2013 |publisher=World Nuclear Association}}</ref><ref>{{Cite news |title=Nuclear energy: What you need to know |url=https://www.gov.uk/government/news/nuclear-energy-what-you-need-to-know |archive-url=https://web.archive.org/web/20230228181113/https://www.gov.uk/government/news/nuclear-energy-what-you-need-to-know |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=UK Government}}</ref> In the late 1990s [[Nuclear power plants in the United Kingdom|nuclear power plants]] contributed around 25 per cent of the total annual electricity generation in the UK, but this has gradually declined as old plants have been shut down. The UK government is investing in [[small modular reactors]] that operate via [[nuclear fission]], as well as in research and development towards commercial [[fusion reactors]]. To that end the government entered into a partnership with the US in late 2023 to collaborate on fusion technology, with "a commercial grid-ready fusion reactor by 2040" stated as a goal.<ref>{{Cite news |title=UKAEA implementing the UK's fusion energy strategy |work=Open Access Government |date=7 March 2024 |url=https://www.openaccessgovernment.org/ukaea-implementing-the-uks-fusion-energy-strategy/174384/ |access-date=27 May 2024 |last1=Belderbos |first1=Harriet}};{{Cite magazine |title=UK nuclear fusion reactor sets new world record for energy output |url=https://www.newscientist.com/article/2415909-uk-nuclear-fusion-reactor-sets-new-world-record-for-energy-output/ |magazine=New Scientist |access-date=27 May 2024}}</ref>
At the end of 2023 it was estimated that there were 1.1 billion [[barrels of oil equivalent]] of "proven" and "probable" [[Oil and gas reserves and resource quantification|gas reserves]] and 2.3 billion boe of "proven" and "probable" [[North Sea oil|oil reserves]] offshore, reducing reliance on imports for energy security and transitioning to renewables.<ref>{{Cite report |title=UK Oil and Gas Reserves and Resources |url=https://www.nstauthority.co.uk/media/vtjkyqnf/uk-reserves-and-resources-report-as-at-end-2023.pdf |archive-url=https://web.archive.org/web/20250113172052/https://www.nstauthority.co.uk/media/vtjkyqnf/uk-reserves-and-resources-report-as-at-end-2023.pdf |archive-date=13 January 2025 |access-date=1 February 2025 |publisher=North Sea Transition Authority}}</ref> Emissions from UK gas production are roughly four times lower than imported [[liquefied natural gas]] (LNG), according to the [[North Sea Transition Authority|UK's oil and gas regulator]].<ref>{{Cite news |title=North Sea oil and gas claims fact-checked |work=BBC |date=22 January 2024 |url=https://www.bbc.co.uk/news/science-environment-67945281 |archive-url=https://web.archive.org/web/20250201182137/https://www.bbc.com/news/science-environment-67945281 |archive-date=1 February 2025 |access-date=1 February 2025}}</ref>
In September 2024 the last coal power station was closed, making [[coal]] no longer a power source in the UK.<ref name="2024 Energy" /> The UK currently has no [[fracking]] (hydraulic fracturing) for [[shale gas]] despite a large supply, due to environmental concerns.<ref>{{Cite news |title=UK's last fracking wells to be filled with cement despite dwindling gas stocks |date=29 January 2025 |url=https://www.cityam.com/uks-last-fracking-wells-to-be-filled-with-cement-despite-dwindling-gas-stocks/ |archive-url=https://web.archive.org/web/20250201182917/https://www.cityam.com/uks-last-fracking-wells-to-be-filled-with-cement-despite-dwindling-gas-stocks/ |archive-date=1 February 2025 |access-date=1 February 2025 |work=City AM}}</ref>
=== Water supply and sanitation ===
{{Main|Water supply and sanitation in the United Kingdom}}
Access to improved water supply and sanitation in the UK is universal. It was estimated that 96 per cent of households were connected to the sewer network in 2022.<ref>{{Cite web |url=https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/69582/pb6655-uk-sewage-treatment-020424.pdf |title=Sewage Treatment in the UK |publisher=DEFRA |website=assets.publishing.service.gov.uk |date=March 2022 |page=3 |id=PB 6655 |access-date=8 April 2023}}</ref> According to the [[Environment Agency]], total water abstraction for public water supply in the UK was 16,406 [[megalitre]]s per day in 2007.<ref>{{Cite web |title=Environment Agency |url=http://www.environment-agency.gov.uk/research/library/data/112185.aspx |archive-url=https://web.archive.org/web/20091125040346/http://www.environment-agency.gov.uk/research/library/data/112185.aspx |archive-date=25 November 2009}}</ref>
In England and Wales, water and sewerage services are provided by 10 private regional water and sewerage companies and 13 mostly smaller private "water only" companies. In Scotland, said services are provided by a single public company, [[Scottish Water]]. In Northern Ireland, they are also provided by a single public entity, [[Northern Ireland Water]].<ref>{{Cite web |title=About Us |url=https://www.niwater.com/about |access-date=29 August 2020 |publisher=niwater.com}}</ref>
== Demographics ==
{{Main|Demographics of the United Kingdom|British people}}
{{Further|Ceremonial counties of England|Subdivisions of Scotland|Subdivisions of Wales|Counties of Northern Ireland}}
[[File:Elderly British Couple.jpg|thumb|261x261px|An elderly British Couple. Approximately 24% of people in England and Wales are aged 60 years and over.<ref>{{Cite web |date=2023-03-31 |title=Age groups |url=https://www.ethnicity-facts-figures.service.gov.uk/uk-population-by-ethnicity/demographics/age-groups/latest/#main-facts-and-figures |access-date=2026-08-16 |website=www.ethnicity-facts-figures.service.gov.uk |language=en}}</ref>]]
Whereas the censuses of England and Wales and of Northern Ireland went ahead as planned in 2021, the census in Scotland was delayed until 2022 due to the COVID-19 pandemic. The Office for National Statistics has estimated that the total population of the United Kingdom recorded in the census would have been 66,912,637 had it been conducted in all parts of the UK on 21 March 2021.<ref name=Ethnicity2021/> The UK population is the [[List of European countries by population|fourth-largest]] in Europe and the [[List of countries by population|22nd-largest]] in the world. In 2012 and 2013 births contributed the most to population growth, while in 2014 and 2015 net international migration contributed more.<ref name="pop2015">{{Cite web |date=23 June 2016 |title=Population Estimates for UK, England and Wales, Scotland and Northern Ireland, Mid-2015 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/bulletins/annualmidyearpopulationestimates/latest |publisher=Office for National Statistics}}</ref> Between 2001 and 2011 the population increased at an average annual rate of 0.7 per cent.<ref name="2011census">{{Cite web |date=21 December 2022 |title=Population estimates for the UK, England, Wales, Scotland and Northern Ireland: mid-2021 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/bulletins/annualmidyearpopulationestimates/mid2021 |access-date=16 April 2025 |publisher=Office for National Statistics}}</ref> The [[2011 United Kingdom census|2011 census]] also showed that, over the previous 100 years, the proportion of the population aged 0–14 fell from 31 to 18 per cent, and the proportion of people aged 65 and over rose from 5 to 16 per cent.<ref name="2011census" /> In 2018 the [[median age]] of the UK population was 41.7 years.<ref name="factbook" /> The 2021 census put Scotland's population at 5.48 million, Wales's at 3.1 million and Northern Ireland's at 1.9 million.<ref name="2011census" />
<!-- Self-maintaining population table -->
{{UK population table}}
England's population in 2021 was 56 million, representing some 84 per cent of the UK total.<ref name="2011census" /> England is one of the [[List of countries and dependencies by population density|most-densely-populated countries]] in the world, with 434 people per square kilometre in mid-2021,<ref name="2011census" /> with a particular concentration in London, the capital,<ref>{{Cite news |date=2012-05-10 |title=United Kingdom country profile |url=https://www.bbc.co.uk/news/world-europe-18023389 |access-date=2026-07-24 |work=BBC News |language=en-GB}}</ref><ref>{{Cite web |title=United Kingdom - Country Profile {{!}} OpenFactBook World Factbook |url=https://openfactbook.org/countries/united-kingdom/ |access-date=2026-07-24 |website=openfactbook.org |language=en}}</ref> and the south-east.<ref>{{Cite news |last=Khan |first=Urmee |date=16 September 2008 |title=England is most crowded country in Europe |url=https://www.telegraph.co.uk/news/newstopics/politics/2967374/England-is-most-crowded-country-in-Europe.html |archive-url=https://web.archive.org/web/20080918221002/http://www.telegraph.co.uk/news/newstopics/politics/2967374/England-is-most-crowded-country-in-Europe.html |archive-date=18 September 2008 |access-date=5 September 2009 |work=The Telegraph |location=London}}</ref> [[London metropolitan area|London's wider metropolitan area]] is the largest in [[Western Europe]], with a population of 14.9 million in 2024.<ref>{{Cite web |title=Major Agglomerations |url=http://citypopulation.de/en/world/agglomerations |url-status=live |archive-url=https://web.archive.org/web/20231004094531/https://www.citypopulation.de/en/world/agglomerations/ |archive-date=4 October 2023 |access-date=16 October 2023}}</ref>
{| class="wikitable sortable" style="text-align:right;"
|+ Population of England by region ({{UK subdivision statistics year}})<ref name="ONS mid-year pop est" />
|-
! Rowspan=2 | Region
! Colspan=2 | Land area
! Colspan=2 | Population
! Rowspan=2 | Density<br />(/km<sup>2</sup>)
|-
! (km<sup>2</sup>)
! (%)
! People
! (%)
|-
| style="text-align:left;" | [[North East England|North East]]
| 8,581
| 6%
| 2,683,040
| 5%
| 313
|-
| style="text-align:left;" | [[North West England|North West]]
| 14,108
| 11%
| 7,516,113
| 13%
| 533
|-
| style="text-align:left;" | [[Yorkshire and the Humber]]
| 15,404
| 12%
| 5,541,262
| 10%
| 360
|-
| style="text-align:left;" | [[East Midlands]]
| 15,624
| 12%
| 4,934,939
| 9%
| 316
|-
| style="text-align:left;" | [[West Midlands (region)|West Midlands]]
| 12,998
| 10%
| 6,021,653
| 11%
| 463
|-
| style="text-align:left;" | [[East of England]]
| 19,116
| 15%
| 6,398,497
| 11%
| 335
|-
| style="text-align:left;" | [[Greater London]]
| 1,572
| 1%
| 8,866,180
| 15%
| 5,640
|-
| style="text-align:left;" | [[South East England|South East]]
| 19,072
| 15%
| 9,379,833
| 16%
| 492
|-
| style="text-align:left;" | [[South West England|South West]]
| 23,836
| 18%
| 5,764,881
| 10%
| 242
|-
! style="text-align:left;" | England
! style="text-align:right;" | 130,310
! style="text-align:right;" | 100%
! style="text-align:right;" | 57,106,398
! style="text-align:right;" | 100%
! style="text-align:right;" | 438
|}
In 2021 the [[total fertility rate]] across the UK was 1.53 children born per woman,<ref>{{Cite web |title=Vital statistics: population and health reference tables |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/vitalstatisticspopulationandhealthreferencetables |access-date=6 March 2018 |website=Office for National Statistics}}</ref> which remains considerably below the [[Mid-20th century baby boom|baby boom]] peak of 2.95 children per woman in 1964,<ref>{{Cite news |last=Boseley |first=Sarah |date=14 July 2008 |title=The question: What's behind the baby boom? |url=https://www.theguardian.com/lifeandstyle/2008/jul/14/familyandrelationships.women |access-date=28 August 2009 |work=The Guardian |location=London |page=3}}</ref> or the high of 6.02 children born per woman in 1815<ref>{{Citation |last=Roser |first=Max |title=Total Fertility Rate around the world over the last centuries |date=2014 |work=[[Our World in Data]], [[Gapminder Foundation]] |url=https://ourworldindata.org/grapher/children-born-per-woman?year=1800&country=GBR |access-date=10 December 2019 |archive-url=https://web.archive.org/web/20190705121623/https://ourworldindata.org/grapher/children-born-per-woman?year=1800&country=GBR |archive-date=5 July 2019}}</ref> and below the replacement rate of 2.1. In 2011, 47.3 per cent of births in the UK were to unmarried women.<ref>[http://epp.eurostat.ec.europa.eu/tgm/table.do?tab=table&plugin=0&language=en&pcode=tps00018 Tables, Graphs and Maps Interface (TGM) table]. Eurostat (26 February 2013). Retrieved 12 July 2013.</ref> The [[Office for National Statistics]] reported in 2015 that amongst the UK population aged 16 and over, 1.7 per cent identify as gay, lesbian, or bisexual (2.0 per cent of males and 1.5 per cent of females); 4.5 per cent of respondents responded with "other", "I don't know", or did not respond.<ref>{{Cite web |date=5 October 2016 |title=Sexual identity, UK: 2015 – Experimental Official Statistics on sexual identity in the UK in 2015 by region, sex, age, marital status, ethnicity and NS-SEC |url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/sexuality/bulletins/sexualidentityuk/2015 |access-date=19 January 2017 |publisher=[[Office for National Statistics]]}}</ref> The number of [[transgender]] people in the UK was estimated to be between 65,000 and 300,000 by research between 2001 and 2008.<ref>{{Cite web |title=Research report 27: Trans research review |url=http://www.equalityhumanrights.com/about-us/our-work/key-projects/trans-inequalities-reviewed/introduction-to-the-review |url-status=dead |archive-url=https://web.archive.org/web/20150706020643/http://www.equalityhumanrights.com/about-us/our-work/key-projects/trans-inequalities-reviewed/introduction-to-the-review |archive-date=6 July 2015 |access-date=26 November 2021 |website=equalityhumanrights.com |page=v}}</ref>
{{Largest Urban Areas of the United Kingdom}}
=== Ethnicity ===
{{Main|Ethnic groups in the United Kingdom}}
Historically, indigenous British people were thought to be [[Genetic history of the British Isles|descended from ethnic groups]] that settled there before the 12th century: the [[Celts]], Romans, Anglo-Saxons, Norse and the [[Normans]]. [[Welsh people]] could be the oldest ethnic group in the UK.<ref>{{Cite news |date=19 June 2012 |title=Welsh people could be most ancient in UK, DNA suggests |url=https://www.bbc.co.uk/news/uk-wales-18489735 |access-date=28 April 2013 |work=BBC News}}</ref> The UK has a history of non-white immigration with [[Liverpool]] having the oldest black population in the country dating from at least the 1730s,<ref>{{Cite book |last=Winder |first=Robert |url=https://books.google.com/books?id=7ORcaQIgdcEC&q=combed&pg=PT94 |title=Bloody Foreigners: The Story of Immigration to Britain |date=2010 |publisher=Little, Brown Book |isbn=978-0-7481-2396-4}}; {{Cite book |last=Costello |first=Ray |title=Black Liverpool: The Early History of Britain's Oldest Black Community 1730–1918 |date=2001 |publisher=Picton Press |isbn=978-1-873245-07-1 |location=Liverpool}}</ref> in addition to having the oldest [[British Chinese|Chinese]] community in Europe dating from the 19th century.<ref>{{Cite web |title=Culture and Ethnicity Differences in Liverpool – Chinese Community |url=http://www.mersey-gateway.org/server.php?show=ConWebDoc.1369 |archive-url=https://web.archive.org/web/20090724204513/http://www.mersey-gateway.org/server.php?show=ConWebDoc.1369 |archive-date=24 July 2009 |access-date=9 March 2015 |publisher=Chambré Hardman Trust}}</ref>
In 2021, 83.1 per cent of the UK population was classified as white, 8.6 per cent as Asian or Asian British, 3.7 per cent as Black or Black British, 2.7 per cent as mixed ethnicity, and 2.0 per cent other.<ref name=Ethnicity2021/> Ethnic diversity varies significantly across the UK. In 2021, 46.2 per cent of London's population was from a non-white ethnic minority,<ref name=Regionaldiversity>{{cite news|url=https://www.ethnicity-facts-figures.service.gov.uk/uk-population-by-ethnicity/national-and-regional-populations/regional-ethnic-diversity/latest/|title=Regional ethnic diversity|publisher=Office for National Statistics|date=22 December 2022|access-date=28 March 2026}}</ref> compared less than 10 per cent in the South West and North East of England, Wales,<ref name=Regionaldiversity/> Scotland<ref>{{cite news|url=https://www.scotlandscensus.gov.uk/census-results/at-a-glance/ethnicity/|title=Ethnicity|publisher=National Records of Scotland|date=4 February 2025|access-date=28 March 2026}}</ref> and Northern Ireland.<ref>{{cite web|url=https://www.nisra.gov.uk/system/files/statistics/census-2021-ms-b01.xlsx|title=MS-B01: Ethnic group|publisher=Northern Ireland Statistics and Research Agency|date=30 November 2023|access-date=28 March 2026}}</ref>
=== Language ===
{{Main|Languages of the United Kingdom}}
The [[English language]] is the ''[[de facto]]'' official and most widely spoken language in the United Kingdom.<ref>{{Cite web |title=English language – Government, citizens and rights |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012519 |archive-url=http://webarchive.nationalarchives.gov.uk/20121015000000/http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012519 |archive-date=15 October 2012 |access-date=23 August 2011 |website=[[Directgov]]}}</ref><ref>{{Cite journal |last=Mac Sithigh |first=Daithí |date=17 May 2018 |title=Official status of languages in the UK and Ireland |url=https://pureadmin.qub.ac.uk/ws/portalfiles/portal/141540053/Status_OA_Feb_2018.pdf |journal=Common Law World Review |publisher=Queen's University, Belfast |volume=47 |issue=1 |pages=77–102 |doi=10.1177/1473779518773642 |s2cid=219987922}}</ref> The UK promotes the language globally to build connections, understanding and trust between people in the UK and countries worldwide.<ref>British Council {{Cite web |title=British Council | the UK's international culture and education organisation |url=https://www.britishcouncil.org/ |url-status=live |archive-url=https://web.archive.org/web/20230201181104/https://www.britishcouncil.org/ |archive-date=1 February 2023 |access-date=5 December 2018}} (last checked 6 February 2023)</ref><ref>{{Cite web |title=About BBC Learning English |url=https://www.bbc.com/learningenglish/english/hygiene |url-status=live |archive-url=https://web.archive.org/web/20230204204233/https://www.bbc.com/learningenglish/english/hygiene |archive-date=4 February 2023 |access-date=9 February 2023 |website=BBC}}</ref>
In the UK, the English language is spoken with distinctive characteristics that collectively form what is known as [[British English]]. The variety of dialects and accents is often noted, with nearby regions frequently having highly distinct variations. [[Received Pronunciation]] is traditionally associated with educated speakers in southern England.<ref>{{Cite web |title=British English Pronunciations |url=https://www.oed.com/information/understanding-entries/pronunciation/british-english-pronunciations/?tl=true |archive-url=https://web.archive.org/web/20250605075115/https://www.oed.com/information/understanding-entries/pronunciation/british-english-pronunciations/?tl=true |archive-date=5 June 2025 |access-date=5 June 2025 |website=OED}}</ref> The main national dialects are [[Scottish English]], [[Welsh English]] and [[Northern Irish English]]. Distinctive regional varieties include
[[Brummie dialect|Brummie]], [[Cockney]], [[Geordie]], [[Manchester dialect|Mancunian]], [[Scouse]], [[West Country English|West Country]], [[Yorkshire dialect|Yorkshire]] and [[Multicultural London English|MLE]] (Multicultural London English).<ref>{{Cite web |title=10 British dialects you need to know |url=https://www.ef.com/wwen/blog/language/british-dialects-you-need-to-know/ |website=EF |access-date=5 June 2025}}</ref>
[[File:Bilingual welcome sign Newry.jpg|thumb|[[Bilingual sign]] ([[Irish language|Irish]] and [[English language|English]]) in [[Newry]], Northern Ireland]]Three indigenous [[Celtic languages]] are spoken in the UK: [[Welsh language|Welsh]], [[Irish language|Irish]] and [[Scottish Gaelic]]. [[Cornish language|Cornish]], which became extinct as a first language in the late-18th century, is being revived and has a small group of second-language speakers.<ref>{{Cite book |last1=Track |first1=Robert Lawrence |url=https://books.google.com/books?id=oLx9AgAAQBAJ&q=%E2%80%9Cthese+people+speak+the+dead+language+as+a+second+language%E2%80%9D&pg=PA63 |title=Language and Linguistics: The Key Concepts |last2=Stockwell, Peter |date=2007 |isbn=978-0-415-41358-9 |page=63 |publisher=Routledge |access-date=4 August 2019}}; {{Cite web |title=Framework Convention for the Protection of National Minorities, Strasbourg, 1.II.1995 |url=http://conventions.coe.int/Treaty/en/Treaties/Html/157.htm |access-date=9 March 2015 |publisher=Council of Europe |archive-date=22 February 2005 |archive-url=https://web.archive.org/web/20050222193410/http://conventions.coe.int/Treaty/EN/treaties/Html/157.htm |url-status=dead}}; {{Cite web |title=European Charter for Regional or Minority Languages, Strasbourg, 5.XI.1992 |url=http://conventions.coe.int/treaty/en/Treaties/Html/148.htm |access-date=9 March 2015 |publisher=Council of Europe |archive-date=26 February 2011 |archive-url=https://web.archive.org/web/20110226052008/http://conventions.coe.int/Treaty/EN/Treaties/HTML/148.htm |url-status=dead}}</ref><ref name="reglang" /> In the [[2021 United Kingdom census|2021 census]] the [[Welsh-speaking population]] of Wales aged three or older was 538,300 (17.8 per cent).<ref>{{Cite web |date=6 December 2022 |title=Welsh language in Wales (Census 2021) |url=https://gov.wales/welsh-language-wales-census-2021-html |access-date=6 December 2022 |website=gov.wales}}</ref> In addition it is estimated that about 200,000 Welsh-speakers live in England.<ref>{{Cite web |last=Wynn Thomas |first=Peter |date=March 2007 |title=Welsh today |url=https://www.bbc.co.uk/voices/multilingual/welsh.shtml |access-date=5 July 2011 |website=Voices |publisher=BBC}}</ref> In the 2021 census in Northern Ireland 12.4 per cent of people had some [[Irish language in Northern Ireland|Irish language]] ability and 10.4 per cent had some facility in the [[Ulster Scots dialect|Ulster-Scots]] language.<ref>{{Cite web |title=Census 2021: Main statistics for Northern Ireland |url=https://www.nisra.gov.uk/system/files/statistics/census-2021-main-statistics-for-northern-ireland-phase-1-statistical-bulletin-language.pdf |archive-url=https://web.archive.org/web/20240210110853/https://www.nisra.gov.uk/system/files/statistics/census-2021-main-statistics-for-northern-ireland-phase-1-statistical-bulletin-language.pdf |archive-date=10 February 2024 |access-date=10 February 2024}}</ref>
In 2001, over 92,000 people in Scotland, just under 2 per cent of the population, had some Gaelic language ability, including 72 per cent of those living in the [[Outer Hebrides]].<ref>{{Cite web |title=Scotland's Census 2001 – Gaelic Report |url=http://www.gro-scotland.gov.uk/press/news2005/scotlands-census-2001-gaelic-report.html |archive-url=https://web.archive.org/web/20130522110328/http://www.gro-scotland.gov.uk/press/news2005/scotlands-census-2001-gaelic-report.html |archive-date=22 May 2013 |access-date=28 April 2013 |publisher=General Register Office for Scotland}}</ref> The number of children being taught either Welsh or Scottish Gaelic is increasing.<ref>{{Cite news |date=12 February 2009 |title=Local UK languages 'taking off' |url=http://news.bbc.co.uk/1/hi/education/7885493.stm |work=BBC News}}</ref> [[Scots language|Scots]], a language descended from early northern [[Middle English]], has limited [[European Charter for Regional or Minority Languages|recognition]] alongside its regional variant, [[Ulster Scots dialects|Ulster Scots]] in Northern Ireland, without specific commitments to protection and promotion.<ref name="reglang" /><ref>{{Cite web |title=Language Data – Scots |url=http://www.eurolang.net/index.php?option=com_content&task=view&id=2449&Itemid=52&lang=en |archive-url=https://web.archive.org/web/20070623185445/http://eurolang.net/index.php?option=com_content&task=view&id=2449&Itemid=52&lang=en |archive-date=23 June 2007 |access-date=2 November 2008 |publisher=European Bureau for Lesser-Used Languages}}</ref> As of April 2020 there are around 151,000 users of [[British Sign Language]] (BSL), a [[sign language]] used by deaf people, in the UK.<ref>{{Cite news |last=Brown |first=Hannah |date=23 April 2020 |title='People are dying because of this': Calls for UK Gov to follow Scotland with sign language interpreter at Covid-19 briefing |url=https://www.scotsman.com/news/politics/people-are-dying-because-calls-uk-gov-follow-scotland-sign-language-interpreter-covid-19-briefing-2547989 |access-date=19 December 2021 |work=The Scotsman}}</ref>
In 2013, it was estimated that 95 per cent of the UK's population were [[monolingual]] English speakers.<ref name="BBC languages">{{Cite web |title=Languages across Europe: United Kingdom |url=https://www.bbc.co.uk/languages/european_languages/countries/uk.shtml |access-date=4 February 2013 |website=BBC}}</ref> In 2013, over 5 per cent of the population were estimated to speak languages brought to the UK as a result of immigration.<ref name="BBC languages" /> [[South Asian languages]] are the largest group, which includes [[Punjabi language|Punjabi]], [[Urdu]], [[Bengali language|Bengali]], [[Sylheti language|Sylheti]], [[Hindi]], [[Pahari-Pothwari]], [[Tamil language|Tamil]] and [[Gujarati language|Gujarati]].<ref>Carl Skutsch (2013). ''Encyclopedia of the World's Minorities''. pp.1261. Routledge. Retrieved 3 December 2020.</ref> In the 2011 census [[Polish language|Polish]] was the second-largest language spoken in England, with 546,000 speakers.<ref>{{Cite news |last=Booth |first=Robert |date=30 January 2013 |title=Polish becomes England's second language |url=https://www.theguardian.com/uk/2013/jan/30/polish-becomes-englands-second-language |access-date=4 February 2012 |work=The Guardian |location=London}}</ref> In 2019 some three-quarters of a million people spoke little or no English.<ref>{{Cite news |date=23 April 2019 |title=The teenagers who translate for their parents |url=https://www.bbc.co.uk/news/av/uk-47982494 |access-date=23 April 2019 |work=BBC News}}</ref>
=== Religion ===
{{Main|Religion in the United Kingdom|Freedom of religion in the United Kingdom}}
[[File:Westminster_Abbey_St_Peter.jpg|thumb|The [[Westminster Abbey]] in [[London]]. This was the [[Coronation of the British monarch|coronation]] site of 40 monarchs, 18 royal burials, and at least 16 royal weddings since 1100.]]
[[Christianity]] has dominated religious life in the United Kingdom for [[History of Christianity in Britain|more than 1,400 years]].<ref>Cannon, John, ed. (2nd edn., 2009). [https://books.google.com/books?id=TYnfhTq2M7EC&pg=PA144 ''A Dictionary of British History'']. Oxford University Press. p. 144. {{ISBN|978-0-19-955037-1}}.</ref> Although a majority of citizens still identify with Christianity in surveys, regular church attendance has fallen dramatically since the middle of the 20th century,<ref>Field, Clive D. (November 2009). [http://www.brin.ac.uk/wp-content/uploads/2011/12/development-of-religious-statistics.pdf "British religion in numbers"]. BRIN Discussion Series on Religious Statistics, Discussion Paper 001. Retrieved 7 March 2015.</ref> while immigration and demographic change have contributed to the growth of Islam and other faiths.<ref>Yilmaz, Ihsan (2005). [https://books.google.com/books?id=ryrD2YODzxUC&pg=PA291 ''Muslim Laws, Politics and Society in Modern Nation States: Dynamic Legal Pluralisms in England, Turkey, and Pakistan'']. Aldershot: Ashgate Publishing. pp. 55–56. {{ISBN|978-0-7546-4389-0}}.</ref> This has led some commentators to describe the UK as a multi-faith,<ref>Brown, Callum G. (2006). [https://books.google.com/books?id=ryrD2YODzxUC&pg=PA291 ''Religion and Society in Twentieth-Century Britain'']. Harlow: Pearson Education. p. 291. {{ISBN|978-0-582-47289-1}}.</ref> [[secularised]],<ref>Norris, Pippa; Inglehart, Ronald (2004). [https://books.google.com/books?id=dto-P2YfWJIC&pg=PA84 ''Sacred and Secular: Religion and Politics Worldwide'']. Cambridge University Press. p. 84. {{ISBN|978-0-521-83984-6}}.</ref> or [[post-Christian]] society.<ref>Fergusson, David (2004). [https://books.google.com/books?id=Owz4aBSEINgC&pg=PA94 ''Church, State and Civil Society'']. Cambridge University Press. p. 94. {{ISBN|978-0-521-52959-4}}.</ref>
In the 2021 census of England and Wales, 46.2 per cent of respondents reported that they were Christians, with the next largest faiths being [[Islam in the United Kingdom|Islam]] (6.5 per cent), [[Hinduism in the United Kingdom|Hinduism]] (1.7 per cent), [[Sikhism in the United Kingdom|Sikhism]] (0.9 per cent), [[Buddhism in the United Kingdom|Buddhism]] (0.5 per cent), [[Judaism in the United Kingdom|Judaism]] (0.5 per cent), and all other religions (0.6 per cent). Of the respondents, 37.2 per cent stated that they had [[Irreligion in the United Kingdom|no religion]] and a further 6.0 per cent did not answer the optional question.<ref>{{cite news|url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/religion/bulletins/religionenglandandwales/census2021|title=Religion, England and Wales: Census 2021|publisher=Office for National Statistics|first=Michael|last=Roskams|date=29 November 2022|access-date=28 March 2026}}</ref> In the census of Northern Ireland, 42.3 per cent of the population was recorded as Catholic, 37.7% as Protestant or other Christian, 1.3 per cent as belonging to other religions, 17.4 per cent as having no religion and 1.6 per cent did not state a religion.<ref>{{cite web|url=https://www.nisra.gov.uk/system/files/statistics/census-2021-ms-b19.xlsx|title=MS-B19: Religion|publisher=Northern Ireland Statistics and Research Agency|date=30 November 2023}}</ref> In Scotland's 2022 census, 51.1 per cent of the population stated that they had no religion, 20.4 per cent were recorded as Church of Scotland, 13.3 per cent as Catholic, 5.1 per cent as other Christian, 2.2 per cent as Muslim and 0.6 per cent as Hindu, with 1.2 per cent belonging to other religions and 6.2 per cent not stating a religion.<ref>{{cite web|url=https://www.scotlandscensus.gov.uk/2022-reports/scotland-s-census-2022-ethnic-group-national-identity-language-and-religion/|title=Scotland's Census 2022 - Ethnic group, national identity, language and religion|publisher=National Records of Scotland|date=21 May 2024|access-date=28 March 2026}}</ref>
A [[Tearfund]] survey in 2007 showed that one Briton in ten attends church weekly.<ref>{{Cite web |date=4 April 2007 |title=United Kingdom: New Report Finds Only One in 10 Attend Church |url=http://news.adventist.org/2007/04/uite-kigom-ew-report-fis-oly-oe-i-10-atte-church.html |archive-url=https://web.archive.org/web/20111213155625/http://news.adventist.org/2007/04/uite-kigom-ew-report-fis-oly-oe-i-10-atte-church.html |archive-date=13 December 2011 |access-date=9 March 2015 |website=News.adventist.org}}</ref> Between the 2001 and 2011 censuses there was a 12 per cent decrease in those who identified as Christian, while the percentage reporting no religious affiliation doubled. This contrasted with growth in the other main religious group categories, with the number of [[Muslims]] increasing the most to about 5 per cent.<ref>{{Cite news |last=Philby |first=Charlotte |date=12 December 2012 |title=Less religious and more ethnically diverse: Census reveals a picture of Britain today |url=https://www.independent.co.uk/news/uk/home-news/less-religious-and-more-ethnically-diverse-census-reveals-a-picture-of-britain-today-8406506.html |work=[[The Independent|Independent]] |location=London}}</ref>
The [[Church of England]] is the [[State religion|established church]] in England.<ref>{{Cite web |date=2004 |title=The History of the Church of England |url=http://www.cofe.anglican.org/about/history/ |url-status=dead |archive-url=https://web.archive.org/web/20100221212004/http://www.cofe.anglican.org/about/history |archive-date=21 February 2010 |access-date=23 November 2008 |website=The Church of England}}</ref> It retains [[Lords Spiritual|representation]] in the UK Parliament, and the British monarch is its [[Supreme Governor of the Church of England|Supreme Governor]].<ref>{{Cite web |title=Queen and Church of England |url=http://www.royalinsight.gov.uk/output/Page4708.asp |archive-url=https://web.archive.org/web/20061008203611/http://www.royalinsight.gov.uk/output/Page4708.asp |archive-date=8 October 2006 |access-date=5 June 2010 |publisher=British Monarchy Media Centre}}</ref> In [[religion in Scotland|Scotland]] the [[Church of Scotland]] is the [[national church]]. It is not subject to state control, and the British monarch is an ordinary member, required to swear an oath to "maintain and preserve the Protestant Religion and [[Presbyterian polity|Presbyterian Church Government]]" upon his or her accession.<ref>{{Cite web |title=Queen and the Church |url=http://www.royal.gov.uk/MonarchUK/QueenandChurch/History.aspx |url-status=live |archive-url=https://web.archive.org/web/20110605025533/http://www.royal.gov.uk/MonarchUK/QueenandChurch/History.aspx |archive-date=5 June 2011 |publisher=The British Monarchy (Official Website)}}</ref><ref name="reglang" /><ref>{{Cite web |date=22 February 2010 |title=Our structure |url=https://www.churchofscotland.org.uk/about-us/our-structure |url-status=live |archive-url=https://web.archive.org/web/20200125192732/https://www.churchofscotland.org.uk/about-us/our-structure |archive-date=25 January 2020 |website=churchofscotland.org.uk}}</ref> The [[Church in Wales]] was disestablished in 1920 and, because the [[Church of Ireland]] was disestablished in 1870 before the [[partition of Ireland]], there is no established church in Northern Ireland.<ref>Weller, Paul (2005). [https://books.google.com/books?id=tHc88PzAPLMC&pg=PA80 ''Time for a Change: Reconfiguring Religion, State, and Society'']. London: Continuum. pp. 79–80. {{ISBN|978-0-567-08487-3}}.</ref> Although there are no UK-wide data in the 2001 census on adherence to individual Christian denominations, it has been estimated that 62 per cent of Christians are Anglican, 13.5 per cent Catholic, 6 per cent Presbyterian, and 3.4 per cent Methodist, with smaller numbers of other denominations.<ref>Peach, Ceri, [https://books.google.com/books?id=i6ER_z8gcD4C "United Kingdom, a major transformation of the religious landscape"], in H. Knippenberg. ed. (2005). ''The Changing Religious Landscape of Europe''. Amsterdam: Het Spinhuis. pp. 44–58. {{ISBN|978-90-5589-248-8}}.</ref>
=== Migration ===
{{Main|Historical immigration to Great Britain|Modern immigration to the United Kingdom}}
{{See also|Foreign-born population of the United Kingdom}}
[[File:United Kingdom foreign born population by country of birth.png|thumb|upright=1.35|Estimated foreign-born population by country of birth from April 2007 to March 2008]]
[[File:British expats countrymap.svg|thumb|upright=1.35|Estimated number of British citizens living overseas by country in 2006:
{{legend|#002255|Greater than or equal to 1,000,000}}
{{legend|#003380|500,000 - 999,999}}
{{legend|#0044aa|100,000 - 499,999}}
{{legend|#0055d4|50,000 - 99,999}}
{{legend|#0066ff|10,000 - 49,999}}
{{legend|#2a7fff|5,000 - 9,999}}
{{legend|#5599ff|1,000 - 4,999}}
{{legend|#80b3ff|100 - 999}}
{{legend|#afc6e9|Less than 100 or no data}}
{{legend|#000000|UK}}
]]
Immigration is contributing to a rising population in the United Kingdom,<ref>{{Cite news |date=21 August 2008 |title=Immigration and births to non-British mothers pushes British population to record high |url=https://www.standard.co.uk/news/immigration-and-births-to-nonbritish-mothers-pushes-british-population-to-record-high-6816318.html |work=London Evening Standard}}</ref><ref name="bbc-23-05-2024">{{cite news |title=Migration: How many people come to the UK and how are the salary rules changing? |url=https://www.bbc.com/news/uk-48785695 |work=BBC News |date=23 May 2024}}</ref> with arrivals and UK-born children of migrants accounting for about half of the population increase between 1991 and 2001. According to statistics released in 2015, 27 per cent of UK live births in 2014 were to mothers born outside the UK.<ref>{{Cite web |date=15 July 2015 |title=Births in England and Wales: 2014 |url=http://www.ons.gov.uk/ons/rel/vsob1/birth-summary-tables--england-and-wales/2014/index.html |website=Office for National Statistics }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref>
In 2013 approximately 208,000 foreign nationals were naturalised as British citizens, the highest number since 1962. This figure fell to around 125,800 in 2014. Between 2009 and 2013 the average number of British citizenships granted annually was 195,800. The most common origins of those naturalised in 2024 were Pakistani, Indian, [[Nigeria]]n, [[Philippines|Filipino]], [[Bangladesh]]i, Italian, Turkish, Romanian and Iranian. The number of grants of settlement, which confer [[Permanent residency|permanent residence]] in the UK but not [[British citizenship|citizenship]],<ref>{{Cite web |last=Blinder |first=Scott |date=11 June 2014 |title=Settlement in the UK |url=http://www.migrationobservatory.ox.ac.uk/briefings/settlement-uk |archive-url=https://web.archive.org/web/20150906232123/http://migrationobservatory.ox.ac.uk/briefings/settlement-uk |archive-date=6 September 2015 |access-date=1 August 2015 |publisher=The Migration Observatory, University of Oxford}}</ref> was approximately 154,700 in 2013, higher than the previous two years.<ref name="Blinder2015">{{Cite web |last=Blinder |first=Scott |date=27 March 2015 |title=Naturalisation as a British Citizen: Concepts and Trends |url=http://www.migrationobservatory.ox.ac.uk/sites/files/migobs/Briefing%20-%20Naturalisation%20as%20a%20British%20Citizen%20-%20Concepts%20and%20Trends_0.pdf |archive-url=https://web.archive.org/web/20150916052200/http://www.migrationobservatory.ox.ac.uk/sites/files/migobs/Briefing%20-%20Naturalisation%20as%20a%20British%20Citizen%20-%20Concepts%20and%20Trends_0.pdf |archive-date=16 September 2015 |access-date=1 August 2015 |publisher=The Migration Observatory, University of Oxford}}</ref> Long-term net migration (the number of people immigrating minus the number emigrating) reached a record of 860,000 in 2023, with immigration at 1.326 million and emigration at 466,000. In comparison, in 2024 net migration was estimated to be 431,000 with immigration at 948,000 and emigration at 517,000.<ref>{{Cite web |title=Long-term international migration, provisional: year ending December 2024 |date=22 May 2025 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/internationalmigration/bulletins/longterminternationalmigrationprovisional/yearendingdecember2024 |website=gov.uk |access-date=22 May 2025}}</ref>
[[British diaspora|Emigration]] was an important feature of British society in the 19th century. Between 1815 and 1930, around 11.4 million people emigrated from Britain and 7.3 million from Ireland.<ref>{{Cite book |last=Hammar |first=Tomas |url=https://www.cambridge.org/core/books/european-immigration-policy/10B639425685B0C101619FA11522C409 |title=European Immigration Policy: A Comparative Study |date=1985 |publisher=Cambridge University Press |isbn=978-0-521-12437-9 |series=Comparative Ethnic and Race Relations |location=Cambridge}}</ref><ref name="richards-2018">{{Cite book |last=Richards |first=Eric |url=https://www.jstor.org/stable/j.ctvnb7rj2 |title=The genesis of international mass migration: The British case, 1750-1900 |date=2018 |publisher=Manchester University Press |edition=1 |jstor=j.ctvnb7rj2}}</ref> Estimates show that by the end of the 20th century, some 300 million people of British and Irish descent were permanently settled around the globe.<ref name="richards-2018" /> In 2006 at least 5.5 million UK-born people lived abroad,<ref name="BritsAbroad">{{Cite web |last1=Sriskandarajah |first1=Dhananjayan |last2=Drew |first2=Catherine |date=11 December 2006 |title=Brits Abroad: Mapping the scale and nature of British emigration |url=http://www.ippr.org/publicationsandreports/publication.asp?id=509 |archive-url=https://web.archive.org/web/20070828011816/http://www.ippr.org/publicationsandreports/publication.asp?id=509 |archive-date=28 August 2007 |access-date=9 March 2015 |publisher=Institute for Public Policy Research}}</ref><ref>{{Cite news |title=Brits Abroad: world overview |url=http://news.bbc.co.uk/1/shared/spl/hi/in_depth/brits_abroad/html/default.stm |access-date=20 April 2007 |publisher=BBC}}; {{Cite news |last=Casciani |first=Dominic |date=11 December 2006 |title=5.5 m Britons 'opt to live abroad' |work=BBC News |url=http://news.bbc.co.uk/2/hi/uk_news/6210358.stm |access-date=20 April 2007}}</ref> mainly in Australia, Spain, the United States and Canada.<ref name="BritsAbroad" /><ref>{{Cite news |date=11 December 2006 |title=Brits Abroad: Country-by-country |url=http://news.bbc.co.uk/2/hi/uk_news/6161705.stm |work=BBC News}}</ref>
=== Education ===
{{Main|Education in the United Kingdom|Universities in the United Kingdom}}
{{Further|Education in England|Education in Scotland|Education in Wales|Education in Northern Ireland}}
Education in the United Kingdom is a [[Devolution|devolved]] matter, with each country having a separate education system. About 38 per cent of the United Kingdom population has a university or [[college degree]], the highest percentage in Europe and one of the highest in the world.<ref>{{Cite web |date=24 September 2012 |title=The Most Educated Countries in the World |url=https://finance.yahoo.com/news/the-most-educated-countries-in-the-world.html;_ylt=AlaWy8IcyeBaviKi7_.WJyhE6odG;_ylu=X3oDMTJrY2d2NGZyBG1pdANDeFMgRmluYW5jaWFsbHkgRml0IEFydGljbGUgQXJ0aWNsZSBCb2R5IFByb2QEcG9zAzMEc2VjA01lZGlhQXJ0aWNsZUJvZHlBc3NlbWJseQ--;_ylg=X3oDMTNjdGVoaXJqBGludGwDdXMEbGFuZwNlbi11cwRwc3RhaWQDY2IyOTRhMGEtYmY2OS0zYTdlLThlYTUtZWFlNTU3YWI1ZTc3BHBzdGNhdANleGNsdXNpdmVzfGZpbmFuY2lhbGx5Zml0BHB0A3N0b3J5cGFnZQ--;_ylv=3?page=1 |archive-url=https://web.archive.org/web/20160204213400/http://finance.yahoo.com/news/the-most-educated-countries-in-the-world.html%3B_ylt%3DAlaWy8IcyeBaviKi7_.WJyhE6odG%3B_ylu%3DX3oDMTJrY2d2NGZyBG1pdANDeFMgRmluYW5jaWFsbHkgRml0IEFydGljbGUgQXJ0aWNsZSBCb2R5IFByb2QEcG9zAzMEc2VjA01lZGlhQXJ0aWNsZUJvZHlBc3NlbWJseQ--%3B_ylg%3DX3oDMTNjdGVoaXJqBGludGwDdXMEbGFuZwNlbi11cwRwc3RhaWQDY2IyOTRhMGEtYmY2OS0zYTdlLThlYTUtZWFlNTU3YWI1ZTc3BHBzdGNhdANleGNsdXNpdmVzfGZpbmFuY2lhbGx5Zml0BHB0A3N0b3J5cGFnZQ--%3B_ylv%3D3?page=1 |archive-date=4 February 2016 |access-date=20 April 2016 |website=Yahoo Finance }}; {{Cite magazine |date=27 September 2012 |title=And the World's Most Educated Country Is... |url=https://newsfeed.time.com/2012/09/27/and-the-worlds-most-educated-country-is/ |magazine=Time |location=New York |access-date=20 April 2016 |archive-date=30 April 2018 |archive-url=https://web.archive.org/web/20180430040213/http://newsfeed.time.com/2012/09/27/and-the-worlds-most-educated-country-is/ |url-status=dead }}</ref> The UK is home to [[List of universities in the United Kingdom|many universities]], including the [[University of Oxford]] and [[University of Cambridge]], which often achieve first place on global rankings.<ref>{{Cite web |title=The Times Higher Education World University Rankings 2024 |date=25 September 2023 |url=https://www.timeshighereducation.com/world-university-rankings/2024/world-ranking |access-date=17 April 2024}}</ref><ref>{{Cite web |title=QS World University Rankings 2024 |url=https://www.topuniversities.com/university-rankings/world-university-rankings/2024 |access-date=17 April 2024}}</ref>
University education has varied [[Student loans and grants in the United Kingdom|tuition fees]] in different regions of the UK. England and Wales have a fixed maximum annual fee for all UK citizens, contingent on attaining a certain level of income. Only those who reach a certain salary threshold pay this fee through [[Taxation in the United Kingdom|general taxation]].<ref>{{Cite web |title=Repaying your student loan |url=https://www.gov.uk/repaying-your-student-loan/what-you-pay |website=gov.uk |access-date=21 June 2025}}</ref> Northern Ireland and Scotland have a reduced maximum fee or no fee for citizens where it is their home region. Some NHS courses have bursaries which pay the fee and in 2017 it was stated that each doctor gets subsidised by £230,000 during their training.<ref>{{Cite web |date=20 October 2014 |title=Undergraduate Tuition Fess and Student Loans |url=https://www.ucas.com/money-and-student-life/money/student-finance/undergraduate-tuition-fees-and-student-loans |access-date=24 February 2024 |website=UCAS}}</ref><ref>{{Cite web |title=More undergraduate medical education places |url=https://www.gov.uk/government/news/more-undergraduate-medical-education-places |access-date=24 February 2024 |website=gov.uk}}</ref>
In 2022 the [[Programme for International Student Assessment]] (PISA), coordinated by the [[OECD]], ranked the overall knowledge and skills of British 15-year-olds as 14th in the world in reading, mathematics and science. The average British student scored 494, above the OECD average of 478.<ref>{{Cite web |title=PISA 2022 UK Results |url=https://www.oecd.org/publication/pisa-2022-results/country-notes/united-kingdom-9c15db47#chapter-d1e11 |access-date=24 February 2024 |website=OECD |date=4 December 2023}}</ref>
=== Health ===
{{Main|Health in the United Kingdom|Healthcare in the United Kingdom}}
{{Further|Healthcare in England|Healthcare in Scotland|Healthcare in Wales|Healthcare in Northern Ireland}}
[[File:QEUH.jpg|thumb|[[NHS Scotland]]'s [[Queen Elizabeth University Hospital]] in Glasgow, the largest hospital campus in Europe]]
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the establishment of the [[National Health Service]] (NHS), which began operating in 1948 as the primary healthcare provider in the United Kingdom.<ref>{{cite web |title=The foundation of the NHS |url=https://www.nationalarchives.gov.uk/explore-the-collection/stories/the-foundation-of-the-nhs/ |access-date=6 July 2026 |publisher=The National Archives}}</ref> The widespread popularity of the NHS has led to it being described as a "national religion".<ref>{{Cite news |last=Gill |first=Martha |date=9 July 2023 |title=To those who claim the NHS has turned into a British religion, I say: keep the faith |url=https://www.theguardian.com/commentisfree/2023/jul/09/nhs-british-religion-keep-faith-nhs-at-75 |access-date=16 July 2023 |work=The Observer}}</ref><ref>{{Cite web |date=14 April 2020 |title=Is the NHS our new national religion? – Religion Media Centre |url=https://religionmediacentre.org.uk/news/is-the-nhs-our-new-national-religion/ |access-date=16 July 2023 |website=religionmediacentre.org.uk}}</ref> Healthcare in the United Kingdom is a [[Devolution|devolved matter]] and each country has its own system of universal publicly funded healthcare ([[NHS England]], [[NHS Scotland]], [[Health and Social Care (Northern Ireland)]] and [[NHS Wales]]), although private healthcare is also available. Public healthcare is provided to all [[British nationality law|UK permanent residents]] and is mostly free at the point of need, being paid for from [[Taxation in the United Kingdom|general taxation]]. The [[World Health Organization]], in 2000, ranked the provision of healthcare in the United Kingdom as fifteenth-best in Europe and eighteenth in the world.<ref>{{Cite book |url=https://archive.org/details/worldhealthrepor00worl |title=The world health report 2000 – Health systems: improving performance |publisher=World Health Organization |date=2000 |isbn=978-92-4-156198-3 |editor-last=Haden |editor-first=Angela |location=Geneva |access-date=5 July 2011 |editor-last2=Campanini |editor-first2=Barbara}}; {{Cite web |last=World Health Organization |author-link=World Health Organization |title=Measuring overall health system performance for 191 countries |url=http://pages.stern.nyu.edu/~wgreene/Statistics/WHO-COMP-Study-30.pdf |access-date=5 July 2011 |publisher=New York University}}</ref>
Since 1979 expenditure on healthcare has increased significantly.<ref>{{Cite journal |last=Fisher |first=Peter |title=The NHS from Thatcher to Blair |url=http://www.healthp.org/node/71 |journal=NHS Consultants Association |archive-url=https://web.archive.org/web/20181120124807/http://www.healthp.org/node/71 |archive-date=20 November 2018 |access-date=19 December 2018 |quote=The Budget ... was even more generous to the NHS than had been expected amounting to an annual rise of 7.4 per cent above the rate of inflation for the next five years. This would take us to 9.4 per cent of GDP spent on health ie around EU average.}}</ref> The 2018 [[OECD]] data, which incorporates in health a chunk of what in the UK is classified as social care, has the UK spending £3,121 per person.<ref>{{Cite news |date=24 September 2019 |title=Swindells: They aren't 'your' patients |url=https://www.hsj.co.uk/policy-and-regulation/swindells-they-arent-your-patients/7025988.article? |access-date=19 November 2019 |publisher=Health Service Journal}}</ref> In 2017 the UK spent £2,989 per person on healthcare, near the median for members of the Organisation for Economic Co-operation and Development.<ref>{{Cite news |date=29 August 2019 |title=How does UK healthcare spending compare with other countries? |url=https://www.ons.gov.uk/peoplepopulationandcommunity/healthandsocialcare/healthcaresystem/articles/howdoesukhealthcarespendingcomparewithothercountries/2019-08-29 |access-date=5 October 2019 |publisher=Office of National Statistics}}</ref>
Regulatory bodies are organised on a UK-wide basis such as the [[General Medical Council]], the [[Nursing and Midwifery Council]] and non-governmental-based, such as the [[Medical royal college|Royal College]]s. Political and operational responsibility for healthcare lies with four national [[governments]]; healthcare in England is the responsibility of the UK Government; healthcare in Northern Ireland is the responsibility of the Northern Ireland Executive; healthcare in Scotland is the responsibility of the Scottish Government; and healthcare in Wales is the responsibility of the Welsh Government. Each National Health Service has different policies and priorities.<ref>{{Cite news |date=28 August 2008 |title='Huge contrasts' in devolved NHS |url=http://news.bbc.co.uk/1/hi/health/7586147.stm |work=BBC News}}; {{Cite news |last=Triggle |first=Nick |date=2 January 2008 |title=NHS now four different systems |work=BBC News |url=http://news.bbc.co.uk/1/hi/health/7149423.stm}}</ref>
== Culture ==
{{Main|Culture of the United Kingdom}}
{{Further|Culture of England|Culture of Scotland|Culture of Wales|Culture of Northern Ireland}}
The culture of the United Kingdom is influenced by the nation's island status, its history, and being a [[political union]] of four countries with each preserving distinctive traditions, customs and symbolism. British influence can be observed in the language, culture and [[Common law|legal systems]] of many of [[List of countries that have gained independence from the United Kingdom|its former colonies]], in particular the United States, Australia, Canada, New Zealand and Ireland, a common culture known as the Anglosphere.<ref>{{Cite book |last=Julian Go |title=Constitutionalism and political reconstruction |date=2007 |publisher=Brill |isbn=978-90-04-15174-1 |editor-last=Arjomand |editor-first=Saïd Amir |pages=92–94 |chapter=A Globalizing Constitutionalism?, Views from the Postcolony, 1945–2000 |chapter-url=https://books.google.com/books?id=kYmmnYKEvE0C&pg=PA94}}</ref>{{Sfn|Ferguson|2004|p=307}} Most of its former colonies are Commonwealth countries, bonded by a shared British inheritance.<ref>{{Cite web |title=The Commonwealth |url=https://www.mfat.govt.nz/en/peace-rights-and-security/the-commonwealth/ |access-date=8 January 2024 |website=[[New Zealand Ministry of Foreign Affairs and Trade]] |language=en-NZ}}</ref><ref>{{Cite web |title=Commonwealth of Nations |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny/parliament-and-empire/contemporary-context/ |access-date=2026-02-22 |publisher=UK Parliament |language=en}}</ref><ref>{{Cite book |last1=Mazrui |first1=Ali Al Amin |title=Anglo-African Commonwealth |last2=Taylor |first2=D. |last3=Bradley |first3=Kenneth |date=1967 |publisher=Pergamon |isbn=978-0-08-012253-3 |pages=40–41 |quote=...in the ultimate analysis, what could a New Zealander have in common with a Jamaican or a Zambian, if not the bonds of a shared British-ness?}}</ref> A global survey in 2024 ranked the UK third in the 'Most Influential Countries' rankings, behind the US and China.<ref>{{Cite web |title=Most Influential Countries |url=https://www.usnews.com/news/best-countries/most-influential-countries |access-date=22 September 2025 |website=[[U.S. News & World Report]]}}</ref>
=== Literature and drama ===
{{Main|British literature|Theatre of the United Kingdom}}
{{Further|Literature of England|Scottish literature|Welsh literature|Literature of Northern Ireland}}
{{multiple image
| align = right
| total_width = 320
| image1 = PG 1063Burns Naysmith.jpg
| alt1 = Robert Burns
| caption1 = [[Robert Burns]] (1759–1796)
| image2 = William Shakespeare by John Taylor, edited.jpg
| alt2 = William Shakespeare
| caption2 = [[William Shakespeare]] (1564–1616)
| footer = Burns and Shakespeare are considered the [[national poet]]s of Scotland and England respectively.
}}
British literature includes that associated with the United Kingdom, the [[Isle of Man]] and the [[Channel Islands]]. Most British literature is in English. In 2022, 669 million physical books were sold in the UK, the most ever.<ref>{{Cite web |title=UK publishing industry reports record-breaking year in 2022 |url=https://www.theguardian.com/books/2023/apr/17/uk-publishing-industry-reports-record-breaking-year-in-2022 |access-date=9 May 2024 |work=[[The Guardian]] |date=17 April 2023}}</ref> Britain is renowned for [[Literature for children|children's literature]]; writers include [[Daniel Defoe]], [[Rudyard Kipling]], [[Lewis Carroll]] and [[Beatrix Potter]], who also illustrated her own books. Other writers include [[A. A. Milne]], [[Enid Blyton]], [[J. R. R. Tolkien]], [[Roald Dahl]], [[Terry Pratchett]] and [[J. K. Rowling]], who wrote ''[[Harry Potter]]'', the [[List of best-selling book series|best-selling book series]] of all time.<ref>{{Cite web |title=Best-selling Book Series Of All Time |url=https://wordsrated.com/best-selling-book-series-of-all-time-statistics/ |access-date=18 May 2024 |publisher=Wordsrated |date=20 July 2023}}</ref>
The playwright and poet [[William Shakespeare]] is generally regarded as the greatest dramatist ever and the [[national poet]] of England.<ref>{{Cite web |title=William Shakespeare (English author) |url=https://www.britannica.com/EBchecked/topic/537853/William-Shakespeare |access-date=26 February 2006 |publisher=[[Encyclopædia Britannica]]}}; {{Cite encyclopedia |title=MSN Encarta Encyclopedia article on Shakespeare |url=http://encarta.msn.com/encyclopedia_761562101/Shakespeare.html |access-date=26 February 2006 |archive-url=https://web.archive.org/web/20060209154055/http://encarta.msn.com/encyclopedia_761562101/Shakespeare.html |archive-date=9 February 2006}}; {{Cite web |title=William Shakespeare |work=TheFreeDictionary.com |publisher=Columbia Electronic Encyclopedia |url=http://encyclopedia2.thefreedictionary.com/Shakespeare%2c+William |access-date=26 February 2006}}</ref> Theatre of United Kingdom plays an important part in British culture and has had a vibrant tradition of [[theatre]] since the Renaissance with roots going back to the Roman occupation. Other important figures in the literature of England are [[Geoffrey Chaucer]], known for ''[[The Canterbury Tales]]'', the poet [[William Wordsworth]], and other [[Romantic Poetry|Romantic poets]], also the novelists [[Charles Dickens]], [[H. G. Wells]], [[George Orwell]], [[Aldous Huxley]] and [[Ian Fleming]]. The 20th-century English crime writer [[Agatha Christie]] is the [[List of best-selling fiction authors|best-selling novelist]] in history.<ref>{{Cite news |date=19 December 2005 |title=Mystery of Christie's success is solved |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/uknews/1505799/Mystery-of-Christies-success-is-solved.html |url-status=live |url-access=subscription |access-date=14 November 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/news/uknews/1505799/Mystery-of-Christies-success-is-solved.html |archive-date=10 January 2022}}{{Cbignore}}</ref> Twelve of the top 25 of 100 novels by British writers chosen by a BBC poll of global critics were written by women; these included works by [[George Eliot]], [[Virginia Woolf]], [[Charlotte Brontë]], [[Emily Brontë]], [[Mary Shelley]], [[Jane Austen]], [[Doris Lessing]] and [[Zadie Smith]].<ref>{{Cite news |last=Ciabattari |first=Jane |date=December 2015 |title=The 25 greatest British novels |work=BBC Culture |url=https://www.bbc.com/culture/article/20151204-the-25-greatest-british-novels |access-date=29 December 2021}}</ref>
Scottish literature includes [[Arthur Conan Doyle]] (the creator of [[Sherlock Holmes]]), [[Walter Scott|Sir Walter Scott]], [[J. M. Barrie]], [[Robert Louis Stevenson]] (whose novel ''[[Treasure Island]]'' strongly influenced the portrayal of [[pirates in the arts and popular culture]]), and the poet [[Robert Burns]], who is considered the national poet of Scotland. More recently [[Hugh MacDiarmid]] and [[Neil M. Gunn]] contributed to the [[Scottish Renaissance]], with grimmer works from [[Ian Rankin]] and [[Iain Banks]]. Edinburgh was UNESCO's first worldwide [[City of Literature]].<ref>{{Cite web |year=2004 |title=Edinburgh, United Kingdom, UNESCO City of Literature |url=http://www.unesco.org/new/en/culture/themes/creativity/creative-industries/creative-cities-network/literature/edinburgh |archive-url=https://web.archive.org/web/20130528152834/http://www.unesco.org/new/en/culture/themes/creativity/creative-industries/creative-cities-network/literature/edinburgh |archive-date=28 May 2013 |url-status=dead |access-date=9 March 2015 |work=Unesco}}</ref>
Welsh literature includes Britain's oldest known poem, ''[[Y Gododdin]]'', most likely composed in the late 6th century. It was written in [[Cumbric language|Cumbric]] or [[Old Welsh]] and contains the earliest known reference to [[King Arthur]].<ref>{{Cite web |title=Early Welsh poetry |url=https://www.bbc.co.uk/wales/history/sites/themes/society/language_poetry.shtml |access-date=29 December 2010 |work=BBC Wales}}</ref> The [[Arthurian legend]] was further developed by [[Geoffrey of Monmouth]].<ref>{{Cite book |last=Lang, Andrew |url=https://books.google.com/books?id=dKJiPyyTevgC |title=History of English Literature from Beowulf to Swinburne |publisher=Wildside Press |year=2003 |isbn=978-0-8095-3229-2 |location=Holicong, PA |page=42 |orig-date=1913}}</ref> [[Dafydd ap Gwilym]] (''fl.'' 1320–1370) is widely regarded as one of the greatest European poets of his age.<ref>{{Cite web |year=2011 |title=Dafydd ap Gwilym |url=http://www.academi.org/dafydd-ap-gwilym-eng |archive-url=https://web.archive.org/web/20120324034938/http://www.literaturewales.org/dafydd-ap-gwilym-eng |archive-date=24 March 2012 |url-status=dead |access-date=3 January 2011 |website=[[Literature Wales|Academi.org]] |quote=Dafydd ap Gwilym is widely regarded as one of the greatest Welsh poets of all time, and amongst the leading European poets of the Middle Ages.}}</ref> [[Daniel Owen]] is credited as the first Welsh-language novelist, publishing ''[[Rhys Lewis (novel)|Rhys Lewis]]'' in 1885. The best-known of the [[Anglo-Welsh poetry|Anglo-Welsh poets]] are [[Dylan Thomas]] and [[R. S. Thomas]], the latter nominated for the [[Nobel Prize in Literature]] in 1996. Leading Welsh novelists of the twentieth century include [[Richard Llewellyn]] and [[Kate Roberts (author)|Kate Roberts]].<ref>{{Cite web |url=http://newsalerts.bbc.co.uk/1/low/wales/551486.stm |title=True birthplace of Wales's literary hero |archive-url=https://web.archive.org/web/20200316173733/http://newscdn.bbc.net.uk/2/hi/uk_news/wales/551486.stm |archive-date=16 March 2020 |url-status=dead |website=BBC News |date=5 December 1999 |access-date=28 April 2012}}</ref><ref>{{Cite web |title=Kate Roberts: Biography |url=https://www.bbc.co.uk/wales/northwest/halloffame/arts/kateroberts.shtml |url-status=dead |access-date=19 February 2017 |website=BBC Wales |archive-url=https://web.archive.org/web/20130308000646/https://www.bbc.co.uk/wales/northwest/halloffame/arts/kateroberts.shtml |archive-date=8 March 2013}}</ref>
Northern Ireland's most popular writer is [[C. S. Lewis]], who was born in Belfast and wrote ''[[The Chronicles of Narnia]]''.<ref>{{Cite web |title=The Chronicles of Narnia Book Series Statistics |url=https://wordsrated.com/the-chronicles-of-narnia-book-series-statistics/ |access-date=18 May 2024 |publisher=Wordsrated |date=19 July 2023}}</ref> Irish writers, living at a time when all of Ireland was part of the United Kingdom, include [[Oscar Wilde]],<ref>{{Cite book |last=Varty |first=Anne |title=A Preface to Oscar Wilde |date=2014 |publisher=Routledge |isbn=978-1-317-89231-1 |pages=[https://books.google.com/books?id=A9YFBAAAQBAJ&pg=PA231 231–232]}}; {{Cite encyclopedia |title=Oscar Wilde |encyclopedia=[[Encyclopedia.com]] |publisher=[[Cengage]] |url=https://www.encyclopedia.com/people/literature-and-arts/english-literature-19th-cent-biographies/oscar-wilde |access-date=10 December 2019}}</ref> [[Bram Stoker]] (who wrote ''[[Dracula]]'')<ref>{{Cite book |last=Moss |first=Joyce |url=https://archive.org/details/isbn_9780787637286 |title=British and Irish Literature and Its Times: The Victorian Era to the Present (1837–) |publisher=Gale Group |year=2001 |isbn=978-0-7876-3729-3 |page=[https://archive.org/details/isbn_9780787637286/page/107 107] |url-access=registration}}</ref> and [[George Bernard Shaw]].<ref>{{Cite book |last=Holroyd |first=Michael |url=https://archive.org/details/bernardshaw00holr/page/384 |title=Bernard Shaw, Volume 2: 1898–1918: The Pursuit of Power |publisher=Chatto & Windus |year=1989 |isbn=978-0-7011-3350-4 |page=[https://archive.org/details/bernardshaw00holr/page/384 384]}}; {{Cite web |title=G B Shaw |url=https://www.bl.uk/people/g-b-shaw |access-date=10 December 2019 |website=Discovering Literature: 20th century |publisher=[[British Library]] |archive-date=9 August 2020 |archive-url=https://web.archive.org/web/20200809155152/https://www.bl.uk/people/g-b-shaw |url-status=dead}}</ref> There have been many authors whose origins were from outside the United Kingdom but who moved to the UK, including [[Joseph Conrad]],<ref>{{Cite book |last=Middleton |first=Tim |url=https://books.google.com/books?id=Azd1f8NBpUoC&pg=PA159 |title=Joseph Conrad |publisher=Routledge |year=2006 |isbn=978-0-415-26851-6 |page=159}}</ref> [[T. S. Eliot]],<ref>{{Cite book |last=Cooper |first=John Xiros |url=https://books.google.com/books?id=XqmNjQzhwV4C&pg=PA111 |title=The Cambridge Introduction to T. S. Eliot |date=2006 |publisher=Cambridge University Press |isbn=978-1-139-45790-3 |page=111}}</ref> [[Kazuo Ishiguro]],<ref>{{Cite book |last=Sim |first=Wai-chew |url=https://books.google.com/books?id=WcKLAgAAQBAJ&pg=PT201 |title=Kazuo Ishiguro |date=2009 |publisher=Routledge |isbn=978-1-135-19867-1 |page=201}}</ref> Sir [[Salman Rushdie]]<ref>{{Cite web |title=Salman Rushdie |url=https://www.oxfordreference.com/view/10.1093/oi/authority.20110803100433765 |access-date=10 December 2019 |website=Oxford Reference |publisher=[[Oxford University Press]]}}</ref> and [[Ezra Pound]].<ref>{{Cite news |last=Campbell |first=James |date=17 May 2008 |title=Home from home |work=The Guardian |url=https://www.theguardian.com/books/2008/may/17/poetry3 |access-date=10 December 2019}}; {{Cite book |last=Nadel |first=Ira |url=https://books.google.com/books?id=ECiGDAAAQBAJ&pg=PA90 |title=Ezra Pound: A Literary Life |date=2004 |publisher=Palgrave Macmillan |isbn=978-0-230-37881-0 |page=90}}</ref>
=== Philosophy ===
{{Main|British philosophy}}
The United Kingdom is famous for "[[British Empiricism]]", a branch of the philosophy that states that only knowledge verified by experience is valid, and 'Scottish Philosophy', sometimes referred to as the '[[Scottish School of Common Sense]]'.<ref>{{Cite book |url=http://www.rrbltd.co.uk/bibliographies/scottish_v5_bibliog.pdf |title=A bibliography of Scottish common sense philosophy: Sources and origins |publisher=Thoemmes Press |year=2000 |editor-last=Fieser, James |location=Bristol |access-date=17 December 2010 |archive-date=9 April 2023 |archive-url=https://web.archive.org/web/20230409171906/https://www.rrbltd.co.uk/bibliographies/scottish_v5_bibliog.pdf |url-status=dead}}</ref> The most famous philosophers of British Empiricism are [[John Locke]], [[George Berkeley]]{{Efn|Berkeley is in fact Irish but was called a 'British empiricist' due to the territory of what is now known as the [[Republic of Ireland]] being in the UK at the time.}} and [[David Hume]]; while [[Dugald Stewart]], [[Thomas Reid]] and [[Sir William Hamilton, 9th Baronet|William Hamilton]] were major exponents of the Scottish "common sense" school. Two Britons are also notable for the ethical theory of [[utilitarianism]], a moral philosophy first used by [[Jeremy Bentham]] and later by [[John Stuart Mill]] in his short work ''[[Utilitarianism (book)|Utilitarianism]]''.<ref>{{Cite book |last=Palmer, Michael |url=https://books.google.com/books?id=s7y5MJOuN30C&pg=PA66 |title=Moral Problems in Medicine: A Practical Coursebook |publisher=Lutterworth Press |year=1999 |isbn=978-0-7188-2978-0 |location=Cambridge |page=66}}; {{Cite book |last=Scarre, Geoffrey |url=https://books.google.com/books?id=8A4xLnzfqYwC&pg=PA82 |title=Utilitarianism |publisher=Routledge |year=1995 |isbn=978-0-415-12197-2 |location=London |page=82}}</ref>
=== Media ===
{{Main|Media of the United Kingdom|Censorship in the United Kingdom}}
{{Further|Media of England|Media of Scotland|Media of Wales|Media of Northern Ireland}}
The [[BBC]], founded in 1922, is the United Kingdom's publicly funded radio, television and Internet broadcasting corporation, and is the oldest and largest broadcaster in the world.<ref name="MediaNewsline">{{Cite web |title=BBC: World's largest broadcaster & Most trusted media brand |url=http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-url=https://web.archive.org/web/20101005004930/http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-date=5 October 2010 |access-date=23 September 2010 |publisher=Media Newsline}}</ref><ref name="ProspectMag">{{Cite web |title=Digital license |url=http://www.prospectmagazine.co.uk/?p=64654 |archive-url=https://web.archive.org/web/20111107024637/http://www.prospectmagazine.co.uk/2009/07/digitallicense |archive-date=7 November 2011 |access-date=9 March 2015 |publisher=Prospect}}</ref><ref name="AboutBBC">{{Cite news |title=About the BBC – What is the BBC |work=BBC Online |url=https://www.bbc.co.uk/info/purpose/what.shtml |access-date=9 March 2015 |archive-url=https://web.archive.org/web/20100116202334/http://www.bbc.co.uk/info/purpose/what.shtml |archive-date=16 January 2010}}</ref> It operates television and radio stations across the UK and abroad and its domestic services are funded by the [[Television licensing in the United Kingdom|television licence]].<ref>{{Cite journal |date=13 August 2009 |title=BBC: World's largest broadcaster & Most trusted media brand |url=http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |journal=Media Newsline |archive-url=https://web.archive.org/web/20110510090842/http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-date=10 May 2011 |access-date=19 June 2011}}; {{Cite web |date=April 2010 |title=TV Licence Fee: facts & figures |url=https://www.bbc.co.uk/pressoffice/keyfacts/stories/licencefee.shtml |url-status=live |archive-url=https://web.archive.org/web/20110427080539/http://www.bbc.co.uk/pressoffice/keyfacts/stories/licencefee.shtml |archive-date=27 April 2011 |publisher=BBC Press Office}}</ref> The [[BBC World Service]] is an [[International broadcasting|international broadcaster]] owned and operated by the BBC, and the world's largest.<ref>{{Cite web |title=Microsoft Word – The Work of the BBC World Service 2008–09 HC 334 FINAL.doc |url=https://publications.parliament.uk/pa/cm200910/cmselect/cmfaff/334/334.pdf |archive-url=https://web.archive.org/web/20201021001645/https://publications.parliament.uk/pa/cm200910/cmselect/cmfaff/334/334.pdf |archive-date=21 October 2020 |access-date=16 February 2011}}</ref> It broadcasts radio news, speech and discussions in more than 40 languages.<ref>{{Cite web |title=News in your language – BBC News |url=https://www.bbc.co.uk/ws/languages |website=BBC}}; {{Cite web |title=BBC World Service |url=https://www.facebook.com/pages/category/Media-News-Company/bbcworldservice/about |website=Facebook.com}}</ref>
Other major players in the UK media include [[ITV plc|ITV]], which operates 11 of the 15 regional television broadcasters that make up the [[ITV (TV network)|ITV Network]],<ref>{{Cite web |title=Publications & Policies: The History of ITV |url=http://www.itv.com/aboutitv/publications-policies |archive-url=https://web.archive.org/web/20110411224117/http://www.itv.com/aboutitv/publications-policies |archive-date=11 April 2011 |website=ITV.com}}</ref> and [[Sky UK|Sky]].<ref>{{Cite journal |title=Direct Broadcast Satellite Television |url=http://www.newscorp.com/operations/dbst.html |journal=News Corporation |archive-url=https://web.archive.org/web/20110604095622/http://www.newscorp.com/operations/dbst.html |archive-date=4 June 2011}}</ref> Newspapers produced in the United Kingdom include the ''[[Daily Mail]]'', ''[[The Guardian]]'', ''[[The Daily Telegraph|The Telegraph]]'', ''[[The Times]]'', and the ''[[Financial Times]]''.<ref>{{Cite news |date=10 October 2008 |title=ABCs: National daily newspaper circulation September 2008 |work=The Guardian |location=London |url=https://www.theguardian.com/media/table/2008/oct/10/abcs-pressandpublishing |access-date=17 October 2008}}</ref> Magazines and journals published in the United Kingdom that have achieved worldwide circulation include ''[[The Spectator]]'', ''[[The Economist]]'', ''[[New Statesman]]'' and ''[[Radio Times]]''.
[[File:Media City Footbridge and BBC Offices (geograph 2685261).jpg|thumb|[[MediaCityUK]] in [[Salford]], [[Greater Manchester]], is one of the largest media production facilities in Europe.]]London dominates the media sector in the UK: national newspapers and television and radio are largely based there, although [[MediaCityUK]] in Manchester is also a significant national media centre. Edinburgh and Glasgow, and Cardiff, are important centres of newspaper and broadcasting production in Scotland and Wales, respectively.<ref>William, D. (2010). [https://books.google.com/books?id=7yg45P35KDMC ''UK Cities: A Look at Life and Major Cities in England, Scotland, Wales and Northern Ireland'']. Eastbourne: Gardners Books. {{ISBN|978-9987-16-021-1}}, pp. 22, 46, 109 and 145.</ref> The UK publishing sector, including books, directories and databases, journals, magazines and business media, newspapers and news agencies, has a combined turnover of around £20 billion and employs 167,000 people.<ref>{{Cite web |title=Publishing |url=http://www.culture.gov.uk/what_we_do/creative_industries/3280.aspx |url-status=live |archive-url=https://web.archive.org/web/20110505104322/http://www.culture.gov.uk/what_we_do/creative_industries/3280.aspx |archive-date=5 May 2011 |publisher=Department of Culture, Media and Sport}}</ref> In 2015 the UK published 2,710 book titles per million inhabitants, more than any other country, with much of this exported to other [[Anglophone]] countries.<ref>{{Cite web |last=<!--Not stated--> |date=2016 |title=Annual Report 2015–2016 |url=https://www.internationalpublishers.org/images/reports/Annual_Report_2016/IPA_Annual_Report_2015-2016_interactive.pdf |access-date=14 January 2021 |website=internationalpublishers.org |publisher=International Publishers Association |page=16 |archive-date=31 August 2023 |archive-url=https://web.archive.org/web/20230831205753/https://www.internationalpublishers.org/images/reports/Annual_Report_2016/IPA_Annual_Report_2015-2016_interactive.pdf |url-status=dead}}</ref>
In 2010, 82.5 per cent of the UK population were Internet users, the [[List of countries by number of Internet users|highest proportion]] amongst the 20 countries with the largest total number of users in that year.<ref>{{Cite journal |title=Top 20 countries with the highest number of Internet users |url=http://www.internetworldstats.com/top20.htm |journal=Internet World Stats |archive-url=https://web.archive.org/web/20110610104435/http://www.internetworldstats.com/top20.htm |archive-date=10 June 2011 |access-date=19 June 2011}}</ref> The [[Video games in the United Kingdom|British video game industry]] is the largest in Europe, and since 2022 the UK has the [[List of video games markets by country|largest video game market]] in Europe by sales, surpassing [[Video games in Germany|Germany]].<ref>{{Cite web |last=Dring |first=Christopher |date=12 January 2023 |title=European console and PC game sales fall 7.1% in 2022 |url=https://www.gamesindustry.biz/european-console-and-pc-game-sales-fall-71-over-2021 |access-date=30 September 2023 |website=GamesIndustry.biz}}</ref> It is the world's third-largest producer of video games after [[Video games in Japan|Japan]] and the [[Video games in the United States|United States]].<ref>{{Cite web |title=About UK Video Games Industry |url=https://tiga.org/about-tiga-and-our-industry/about-uk-video-games-industry |access-date=6 June 2023 |website=TIGA}}</ref>
=== Visual art ===
{{Main|Art of the United Kingdom|Architecture of the United Kingdom}}
[[File:Angel of the North - 6150534524.jpg|thumb|The [[Angel of the North]] sculpture by [[Antony Gormley]] has become a symbol of [[Northern England]].]]
Major British artists include the [[Romanticism|Romantic]] artists [[William Blake]], [[John Constable]], [[Samuel Palmer]], and [[J. M. W. Turner]]; the [[portrait]] painters [[Joshua Reynolds|Sir Joshua Reynolds]] and [[Lucian Freud]]; the landscape artists [[Thomas Gainsborough]] and [[L. S. Lowry]]; the pioneer of the [[Arts and Crafts movement]] [[William Morris]]; the figurative painter [[Francis Bacon (artist)|Francis Bacon]]; the [[Pop artist]]s [[Peter Blake (artist)|Peter Blake]], [[Richard Hamilton (artist)|Richard Hamilton]] and [[David Hockney]]; the pioneers of [[conceptual art]] movement [[Art & Language]];<ref>{{Cite news |last=Tate |title=Art & Language – Art Term {{!}} Tate |work=Tate |url=https://www.tate.org.uk/art/art-terms/a/art-language |access-date=8 September 2018}}</ref> the collaborative duo [[Gilbert and George]]; the [[Abstract art|abstract]] artist [[Howard Hodgkin]]; and the sculptors [[Antony Gormley]], [[Anish Kapoor]] and [[Henry Moore]]. During the late 1980s and 1990s the [[Saatchi Gallery]] in London helped to bring to public attention a group of multi-genre artists who would become known as the "[[Young British Artists]]": [[Damien Hirst]], [[Chris Ofili]], [[Rachel Whiteread]], [[Tracey Emin]], [[Mark Wallinger]], [[Steve McQueen (director)|Steve McQueen]], [[Sam Taylor-Wood]] and the [[Jake and Dinos Chapman|Chapman Brothers]] are amongst the better-known members of this loosely affiliated movement.
The [[Royal Academy]] in London is a key organisation for the promotion of the visual arts in the United Kingdom. Major schools of art in the UK include: the six-school [[University of the Arts London]], which includes the [[Central Saint Martins College of Art and Design]] and [[Chelsea College of Art and Design]]; [[Goldsmiths, University of London]]; the [[Slade School of Fine Art]] (part of [[University College London]]); the [[Glasgow School of Art]]; the [[Royal College of Art]]; and [[The Ruskin School of Drawing and Fine Art]] (part of the University of Oxford). The [[Courtauld Institute of Art]] is a leading centre for the teaching of the [[history of art]]. Important art galleries in the United Kingdom include the [[National Gallery]], [[National Portrait Gallery (London)|National Portrait Gallery]], [[Tate Britain]], and [[Tate Modern]] (the most-visited modern art gallery in the world, with around 4.7 million visitors per year).<ref>{{Cite news |last=Bayley |first=Stephen |date=24 April 2010 |title=The startling success of Tate Modern |work=[[The Times]] |location=London |url=http://entertainment.timesonline.co.uk/tol/arts_and_entertainment/visual_arts/article7105032.ece |archive-url=https://web.archive.org/web/20110429173928/http://entertainment.timesonline.co.uk/tol/arts_and_entertainment/visual_arts/article7105032.ece |url-status=dead |archive-date=29 April 2011 |access-date=19 January 2011}} {{Subscription required}}</ref>
=== Music ===
{{Main|Music of the United Kingdom}}
{{Further|Music of England (disambiguation){{!}}Music of England|Music of Scotland|Music of Wales|Music of Northern Ireland}}
<!----Caution should be taken to ensure that the sections are not simply a listing of names or mini biographies of individuals accomplishments.---->
[[File:Royal Albert Hall, BBC Proms 2017.jpg|thumb|[[The Proms]] is a classical music festival, most closely associated with [[Henry Wood]] and held at the [[Royal Albert Hall]] in London, which regularly plays music by [[Edward Elgar]] and other British composers.]]
Various styles of music have become popular in the UK, including the [[folk music]] of [[Folk music of England|England]], [[Folk music of Scotland|Scotland]], [[Music of Wales#Folk music|Wales]] and [[Folk music of Northern Ireland|Northern Ireland]]. English folk features melodic ballads with strong lyrics and music for country dancing often using accordion and fiddles.<ref>{{Cite web |access-date=15 September 2025 |title=Songs of England |url=https://www.english-heritage.org.uk/visit/inspire-me/songs-of-england}}</ref> Scottish folk features bagpipes and fiddles playing traditional dance tunes with bouncy tempos.<ref>{{Cite web |access-date=15 September 2025 |title=The influence of traditional Scottish Music |url=https://www.visitscotland.com/things-to-do/events/music-festivals/traditional-folk}}</ref> Welsh folk has harps and vocal harmonies often sung in Welsh.<ref>{{Cite web |access-date=15 September 2025 |title=Celtic connections: the story of folk music in Wales |date=17 February 2020 |url=https://www.wales.com/culture-and-sport/music-and-performance/roots-and-shoots-welsh-folk-music}}</ref> Northern Irish folk blends fiddles with flutes merging Scottish and Irish influences.<ref>{{Cite web |access-date=15 September 2025 |title=Why you should experience traditional music in Ireland |url=https://www.ireland.com/en-us/magazine/music/traditional-music/}}</ref>
Historically, there has been [[Renaissance music]] from the [[Tudor period]], with [[Mass (music)|masses]], [[madrigal]]s and [[lute]] music by [[Thomas Tallis]], [[John Taverner]], [[William Byrd]], [[Orlando Gibbons]] and [[John Dowland]]. After the [[Stuart Restoration]], an English tradition of dramatic [[masque]]s, anthems and airs became established, led by [[Henry Purcell]], followed by [[Thomas Arne]] and others. [[George Frideric Handel]] composed the anthem ''[[Zadok the Priest]]'' for the [[coronation of George II]]; it became the traditional ceremonial music for anointing all future monarchs. Handel's many oratorios, such as his famous ''[[Messiah (Handel)|Messiah]]'', were written in English.<ref>{{Cite web |date=20 July 2009 |title=British Citizen by Act of Parliament: George Frideric Handel |url=http://www.parliament.uk/parliamentary_publications_and_archives/parliamentary_archives/handel_and_naturalisation.cfm |archive-url=https://web.archive.org/web/20100326164147/http://www.parliament.uk/parliamentary_publications_and_archives/parliamentary_archives/handel_and_naturalisation.cfm |archive-date=26 March 2010 |access-date=9 March 2015 |publisher=UK Parliament}}; {{Cite news |last=Andrews |first=John |date=14 April 2006 |title=Handel all'inglese |work=Playbill |location=New York |url=http://www.playbillarts.com/features/article/4236.html |access-date=11 September 2009 |archive-url=https://web.archive.org/web/20080516210558/http://www.playbillarts.com/features/article/4236.html |archive-date=16 May 2008}}</ref>
In the second half of the 19th century, [[Arthur Sullivan]] and his librettist [[W. S. Gilbert]] wrote their popular [[Savoy opera]]s, and [[Edward Elgar]] composed a wide range of music. Increasingly, composers became inspired by the English countryside and its [[folk music]], notably [[Gustav Holst]], [[Ralph Vaughan Williams]] and [[Benjamin Britten]], a pioneer of modern British opera. Amongst the many post-war composers, some of the most notable have made their own personal choice of musical identity: [[Peter Maxwell Davies]] (Orkney), [[Harrison Birtwistle]] (mythological), and [[John Tavener]] (religious).<ref>{{Cite Grove |title=Great Britain |first1=Nicholas |last1=Iemperley |date=2002 |url=https://doi.org/10.1093/gmo/9781561592630.article.O006236 |url-access=subscription}}; {{Cite Grove |title=England (i) |date=2001 |url=https://doi.org/10.1093/gmo/9781561592630.article.40044 |url-access=subscription |first1=Stephen |last1=Banfield |first2=Ian |last2=Russell}}; {{Cite Grove |title=Wales |date=2001 |first1=Geraint |last1=Lewis |first2=Lyn |last2=Davies |first3=Phyllis |last3=Kinney |url=https://doi.org/10.1093/gmo/9781561592630.article.41108 |url-access=subscription}}; {{Cite Grove |title=Scotland |first1=Kenneth |last1=Elliott |first2=Francis |last2=Collinson |first3=Peggy |last3=Duesenberry |url=https://doi.org/10.1093/gmo/9781561592630.article.40113 |url-access=subscription |date=2001}}; {{Cite Grove |title=Ireland |first1=Harry |last1=White |first2=Nicholas |last2=Carolan |url=https://doi.org/10.1093/gmo/9781561592630.article.13901 |url-access=subscription |date=2011}}; {{Cite web |title=British 20th century composers |url=https://www.bbc.co.uk/bitesize/guides/zdjw7p3/revision/1 |access-date=21 April 2022 |website=[[BBC]]}}</ref> Recent classical singers include [[Alfie Boe]], [[Bryn Terfel]], [[Katherine Jenkins]], [[Michael Ball]], [[Roderick Williams]], [[Russell Watson]] and [[Sarah Brightman]], while [[Nicola Benedetti]] and [[Nigel Kennedy]] are renowned for their violin ability.<ref>{{Cite web |date=21 June 2022 |title=30 of the greatest violinists on record |url=https://www.gramophone.co.uk/features/article/30-of-the-greatest-violinists-on-record |access-date=4 March 2024 |website=Gramophone}};{{Cite web |date=1 January 2020 |title=Katherine Jenkins has officially sold the most classical albums this century |url=https://www.classicfm.com/radio/shows-presenters/classic-fm-chart/katherine-jenkins-most-classical-albums/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=6 May 2023 |title=Who is Roderick Williams, the British baritone and composer at the King's coronation? |url=https://www.classicfm.com/discover-music/roderick-williams-composer-baritone-singing-roles/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=23 February 2024 |title=Michael Ball |url=https://www.eno.org/artists/michael-ball-2/ |access-date=4 March 2024 |website=English National Opera}};{{Cite web |title=Alfie Bow |url=https://www.classicfm.com/artists/alfie-boe/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=11 July 2023 |title=Sarah Brightman facts |url=https://www.smoothradio.com/news/music/sarah-brightman-age-husband-songs/ |access-date=4 March 2024 |website=Smooth Radio}}</ref>
According to ''[[The New Grove Dictionary of Music and Musicians]]'' the term "[[pop music]]" originated in Britain in the mid-1950s to describe [[rock and roll]]'s fusion with the "new youth music".<ref>R. Middleton, et al., [http://www.oxfordmusiconline.com/public/book/omo_gmo "Pop"], ''Grove music online'', retrieved 14 March 2010. {{Subscription required}} {{Webarchive|url=https://web.archive.org/web/20110113160329/http://www.oxfordmusiconline.com/public/book/omo_gmo|date=13 January 2011}}</ref> ''The Oxford Dictionary of Music'' states that artists such as [[the Beatles]] and [[the Rolling Stones]] drove pop music to the forefront of popular music in the early 1960s.<ref>"Pop", [http://www.oxfordmusiconline.com/public/book/omo_t237 ''The Oxford Dictionary of Music''], retrieved 9 March 2010.{{Subscription required}} {{Webarchive|url=https://web.archive.org/web/20171112170116/http://www.oxfordmusiconline.com/public/book/omo_t237|date=12 November 2017}}</ref> Birmingham became known as the birthplace of [[heavy metal music|heavy metal]], with the band [[Black Sabbath]] starting there in the 1960s.<ref>{{Cite news |title=Birmingham, England ... the unlikely birthplace of heavy metal |work=CNN |date=1 July 2011 |first1=Laura |last1=Allsop |url=http://www.cnn.com/2011/WORLD/europe/07/01/birmingham.home.of.metal/index.html |access-date=28 February 2022 |postscript=;}} {{Cite web |last=Bentley |first=David |date=4 June 2013 |title=Midlands rocks! How Birmingham's industrial heritage made it the birthplace of heavy metal |url=http://www.birminghampost.co.uk/whats-on/music/birmingham-birthplace-of-heavy-metal-4031445 |access-date=28 February 2022 |website=[[Birmingham Post]]}}</ref> In the following years, Britain took part in the development of [[rock music]], with British acts pioneering [[hard rock]],<ref>{{Cite web |title=The Rolling Stones {{!}} Biography & History |url=https://www.allmusic.com/artist/the-rolling-stones-mn0000894465/biography |access-date=22 July 2020 |website=AllMusic}}</ref> [[raga rock]], heavy metal,<ref>{{Cite book |last=Tom Larson |url=https://books.google.com/books?id=vGJ7XmA8rjIC&pg=PA183 |title=History of Rock and Roll |publisher=Kendall/Hunt Pub. |year=2004 |isbn=978-0-7872-9969-9 |pages=183–187}}</ref> [[space rock]], [[glam rock]],<ref>{{Cite encyclopedia |title=Glam Rock |url=http://encarta.msn.com/dictionary_561509274/glam_rock.html |access-date=21 December 2008 |archive-url=https://web.archive.org/web/20090828224412/http://encarta.msn.com/dictionary_561509274/glam_rock.html |archive-date=28 August 2009 |encyclopedia=[[Encarta]]}}</ref> [[Gothic rock]],<ref>{{Cite web |year=2004 |title=NME Originals: Goth |url=https://www.nme.com/originals/4 |archive-url=https://web.archive.org/web/20080126150121/http://www.nme.com/originals/4 |archive-date=26 January 2008 |access-date=30 September 2013 |website=[[NME]]}}</ref> [[psychedelic rock]]<ref>{{Cite web |title=Pop/Rock » Psychedelic/Garage |url=https://www.allmusic.com/subgenre/psychedelic-garage-ma0000002800 |access-date=6 August 2020 |publisher=[[AllMusic]]}}</ref> and [[punk rock]].<ref>{{cite magazine |author1=Charles M. Young |title=Rock is Sick and Living in London |url=https://www.rollingstone.com/feature/a-report-on-the-sex-pistols-119989/ |magazine=Rolling Stone |access-date=23 February 2026 |date=20 October 1977 |archive-url=https://web.archive.org/web/20250328094721/https://www.rollingstone.com/feature/a-report-on-the-sex-pistols-119989/ |archive-date=28 March 2025}}</ref> British acts also developed [[neo soul]] and created [[dubstep]].<ref>Henderson, Alex (1 August 2003). [https://web.archive.org/web/20101104165122/http://allmusic.com/explore/essay/british-soul-t2160 British Soul]. Allmusic. Retrieved 6 March 2011.; [http://www.allmusic.com/style/dubstep-ma0000004465 AllMusic – Dubstep] {{Webarchive|url=https://web.archive.org/web/20170923151236/http://www.allmusic.com/style/dubstep-ma0000004465|date=23 September 2017}} "Absorbed and transfigured elements of techno, drum'n' bass and dub"; {{Cite news |last=Goldman |first=Vivien |date=31 January 2012 |title=Local Groove Does Good: The Story Of Trip-Hop's Rise From Bristol |work=NPR |url=https://www.npr.org/sections/therecord/2012/01/31/142607358/local-groove-does-good-the-story-of-trip-hops-rise-from-bristol}}</ref> The UK has produced some of the most prominent English-speaking [[rappers]] along with the United States, including [[Stormzy]], [[Kano (rapper)|Kano]], [[Yxng Bane]], [[Ramz (rapper)|Ramz]], [[Little Simz]] and [[Skepta]].<ref>{{Cite magazine |title=5 U.K. Rappers Primed to Take Over America in 2018 |url=https://www.billboard.com/music/rb-hip-hop/uk-rappers-to-watch-2018-8097878/ |magazine=Billboard |access-date=18 June 2018}}</ref>
[[File:The SSE Hydro arena - geograph.org.uk - 6725739.jpg|thumb|right|The [[OVO Hydro]] in [[Glasgow]], Scotland, a 14,500-capacity arena consistently ranked within the top ten busiest venues worldwide<ref>{{cite web |title=OVO Hydro {{!}} SEC |url=https://www.sec.co.uk/organise-an-event/event-spaces/the-ovo-hydro |website=www.sec.co.uk |access-date=9 February 2026 |language=en}}</ref>]]
The Beatles have international sales of over 1 billion units and are the [[List of best-selling music artists|biggest-selling band]], in addition to being [[Cultural impact of the Beatles|widely regarded as the most influential band]] in the history of popular music.<ref name="Beatles sales">{{Cite web |title=1960–1969 |url=http://www.emimusic.com/about/history/1960-1969/# |archive-url=https://web.archive.org/web/20140425011032/http://www.emimusic.com/about/history/1960-1969 |archive-date=25 April 2014 |access-date=9 March 2015 |publisher=EMI Group}}</ref><ref name="McCartney">{{Cite magazine |date=8 June 1992 |title=Paul At Fifty |url=http://www.time.com/time/magazine/article/0,9171,975715-2,00.html |magazine=Time |location=New York |archive-url=https://web.archive.org/web/20090206120350/http://www.time.com/time/magazine/article/0,9171,975715-2,00.html |archive-date=6 February 2009}}</ref><ref name="Guinness">[https://books.google.com/books?id=rdU1xtIWJz0C Most Successful Group] ''[[The Guinness Book of Records]]'' 1999, p. 230. Retrieved 19 March 2011.</ref><ref>{{Cite news |date=25 November 2010 |title=Beatles a big hit with downloads |work=Belfast Telegraph |url=http://www.belfasttelegraph.co.uk/entertainment/music/news/beatles-a-big-hit-with-downloads-15013117.html |access-date=16 May 2011}}</ref> Other prominent British contributors to popular music over the last 50 years include the Rolling Stones, [[Pink Floyd]], [[Queen (band)|Queen]], [[Led Zeppelin]], the [[Bee Gees]] and [[Elton John]], all of whom have worldwide record sales of 200 million or more.<ref>{{Cite press release |title=British rock legends get their own music title for PlayStation3 and PlayStation2 |date=2 February 2009 |publisher=[[EMI]] |url=http://www.emimusic.com/news/2009/singstar®-queen-to-be-launched-by-sony-computer-entertainment-europe |access-date=9 March 2015 |archive-url=https://web.archive.org/web/20140423012539/http://www.emimusic.com/news/2009/singstar%C2%AE-queen-to-be-launched-by-sony-computer-entertainment-europe |archive-date=23 April 2014}}; {{Cite news |last=Khan |first=Urmee |date=17 July 2008 |title=Sir Elton John honoured in Ben and Jerry ice cream |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/newstopics/celebritynews/2305273/Sir-Elton-John-honoured-in-Ben-and-Jerry-ice-cream.html |archive-url=https://web.archive.org/web/20080730164432/http://www.telegraph.co.uk/news/newstopics/celebritynews/2305273/Sir-Elton-John-honoured-in-Ben-and-Jerry-ice-cream.html |archive-date=30 July 2008}}; {{Cite news |last=Alleyne |first=Richard |date=19 April 2008 |title=Rock group Led Zeppelin to reunite |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/uknews/1562875/Rock-group-Led-Zeppelin-to-reunite.html |url-status=live |url-access=subscription |access-date=31 March 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/news/uknews/1562875/Rock-group-Led-Zeppelin-to-reunite.html |archive-date=10 January 2022}}{{Cbignore}}; {{Cite news |date=11 July 2006 |title=Floyd 'true to Barrett's legacy' |work=BBC News |url=http://news.bbc.co.uk/1/hi/entertainment/5170644.stm}}; {{Cite news |last=Holton |first=Kate |date=17 January 2008 |title=Rolling Stones sign Universal album deal |work=Reuters |url=https://www.reuters.com/article/entertainmentNews/idUSL1767761020080117 |access-date=26 October 2008}}; {{Cite news |last=Walker |first=Tim |date=12 May 2008 |title=Jive talkin': Why Robin Gibb wants more respect for the Bee Gees |work=Independent |location=London |url=https://www.independent.co.uk/arts-entertainment/music/features/jive-talkin-why-robin-gibb-wants-more-respect-for-the-bee-gees-826116.html |access-date=26 October 2008 |archive-url=https://web.archive.org/web/20111013215157/http://www.independent.co.uk/arts-entertainment/music/features/jive-talkin-why-robin-gibb-wants-more-respect-for-the-bee-gees-826116.html |archive-date=13 October 2011}}</ref> The [[Brit Awards]] are the [[British Phonographic Industry|BPI]]'s annual music awards, and some of the British recipients of the [[Brit Award for Outstanding Contribution to Music|Outstanding Contribution to Music]] award include [[the Who]], [[David Bowie]], [[Eric Clapton]], [[Rod Stewart]], [[the Police]] and [[Fleetwood Mac]] (who are a British-American band).<ref>[https://www.theguardian.com/news/datablog/2012/feb/22/brit-awards-winners-list-2012 "Brit awards winners list 2012: every winner since 1977"]. ''The Guardian'' (London). Retrieved 28 February 2012.</ref> <!-- Please note that the following list of recent musicians and groups includes only those selling more than 30 million records. -->More recent UK music acts that have had international success include [[George Michael]], [[Oasis (band)|Oasis]], [[Spice Girls]], [[Radiohead]], [[Coldplay]], [[Arctic Monkeys]], [[Robbie Williams]], [[Amy Winehouse]], [[Susan Boyle]], [[Adele]], [[Ed Sheeran]], [[Lewis Capaldi]], [[One Direction]], [[Harry Styles]] and [[Dua Lipa]].<ref>{{Cite web |date=12 January 2020 |title=Harry Styles Has Weathered the Post-Boy Band Storm Better Than Most |url=https://consequence.net/2020/01/harry-styles-solo-career/ |access-date=15 September 2020 |website=Consequence of Sound}}; {{Cite magazine |date=16 July 2020 |title=10 Years of One Direction: The Story of the World's Biggest Boy Band, Told With the Fans Who Made It Happen |magazine=Billboard |url=https://www.billboard.com/music/pop/one-direction-ten-year-anniversary-fan-interviews-9419436/ |access-date=15 September 2020}}; {{Cite news |last=Corner, Lewis |date=16 February 2012 |title=Adele, Coldplay biggest-selling UK artists worldwide in 2011 |work=Digital Spy |url=http://www.digitalspy.co.uk/music/news/a366130/adele-coldplay-biggest-selling-uk-artists-worldwide-in-2011.html |access-date=22 March 2012}}; {{Cite web |title=Ed Sheeran's career journey: From street busker to global superstar |url=https://planetradio.co.uk/hits-radio/entertainment/celebrity/ed-sheeran-career-timeline/ |access-date=7 January 2023 |website=PlanetRadio.co.uk |last=Magliola |first=Anna Sky |date=30 November 2022}}; {{Cite web |url=https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we |title=Dua Lipa, 77.5M Monthly listeners |date=6 May 2024 |publisher=Spotify}}</ref> As of 2024 the UK is the world's [[List of largest music markets|third-largest music market]] behind the US and Japan,<ref>{{Cite web |last=Paine |first=Andre |date=10 September 2024 |title=IFPI report reveals EU risks falling behind in global market - UK still among top music exporters |url=https://www.musicweek.com/labels/read/ifpi-report-reveals-eu-risks-falling-behind-in-global-market-uk-still-among-top-music-exporters/090424 |access-date=17 November 2025 |website=[[Music Week]] |language=en}}</ref> and in 2021 was the second-largest exporter of music behind the US.<ref>{{Cite news |last=Savage |first=Mark |date=16 June 2021 |title=British music exports reach a record high |url=https://www.bbc.com/news/entertainment-arts-57486272 |access-date=17 November 2025 |work=[[BBC]] |language=en-GB}}</ref>
Many British cities are known for their music. Acts from Liverpool have had 54 UK chart number 1 hit singles, more per capita than any other city worldwide.<ref>{{Cite news |last=Hughes |first=Mark |date=14 January 2008 |title=A tale of two cities of culture: Liverpool vs Stavanger |work=Independent |location=London |url=https://www.independent.co.uk/news/uk/this-britain/a-tale-of-two-cities-of-culture-liverpool-vs-stavanger-770076.html?r=RSS |access-date=2 August 2009 |archive-url=https://web.archive.org/web/20180618175425/https://www.independent.co.uk/news/uk/this-britain/a-tale-of-two-cities-of-culture-liverpool-vs-stavanger-770076.html?r=RSS |archive-date=18 June 2018}}</ref> Glasgow's contribution was recognised in 2008 when it was named a [[City of Music (UNESCO)|City of Music]] by [[UNESCO]].<ref>{{Cite news |date=20 August 2008 |title=Glasgow gets city of music honour |work=BBC News |url=http://news.bbc.co.uk/1/hi/scotland/glasgow_and_west/7570915.stm |access-date=2 August 2009}}</ref> Manchester played a role in the spread of dance music such as [[acid house]], and from the mid-1990s, [[Britpop]]. London and Bristol are closely associated with the origins of [[electronic music]] sub-genres such as [[drum and bass]] and [[trip hop]].<ref>{{Cite web |title=Out of the melting pot: The origins and evolution of drum'n'bass |url=https://www.redbull.com/gb-en/history-of-drum-and-bass-music |access-date=1 August 2021 |website=Red Bull |date=25 June 2020}}</ref>
UK dance music traces its roots back to the black British [[Sound system (Jamaican)|Sound System Culture]] and the [[New Age travellers|New Age Traveller]] movement of the 60s and 70s,<ref>{{Cite web |date=3 August 2023 |title=Parties, protest and police: the neglected histories of UK dance music |url=https://www.dazeddigital.com/music/article/60511/1/ed-gillet-new-book-party-lines-politics-history-uk-dance-music-clubbing |access-date=27 February 2024 |website=Dazed}}</ref> it also has influences from the [[House music|Chicago House]] and [[Detroit techno|Detroit Techno]] scenes. In the late 80's, dance music exploded with [[Rave]] culture mainly [[Acid House]] tracks which were made mainstream with novelty records (such as Smart E's [[Sesame's Treet]] and the Prodigy's [[Charly (song)|Charly]])<ref>{{Cite web |date=20 January 2001 |title=Rave |url=https://www.oxfordmusiconline.com/search?q=rave |access-date=27 February 2024 |website=Oxford Music Online}}</ref> and the [[Balearic beat|Balearic sound]] brought back from the Ibiza club scene. This led on to genres such as [[UK Garage]], [[Speed Garage]], [[Drum and bass]], [[Jungle music|Jungle]], [[Trance music|Trance]], and [[Dubstep]]. Influential UK dance acts past and present include [[808 State]], [[Orbital (band)|Orbital]], [[the Prodigy]], [[Underworld (band)|Underworld]], [[Roni Size]], [[Leftfield]], [[Massive Attack]], [[Groove Armada]], [[Fatboy Slim]], [[Faithless]], [[Basement Jaxx]], [[Chemical Brothers]], [[Disclosure (band)|Disclosure]], [[Calvin Harris]], and [[Fred Again]].<ref>{{Cite web |title=Mixmag's Greatest Dance Act of all Time Revealed |date=19 January 2012 |url=http://www.mixmag.net/words/news/mixmags-greatest-dance-act-revealed |archive-date=14 April 2012 |archive-url=https://web.archive.org/web/20120414045620/http://www.mixmag.net/words/news/mixmags-greatest-dance-act-revealed}};{{Cite web |date=26 February 2024 |title=Fred Again: who is the DJ who has thousands queuing for a 'secret rave' at the Sydney Opera House? |url=https://www.theguardian.com/music/2024/feb/27/fred-again-dj-sydney-opera-house-secret-show-tickets-sell-out-profile-bio-details |access-date=27 February 2024 |website=The Guardian}}</ref> Other influential UK DJs include [[Judge Jules]], [[Pete Tong]], [[Carl Cox]], [[Paul Oakenfold]], [[John Digweed]] and [[Sasha (dj)|Sasha]].<ref>{{Cite web |title=Top 100 DJs Poll results 2003 |url=http://djmag.com/top100chart.asp |archive-date=7 December 2003 |archive-url=https://web.archive.org/web/20031207071739/http://djmag.com/top100chart.asp}}</ref>
=== Cinema ===
{{Main|Cinema of the United Kingdom|Independent cinema in the United Kingdom}}
The United Kingdom has had a considerable influence on the history of the cinema. The British directors [[Alfred Hitchcock]], whose film ''[[Vertigo (film)|Vertigo]]'' is considered by some critics as the [[List of films considered the best|best film of all time]],<ref>{{Cite news |date=2 August 2012 |title=Vertigo is named 'greatest film of all time' |work=BBC News |url=https://www.bbc.co.uk/news/entertainment-arts-19078948 |access-date=18 August 2012}}</ref> and [[David Lean]], who directed ''[[Lawrence of Arabia (film)|Lawrence of Arabia]]'', are amongst the most critically acclaimed directors ever.<ref>{{Cite web |title=The Directors' Top Ten Directors |url=http://www.bfi.org.uk/sightandsound/topten/poll/directors-directors.html |url-status=dead |archive-url=https://web.archive.org/web/20120517155218/http://www.bfi.org.uk/sightandsound/topten/poll/directors-directors.html |archive-date=17 May 2012 |publisher=British Film Institute}}</ref> Recent popular directors include [[Christopher Nolan]], [[Sam Mendes]], [[Steve McQueen (director)|Steve McQueen]], [[Richard Curtis]], [[Danny Boyle]], [[Tony Scott]] and [[Ridley Scott]].<ref>{{Cite web |title=The 24 Best British Directors of All Time |date=13 May 2023 |url=https://movieweb.com/best-british-directors-of-all-time/ |access-date=17 February 2024 |publisher=Movieweb}}</ref><ref>{{Cite web |title=Top 22 U.K. Film Directors |url=https://www.imdb.com/list/ls062383258/ |access-date=17 February 2024 |publisher=IMDb}}</ref><ref>{{Cite web |title=5 of the best ... Richard Curtis films |url=https://www.thetimes.com/culture/tv-radio/article/5-of-the-best-richard-curtis-films-tzxx9fv2h |work=The Times |access-date=4 June 2024 |date=17 April 2024}}</ref><ref>{{Cite web |title=The UK's top 50 film directors |date=23 May 2012 |url=https://www.televisual.com/news/the-uk-s-top-50-film-directors_bid-357/ |access-date=17 February 2024 |publisher=Televisual}}</ref> Many British actors have achieved international fame and critical success. Some of the most commercially successful films have been produced in the United Kingdom, including two of the [[List of highest-grossing film series|highest-grossing film franchises]] (''[[Harry Potter (film series)|Harry Potter]]'' and ''[[James Bond (film series)|James Bond]]'').<ref>{{Cite news |date=11 September 2007 |title=Harry Potter becomes highest-grossing film franchise |work=The Guardian |location=London |url=https://www.theguardian.com/film/2007/sep/11/jkjoannekathleenrowling |access-date=2 November 2010}}</ref>
2019 was a particularly good year for British films which grossed around £10.3 billion globally, accounting for 28.7 per cent of global box office revenue.<ref>{{Cite web |title=UK Film Industry Statistics 2023 |date=10 April 2023 |url=https://www.socialfilms.co.uk/blog/uk-film-industry-statistics |archive-url=https://web.archive.org/web/20240217211749/https://www.socialfilms.co.uk/blog/uk-film-industry-statistics |archive-date=17 February 2024 |access-date=17 February 2024}}</ref> UK box-office takings totalled £1.25 billion in 2019, with around 176 million admissions.<ref>{{Cite web |title=The UK box office in 2019 |url=https://www2.bfi.org.uk/sites/bfi.org.uk/files/downloads/bfi-uk-box-office-2019.pdf |archive-url=https://web.archive.org/web/20240217214846/https://www2.bfi.org.uk/sites/bfi.org.uk/files/downloads/bfi-uk-box-office-2019.pdf |archive-date=17 February 2024 |access-date=17 February 2024}}</ref> In 2023 UK film and television studio stage space stood at 6.9 million sq ft, with 1 million sq ft added in the past year with more in development.<ref>{{Cite web |title=UK Film and Television Studios Market Report |url=https://content.knightfrank.com/research/2439/documents/en/uk-film-and-television-studios-market-2023-10567.pdf |access-date=17 February 2024 |publisher=Knight Frank}}</ref> The annual [[British Academy Film Awards|BAFTA Film Awards]] are hosted by the [[British Academy of Film and Television Arts]].<ref>{{Cite news |date=26 February 2001 |title=Baftas fuel Oscars race |work=BBC News |url=http://news.bbc.co.uk/1/hi/entertainment/1190562.stm |access-date=14 February 2011}}</ref>
=== Cuisine ===
{{Main|British cuisine}}
{{Further|English cuisine|Scottish cuisine|Welsh cuisine|Northern Irish cuisine}}
[[File:Fish, chips and mushy peas.jpg|thumb|[[Fish and chips]], a traditional British dish, served with lemon, tartar sauce and mushy peas]]
British cuisine developed from influences reflective of its land, settlements, [[Immigration to the United Kingdom|arrivals of new settlers and immigrants]], trade and colonialism. The food of England has historically been characterised by simplicity of approach and a reliance on the high quality of natural produce.<ref>{{Cite book |last=Else |first=David |title=Inghilterra |publisher=EDT srl |date=2007 |isbn=978-88-6040-136-6 |page=76}}</ref> The traditional [[Sunday roast]] is one example, featuring a [[roasting|roast joint]] (usually of beef), lamb, chicken, or pork, often [[free range]] (and generally grass-fed, in the case of beef). Roasts are served with either roasted or boiled vegetables, [[Yorkshire pudding]] and [[gravy]]. Other traditional meals include [[meat pie]]s and [[stew]]s. A poll by [[YouGov]] in 2019 rated classic British food, with more than 80 per cent liking the Sunday roast, Yorkshire pudding, [[fish and chips]], [[crumpet]]s and the [[full English breakfast]].<ref>{{Cite web |url=https://yougov.co.uk/topics/consumer/articles-reports/2019/06/12/classic-british-cuisine-ranked-britons |date=11 June 2019 |title=Classic British cuisine ranked by Britons }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref>
The UK is home to a large selection of [[fine dining]]. The nation hosts multiple restaurant guides such as ''[[The Good Food Guide]]'' and ''[[Harden's]]''. In 2025 there were 197 restaurants with a [[Michelin Star]]; [[List of Michelin 3-star restaurants in the United Kingdom|ten of which have received a three-star rating]].<ref>{{cite web |url=https://guide.michelin.com/en/gb/restaurants/all-starred |title=United Kingdom |publisher=Michelin Guide |access-date=12 May 2025}}</ref> Sweet foods are common within British cuisine, and there is a long list of [[List of British desserts|British desserts]]. Afternoon tea is a light afternoon meal served with tea in tea rooms and hotels around the United Kingdom, with the tradition dating back to around 1840.<ref>{{Cite web |title=The tea-rific history of Victorian afternoon tea |work=The British Museum |url=https://www.britishmuseum.org/blog/tea-rific-history-victorian-afternoon-tea |access-date=11 April 2023}}</ref> A poll from July 2024 revealed that 3 per cent of the UK population follow a [[vegan]] diet, 6 per cent are [[vegetarian]], and 13 per cent identify as [[flexitarian]] (following a mainly vegetarian diet).<ref>{{Cite web |title=Dietary choices of Brits (e.g. vegeterian, flexitarian, meat-eater etc) |url=https://yougov.co.uk/topics/society/trackers/dietery-choices-of-brits-eg-vegeterian-flexitarian-meat-eater-etc |access-date=26 November 2024 |date=8 July 2024 |website=YouGov.co.uk}}</ref> The British Empire facilitated knowledge of [[Indian cuisine]] with its "strong, penetrating spices and herbs". British cuisine has absorbed the cultural influence of those who have settled in Britain, producing hybrid dishes, such as [[chicken tikka masala]].<ref>{{Cite news |date=19 April 2001 |title=Robin Cook's chicken tikka masala speech |work=The Guardian |location=London |url=https://www.theguardian.com/world/2001/apr/19/race.britishidentity |access-date=7 September 2021}}; {{Cite news |last=BBC E-Cyclopedia |date=20 April 2001 |title=Chicken tikka masala: Spice and easy does it |publisher=BBC |url=http://news.bbc.co.uk/1/hi/special_report/1999/02/99/e-cyclopedia/1285804.stm |access-date=28 September 2007}}</ref> The British have embraced world cuisine and regularly eat recipes or fast food from other European countries, the Caribbean and Asia.
The UK has many [[gastropub]]s and is the birthplace of many alcoholic drinks including several beer styles such as [[pale ale]], [[India pale ale]], [[bitter (beer)|bitter]], [[brown ale]], [[porter (beer)|porter]], and [[stout]]. The number of [[craft beer]]s and microbreweries has expanded rapidly in the last two decades.<ref>{{Cite web |title=A guide to British Beer |url=https://www.expatica.com/uk/lifestyle/food-drink/british-beer-469903/ |access-date=25 November 2024 |website=Expatica}}</ref> Other popular alcoholic drinks produced in the UK include [[Scotch whisky]], [[Wine from the United Kingdom|English wine]], [[gin]], [[perry]] and [[cider]].
=== Sport ===
{{Main|Sport in the United Kingdom|Great Britain at the Olympics}}
{{Further|Sport in England|Sport in Scotland|Sport in Wales|Sport in Northern Ireland}}
[[File:City vs United FA Cup final 2023.jpg|thumb|right|The [[2023 FA Cup final]] at [[Wembley Stadium]] between [[Manchester City]] and [[Manchester United]]]]
[[File:Old 18th tee lr.jpg|thumb|right|Golf originated from the [[Old Course at St Andrews]] in Scotland.]]
[[Association football]], [[tennis]], [[table tennis]], [[badminton]], [[rugby union]], [[rugby league]], [[rugby sevens]], [[golf]], [[boxing]], [[netball]], [[water polo]], [[field hockey]], [[English billiards|billiards]], [[darts]], [[Rowing (sport)|rowing]], [[rounders]] and [[cricket]] originated or were substantially developed in the UK, with the rules and codes of many modern sports invented and codified in the Victorian era.{{efn|In 2012, the president of the IOC, [[Jacques Rogge]], stated, "This great, sports-loving country is widely recognised as the birthplace of modern sport. It was here that the concepts of sportsmanship and fair play were first codified into clear rules and regulations. It was here that sport was included as an educational tool in the school curriculum."<ref>{{Cite web |url=http://www.olympic.org/Documents/Games_London_2012/London_2012_Opening_ceremony_Speech_Jacques_Rogge.pdf |title=Opening Ceremony of the Games of the XXX Olympiad |website=Olympic.org |access-date=30 November 2013 |date=27 July 2012 |archive-date=19 August 2013 |archive-url=https://web.archive.org/web/20130819135346/http://www.olympic.org/Documents/Games_London_2012/London_2012_Opening_ceremony_Speech_Jacques_Rogge.pdf |url-status=dead}}</ref><ref>{{Cite web |url=http://uk.reuters.com/article/uk-oly-preview-ad-idUKBRE86M0I720120723 |title=Unparalleled Sporting History |work=Reuters |access-date=30 November 2013 |last=Mehaffey |first=John |location=London |archive-date=25 May 2017 |archive-url=https://web.archive.org/web/20170525164121/http://uk.reuters.com/article/uk-oly-preview-ad-idUKBRE86M0I720120723 |url-status=dead}}</ref>}}
A poll in 2003 found that football is the most popular sport in the UK.<ref name="sports poll">{{Cite web |date=22 December 2003 |title=Rugby Union 'Britain's Second Most Popular Sport' |url=http://www.ipsos-mori.com/researchpublications/researcharchive/928/Rugby-Union-Britains-Second-Most-Popular-Sport.aspx |access-date=28 April 2013 |publisher=Ipsos-Mori}}</ref> England is recognised by [[FIFA]] as the birthplace of club football, and the [[Football Association]] is the oldest of its kind, with the [[Laws of the Game (association football)|rules of football]] first drafted in 1863 by [[Ebenezer Cobb Morley]].<ref>{{Cite news |last=Rudd |first=Alyson |date=7 April 2008 |title=The father of football deserves much more |work=The Times |location=London |url=http://www.timesonline.co.uk/tol/sport/football/article3694775.ece |url-access=subscription |access-date=29 January 2015 |archive-date=4 June 2011 |archive-url=https://web.archive.org/web/20110604183514/http://www.timesonline.co.uk/tol/sport/football/article3694775.ece |url-status=dead}}; {{Cite web |date=24 October 2007 |title=Sheffield FC: 150 years of history |url=https://www.fifa.com/worldfootball/clubfootball/news/newsid=621801.html |archive-url=https://web.archive.org/web/20071025033006/http://www.fifa.com/worldfootball/clubfootball/news/newsid=621801.html |archive-date=25 October 2007 |access-date=29 January 2015 |publisher=[[FIFA]]}}</ref> Each of the [[Home Nations]] (England, Scotland, Wales and Northern Ireland) has its own football association, national team and [[league system]], and each is individually a governing member of the [[International Football Association Board]] alongside FIFA. The English top division, the [[Premier League]], is the most watched football league in the world.<ref>{{Cite news |last=Ebner |first=Sarah |date=2 July 2013 |title=History and time are key to power of football, says Premier League chief |work=The Times |location=London |url=http://www.thetimes.co.uk/tto/public/ceo-summit/article3804923.ece |url-access=subscription |access-date=30 November 2013}}</ref> The first international football match was contested by [[England national football team|England]] and [[Scotland national football team|Scotland]] on 30 November 1872.<ref>{{Cite web |last=Mitchell, Paul |author-link=Paul Mitchell (broadcaster) |date=November 2005 |title=The first international football match |url=https://www.bbc.co.uk/scotland/sportscotland/asportingnation/article/0012/index.shtml |access-date=15 December 2013 |publisher=BBC Sport Scotland}}</ref> England, Scotland, [[Wales national football team|Wales]] and [[Northern Ireland national football team|Northern Ireland]] usually compete as separate countries in international competitions.<ref>{{Cite news |last=Harlow |first=Phil |date=5 August 2008 |title=Why is there no GB Olympics football team? |work=[[BBC Sport]] |url=http://news.bbc.co.uk/sport1/hi/olympics/football/7529807.stm |access-date=31 December 2010}}</ref>
In 2003 rugby union was ranked the second-most-popular sport in the UK.<ref name="sports poll" /> The sport was created in [[Rugby School]], Warwickshire, and the [[1871 England versus Scotland rugby union match|first rugby international]] took place on 27 March 1871 between [[England national rugby union team|England]] and [[Scotland national rugby union team|Scotland]].<ref>{{Cite web |url=https://www.bbc.co.uk/news/uk-england-coventry-warwickshire-25946757 |title=Six ways the town of Rugby helped change the world |work=BBC News |access-date=29 January 2015 |date=1 February 2014}}</ref><ref>{{Cite book |last1=Godwin |first1=Terry |last2=Rhys |first2=Chris |year=1981 |title=The Guinness Book of Rugby Facts & Feats |page=10 |publisher=Guinness Superlatives |isbn=978-0-85112-214-4}}</ref> England, Scotland, [[Wales national rugby union team|Wales]], [[Ireland national rugby union team|Ireland]], [[France national rugby union team|France]] and [[Italy national rugby union team|Italy]] compete in the [[Six Nations Championship]], the premier international rugby union tournament in the northern hemisphere. [[Sports governing bodies]] in [[Rugby union in England|England]], [[Rugby union in Scotland|Scotland]], [[Rugby union in Wales|Wales]] and [[Rugby union in Ireland|Ireland]] organise and regulate the game separately.<ref>{{Cite book |last1=Louw, Jaco |url=https://books.google.com/books?id=0-IiowvNomMC&pg=PA95 |title=The Girlfriends Guide to Rugby |last2=Nesbit, Derrick |publisher=South Publishers |year=2008 |isbn=978-0-620-39541-0 |location=Johannesburg}}</ref> Every four years the Home Nations make a combined team known as the [[British and Irish Lions]] which tours Australia, New Zealand and South Africa.
The United Kingdom hosted the [[Summer Olympic Games]] in [[1908 Summer Olympics|1908]], [[1948 Summer Olympics|1948]] and [[2012 Summer Olympics|2012]], with London acting as the host city on all three occasions. Birmingham hosted the [[2022 Commonwealth Games]], the seventh time a country of the United Kingdom hosted the [[Commonwealth Games]] (England, Scotland and Wales have each hosted the Commonwealth Games at least once).<ref>{{Cite news |title=The journey of India in Commonwealth Games in 2022 |work=The Times of India |url=https://timesofindia.indiatimes.com/readersblog/allaboutsports/the-journey-of-india-in-commonwealth-games-in-2022-44477/ |access-date=29 June 2023}}</ref>
=== Symbols ===
{{Main|Symbols of the United Kingdom, the Channel Islands and the Isle of Man|l1 = Symbols of the United Kingdom}}
[[File:Queen Elizabeth II Platinum Jubilee 2022 - Platinum Pageant (52123378222).jpg|thumb|Union Jack flags on [[The Mall, London|The Mall]], London]]
The [[flag of the United Kingdom]] is the [[Union Flag]], which is also referred to as the Union Jack.<ref>{{Cite web |title=Union Jack or Union Flag? |url=https://www.flaginstitute.org/wp/uk-flags/the-union-jack-or-the-union-flag |access-date=26 September 2022 |website=The Flag Institute}}</ref> It was created in 1606 by the superimposition of the [[flag of England]], representing [[Saint George]], on the [[flag of Scotland]], representing [[Saint Andrew]], and was updated in 1801 with the addition of [[Saint Patrick's Flag]].<ref>{{Cite web |title=college-of-arms.gov.uk |url=https://www.college-of-arms.gov.uk/resources/union-flag-approved-designs |access-date=14 January 2022 |publisher=The College of Arms}}</ref> Wales is not represented in the Union Flag, as Wales had been conquered and [[annexed]] to England prior to the formation of the United Kingdom. The possibility of redesigning the Union Flag to include representation of Wales was discussed in 2007.<ref>{{Cite news |date=27 November 2007 |title=Welsh dragon call for Union flag |work=BBC News |url=http://news.bbc.co.uk/1/hi/uk/7114248.stm |access-date=17 October 2008}}</ref> The [[national anthem]] of the United Kingdom is "[[God Save the King]]", with "King" replaced with "Queen" in the lyrics whenever the monarch is a woman.
[[Britannia]] is a [[national personification]] of the United Kingdom, originating from [[Roman Britain]].<ref>{{Cite web |title=Britannia on British Coins |url=http://www.24carat.co.uk/britanniaframe.html |access-date=25 June 2006 |publisher=Chard}}</ref> Beside [[The Lion and the Unicorn]] and the [[Welsh Dragon|dragon]] of heraldry, the [[bulldog]] is an iconic animal and commonly represented with the Union Flag.<ref>{{Cite book |last=Baker |first=Steve |title=Picturing the Beast |publisher=University of Illinois Press |year=2001 |isbn=978-0-252-07030-3 |page=52}}</ref> A rare personification is a character originating in the 18th century, [[John Bull]].<ref>{{Cite web |last=<!--Not stated--> |title=Who is John Bull |url=https://www.loc.gov/wiseguide/jan04/johnbull.html |access-date=11 January 2022 |publisher=The Library of Congress}}</ref>
[[National symbols of England|England]], [[National symbols of Wales|Wales]] and [[National symbols of Scotland|Scotland]] each have their own national symbols, including their national flags. [[National symbols of Ireland, the Republic of Ireland and Northern Ireland|Northern Ireland]] also has symbols, many of which are shared with the [[Republic of Ireland]].
== See also ==
{{Portal|United Kingdom|England|Northern Ireland|Scotland|Wales}}
* [[Outline of the United Kingdom]]
** [[Outline of England]]
** [[Outline of Northern Ireland]]
** [[Outline of Scotland]]
** [[Outline of Wales]]
* [[International rankings of the United Kingdom]]
* [[Historiography of the United Kingdom]]
* [[Historiography of the British Empire]]
* [[United Kingdom–Crown Dependencies Customs Union]]
== Notes ==
{{Notelist}}
== References ==
{{Reflist}}
== External links ==
{{Sister project links|auto=yes}}
* [https://www.bbc.co.uk/news/world-europe-18023389 United Kingdom] from [[BBC News]]
* [https://web.archive.org/web/20260118175542/https://www.cia.gov/the-world-factbook/countries/united-kingdom/ United Kingdom]. ''[[The World Factbook]]''. [[Central Intelligence Agency]].
* [https://web.archive.org/web/20090406224510/http://ucblibraries.colorado.edu/govpubs/for/british.htm United Kingdom] from ''UCB Libraries GovPubs'' (archived 6 April 2009)
* {{Wikiatlas|United Kingdom}}
* {{OSM relation|62149}}
* [http://www.ifs.du.edu/ifs/frm_CountryProfile.aspx?Country=GB Key Development Forecasts for the United Kingdom] from [[International Futures]]
=== Government ===
* [https://www.gov.uk/ Official website of HM Government]
* [https://www.royal.uk/ Official website of the British Monarchy]
* [https://www.gov.uk/government/organisations/prime-ministers-office-10-downing-street Official website of the British Prime Minister's Office]
=== Travel ===
* [http://www.visitbritain.com/en/ Official tourist guide to Britain]
<!-- Please discuss links on the talk page before adding them to this list – remember to read the WP:EL guideline.-->
{{United Kingdom topics}}
{{Navboxes
| list =
{{United Kingdom constituents and affiliations}}
{{British Isles}}
{{Sovereign states of Europe}}
{{Commonwealth realms}}
{{English official language clickable map}}
{{The Commonwealth}}
}}
{{Authority control}}
{{Coord|55|N|3|W|type:country_region:GB|display=title}}
[[Category:United Kingdom| ]]
[[Category:British Islands]]
[[Category:Countries in Europe]]
[[Category:Countries and territories where English is an official language]]
[[Category:G20 members]]
[[Category:Island countries]]
[[Category:Member states of NATO]]
[[Category:Member states of the Commonwealth of Nations]]
[[Category:Member states of the Council of Europe]]
[[Category:Member states of the United Nations]]
[[Category:OECD members]]
[[Category:States and territories established in 1707]]
[[Category:States and territories established in 1801]]
[[Category:States and territories established in 1922]]
pov14ogirxro821rmu3zv10sbdjtyba
9320
9319
2026-08-23T08:17:30Z
RAPTOR7762
18
1 revision imported from [[:en:United_Kingdom]]
9319
wikitext
text/x-wiki
{{Short description|Country in northwestern Europe}}
{{Hatnote|"UK" redirects here. For other uses, see [[UK (disambiguation)]] and [[United Kingdom (disambiguation)]]. Not to be confused with [[England]] or [[Great Britain]].}}
{{pp-sock|small=yes}}
{{pp-move|small=yes}}
{{Use British English|date=April 2012}}
{{Use dmy dates|date=November 2025}}
{{Infobox country
| common_name = United Kingdom
| linking_name = the United Kingdom<!--Note: "the" required here as this entry used to create wikilinks-->
| conventional_long_name = United Kingdom of Great Britain and Northern Ireland
| image_flag = Flag of the United Kingdom (1-2).svg
| flag_type = [[Union Jack|Flag]]
| alt_flag = A flag composed of a red cross edged in white and superimposed on a red saltire, also edged in white, superimposed on a white saltire on a blue background
| image_coat =
| other_symbol = [[File:Coat of arms of the United Kingdom (2022, both variants).svg|250px]]<br />Used in relation to [[Scotland]] (right) and elsewhere (left)
| other_symbol_type = [[Coat of arms of the United Kingdom|Coat of arms]]:
| national_anthem = "[[God Save the King]]"{{Efn|"God Save the King" is the [[national anthem]] by custom, not statute, and there is no authorised version. Typically only the first verse is usually sung, although the second verse is also often sung as well at state and public events.<ref>{{Cite web |title=National Anthem |url=https://www.royal.uk/encyclopedia/national-anthem |access-date=10 April 2024 |website=The Royal Family |archive-date=20 May 2024 |archive-url=https://web.archive.org/web/20240520130352/https://www.royal.uk/encyclopedia/national-anthem |url-status=live}}</ref> The words ''King, he, him, his'', used at present, are replaced by ''Queen, she, her'' when the monarch is female.}}<br /><div style="display:inline-block;margin-top:0.4em;">[[File:United States Navy Band - God Save the Queen.ogg|God Save the King / Queen <!-- Do not change file name due to computer error without ensuring that the file is playable. -->]]</div>
| image_map = {{Switcher|[[File:Europe-UK (orthographic projection).svg|upright=1.15|frameless]]|Show globe|[[File:Europe-UK.svg|upright=1.15|frameless]]|Show map of Europe|[[File:United Kingdom (+overseas territories and crown dependencies) in the World (+Antarctica claims).svg|upright=1.15|frameless]]|Show [[British Overseas Territories]] and [[Crown Dependencies]]|[[File:Territorial waters - United Kingdom.svg|upright=1.15|frameless]]|Show [[Exclusive economic zone of the United Kingdom|their exclusive economic zones]]|default=1}}
| map_caption =
| capital = [[London]]
| coordinates = {{Coord|51|30|N|0|7|W|type:city(9,100,000)_region:GB-LND}}
| largest_city = capital
| languages_type = [[National language]]
| languages = [[English language|English]] <!--Note: Just English, don't add "British English".-->
| languages2_type = Regional and minority languages{{Efn|Scots, Ulster Scots, Welsh, Cornish, Scottish Gaelic and Irish are classed as [[Regional language|regional]] or [[Minority language|minority]] languages under the [[Council of Europe]]'s [[European Charter for Regional or Minority Languages]].<ref name="reglang">{{Cite web |title=List of declarations made with respect to treaty No. 148 |url=http://conventions.coe.int/treaty/Commun/ListeDeclarations.asp?CL=ENG&NT=148&VL=1 |access-date=12 December 2013 |publisher=[[Council of Europe]] |archive-date=12 December 2013 |archive-url=https://web.archive.org/web/20131212175720/http://conventions.coe.int/treaty/Commun/ListeDeclarations.asp?CL=ENG&NT=148&VL=1 |url-status=dead}}</ref> These include defined obligations to promote those languages.<ref>{{Cite web |title=Welsh language on GOV.UK – Content design: planning, writing and managing content – Guidance |url=https://www.gov.uk/guidance/content-design/welsh-language-on-gov-uk |access-date=3 August 2018 |website=gov.uk |archive-date=4 August 2018 |archive-url=https://web.archive.org/web/20180804014121/https://www.gov.uk/guidance/content-design/welsh-language-on-gov-uk |url-status=live |postscript=;}} {{Cite news |title=Welsh language scheme |work=GOV.UK |url=https://www.gov.uk/government/organisations/department-for-transport/about/welsh-language-scheme |access-date=3 August 2018 |archive-date=4 August 2018 |archive-url=https://web.archive.org/web/20180804014119/https://www.gov.uk/government/organisations/department-for-transport/about/welsh-language-scheme |url-status=live |postscript=;}} {{Cite news |title=Welsh language scheme |work=GOV.UK |url=https://www.gov.uk/government/organisations/home-office/about/welsh-language-scheme |access-date=3 August 2018 |archive-date=2 August 2018 |archive-url=https://web.archive.org/web/20180802010917/https://www.gov.uk/government/organisations/home-office/about/welsh-language-scheme |url-status=live}}</ref> See also [[Languages of the United Kingdom]]. Welsh has limited ''[[de jure]]'' official status in Wales, as well as in the provision of national government services provided for Wales.}}
| languages2 = {{Hlist
<!--Anglic-->
| [[Scots language|Scots]]
| [[Ulster Scots dialects|Ulster Scots]]
<!--Brittonic-->
| [[Welsh language|Welsh]]
| [[Cornish language|Cornish]]
<!--Goidelic-->
| [[Scottish Gaelic]]<!--Keep "Scottish Gaelic"; people will find "Gaelic" confusing, as the Irish language is also commonly called "Gaelic"-->
| [[Irish language|Irish]]
<!--BANZSL-->
| [[British Sign Language]]
}}
| ethnic_groups = {{unbulleted list
| 83.1% [[White people in the United Kingdom|White]]
| 8.6% [[British Asian|Asian]]
| 3.7% [[Black British|Black]]
| 2.7% [[Mixed (United Kingdom ethnicity category)|Mixed]]
| 2.0% [[Ethnic groups in the United Kingdom|other]]
}}
| ethnic_groups_year = 2021
| ethnic_groups_ref = {{Efn|name=UK-wide2021|Whereas the censuses of England and Wales and of Northern Ireland went ahead as planned in 2021, the census in Scotland was postponed until 2022. The Office for National Statistics reports that these UK-wide statistics "have been created to provide an image of how UK census data may have looked if the most recent UK censuses had been conducted with an aligned date of 21 March 2021".}}<ref name=Ethnicity2021>{{cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/censusbasedstatisticsuk2021|title=Table 06: UK06 - Ethnic group by sex by age, United Kingdom|work=Census-based statistics UK: 2021|publisher=Office for National Statistics|date=27 June 2025|access-date=28 March 2026}}</ref>
| religion = {{unbulleted list
| 46.6% [[Religion in the United Kingdom#Christianity|Christianity]]
| 37.6% [[Irreligion in the United Kingdom|no religion]]
| 6.0% [[Islam in the United Kingdom|Islam]]
| 1.6% [[Hinduism in the United Kingdom|Hinduism]]
| 2.2% [[Religion in the United Kingdom|other]]
| 5.9% not stated
}}
| religion_year = 2021
| religion_ref = {{Efn|name=UK-wide2021}}<ref name=Religion2021>{{cite web|url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/censusbasedstatisticsuk2021|title=Table 07: UK07 - Religion by sex by age, United Kingdom|work=Census-based statistics UK: 2021|publisher=Office for National Statistics|date=27 June 2025|access-date=28 March 2026}}</ref>
| demonym = {{hlist |[[British people|British]] |Briton |Brit (colloquial) }}
| government_type = Unitary [[Westminster parliamentary system|parliamentary constitutional monarchy]]{{Efn|Although the United Kingdom has traditionally been seen as a [[unitary state]], an alternative description of the UK as a "union state", put forward by, amongst others, [[Vernon Bogdanor]],<ref>{{Cite book |last=Bradbury |first=Jonathan |url=https://books.google.com/books?id=c3QWEAAAQBAJ&q=%2522union+state%2522+UK+unitary&pg=PA19 |title=Constitutional Policy and Territorial Politics in the UK: Volume 1: Union and Devolution 1997–2012 |date=2021 |publisher=Policy Press |isbn=978-1-5292-0588-6 |pages=19–20 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204328/https://books.google.com/books?id=c3QWEAAAQBAJ&q=%2522union+state%2522+UK+unitary&pg=PA19#v=onepage&q=%2522union%20state%2522%20UK%20unitary&f=false |url-status=live}}</ref> has become increasingly influential since the adoption of devolution in the 1990s.<ref>{{Cite book |last=Leith |first=Murray Stewart |url=https://books.google.com/books?id=PeBvAAAAQBAJ&q=Uk+%2522unitary+state%2522&pg=PA39 |title=Political Discourse and National Identity in Scotland |date=2012 |publisher=Edinburgh University Press |isbn=978-0-7486-8862-3 |page=39 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204223/https://books.google.com/books?id=PeBvAAAAQBAJ&q=Uk+%2522unitary+state%2522&pg=PA39#v=onepage&q=Uk%20%2522unitary%20state%2522&f=false |url-status=live}}</ref> A union state is considered to differ from a unitary state in that while it maintains a central authority it also recognises the authority of historic rights and infrastructures of its component parts.<ref>{{Cite book |last1=Gagnon |first1=Alain-G. |url=https://books.google.com/books?id=g0ahE2fTxS0C&q=%2522union+state%2522+UK+unitary&pg=PA47 |title=Multinational Democracies |last2=Tully |first2=James |date=2001 |publisher=Cambridge University Press |isbn=978-0-521-80473-8 |page=47 |access-date=3 October 2021 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002204329/https://books.google.com/books?id=g0ahE2fTxS0C&q=%2522union+state%2522+UK+unitary&pg=PA47#v=onepage&q=%2522union%20state%2522%20UK%20unitary&f=false |url-status=live |postscript=;}} {{Cite book |last=Bogdanor |first=Vernon |title=Constitutional Reform in the United Kingdom: Practice and Principles |date=1998 |publisher=Hart Publishing |isbn=978-1-901362-84-8 |editor-last=Beatson |editor-first=Jack |location=Oxford |page=18 |chapter=Devolution: the Constitutional Aspects |chapter-url=https://books.google.com/books?id=YEEgDsCYmbQC&q=%2522union+state%2522+UK+unitary&pg=PA18}}</ref>}}
| leader_title1 = [[Monarchy of the United Kingdom|Monarch]]
| leader_name1 = [[Charles III]]
| leader_title2 = [[Prime Minister of the United Kingdom|Prime Minister]]
| leader_name2 = [[Andy Burnham]]
| legislature = [[Parliament of the United Kingdom|Parliament]]
| upper_house = [[House of Lords]]
| lower_house = [[House of Commons of the United Kingdom|House of Commons]]
| sovereignty_type = [[Formation of the United Kingdom of Great Britain and Northern Ireland|Formation]]
| established_event1 = [[Laws in Wales Acts 1535 and 1542|Laws in Wales Acts]]
| established_date1 = 1535 and 1542
| established_event2 = [[Union of the Crowns]]
| established_date2 = 24 March 1603
| established_event3 = [[Treaty of Union]]
| established_date3 = 22 July 1706
| established_event4 = [[Acts of Union 1707|Acts of Union of England and Scotland]]
| established_date4 = 1 May 1707
| established_event5 = [[Acts of Union 1800|Acts of Union of Great Britain and Ireland]]
| established_date5 = 1 January 1801
| established_event6 = [[Irish Free State Constitution Act 1922|Irish Free State Constitution Act]]
| established_date6 = 6 December 1922
| area_label = Total{{efn|name=ONSArea|[[Office for National Statistics|ONS]] Standard Area Measurement, 'area to mean high water'. Excludes the [[Crown Dependencies]] and [[British Overseas Territories]].}}
| area_km2 = 244376
| area_footnote = <ref name="ONS Standard Area Measurement">{{cite web |url=https://geoportal.statistics.gov.uk/datasets/ons::standard-area-measurements-for-administrative-areas-december-2023-in-the-uk/about |title=Standard Area Measurements for Administrative Areas (December 2023) in the UK |author=<!--Not stated--> |date=31 May 2024 |website=[[ONS Open Geography Portal|Open Geography Portal]] |publisher=Office for National Statistics |access-date=7 June 2024 |archive-date=7 June 2024 |archive-url=https://web.archive.org/web/20240607052407/https://geoportal.statistics.gov.uk/datasets/ons::standard-area-measurements-for-administrative-areas-december-2023-in-the-uk/about |url-status=live}}</ref>
| area_rank = 78th
| area_sq_mi = auto
| area_label2 = Land{{efn|name=ONSLandArea|[[Office for National Statistics|ONS]] Standard Area Measurement, "area to mean high water excluding inland water". Excludes the [[Crown Dependencies]] and [[British Overseas Territories]].}}
| area_data2 = {{convert|{{UK subdivision area|GSS=K02000001}}|km2|sqmi|abbr=on}}<ref name="ONS mid-year pop est" />
| percent_water =
| population_estimate = {{IncreaseNeutral}} {{UK subdivision population|GSS=K02000001}}<ref name="ONS mid-year pop est">{{UK subdivision statistics citation}}</ref>
| population_estimate_year = {{UK subdivision statistics year}}
| population_estimate_rank = 20th
| population_census = {{IncreaseNeutral}} 66,912,637{{Efn|name=UK-wide2021}}<ref name=Ethnicity2021/>
| population_census_year = 2021
| population_census_rank =
| population_density_km2 = {{UK subdivision density|GSS=K02000001}}
| population_density_sq_mi = auto
| population_density_rank = 48th
| pop_den_footnote = <ref name="ONS mid-year pop est" />
| GDP_PPP = {{increase}} $4.721 trillion<ref name="IMFWEO.UK">{{cite web |url=https://data.imf.org/en/Data-Explorer?datasetUrn=IMF.RES:WEO(9.0.0) |title=World Economic Outlook Database (April 2026 Edition) |publisher=[[International Monetary Fund]] |website=www.imf.org |date=14 April 2026 |access-date=18 April 2026}}</ref>
| GDP_PPP_year = 2026
| GDP_PPP_rank = 10th
| GDP_PPP_per_capita = {{increase}} $67,585<ref name="IMFWEO.UK" />
| GDP_PPP_per_capita_rank = 33rd
| GDP_nominal = {{increase}} $4.265 trillion<ref name="IMFWEO.UK" />
| GDP_nominal_year = 2026
| GDP_nominal_rank = 5th
| GDP_nominal_per_capita = {{increase}} $61,056<ref name="IMFWEO.UK" />
| GDP_nominal_per_capita_rank = 21st
| Gini = 35.4
| Gini_year = 2021
| Gini_change = decrease
| Gini_ref = <ref>{{Cite web |title=Income inequality |url=https://data.oecd.org/inequality/income-inequality.htm |access-date=12 February 2024 |website=OECD Data |publisher=[[OECD]] |archive-date=1 July 2022 |archive-url=https://web.archive.org/web/20220701171540/https://data.oecd.org/inequality/income-inequality.htm |url-status=live}}</ref>
| HDI = 0.946<!--number only-->
| HDI_year = 2023<!-- Please use the year to which the data refers, not the publication year.-->
| HDI_change = increase<!--increase/decrease/steady-->
| HDI_ref = <ref name="UNHDR">{{Cite web |date=6 May 2025 |title=Human Development Report 2025 |url=https://hdr.undp.org/system/files/documents/global-report-document/hdr2025reporten.pdf |url-status=live |archive-url=https://web.archive.org/web/20250506051232/https://hdr.undp.org/system/files/documents/global-report-document/hdr2025reporten.pdf |archive-date=6 May 2025 |access-date=6 May 2025 |publisher=[[United Nations Development Programme]] |language=en}}</ref>
| HDI_rank = 13th
| currency = [[Pound sterling|Sterling]]<!--The currency is simply called 'sterling' (see its article); originally, the penny (not the pound) was the primary unit. Internationally it is known as 'pound sterling' so the familiar unit is mentioned.-->{{Efn|Commonly also known as the "pound" (the name of [[pound (currency)|its base unit]]) or "pound sterling". Some of the devolved countries, [[Crown Dependency|Crown Dependencies]] and [[British Overseas Territory|British Overseas Territories]] issue their own sterling banknotes or currencies, or use another nation's currency. See [[List of British currencies]].}} ([[£]])
| currency_code = GBP
| utc_offset = +0
| time_zone = [[Greenwich Mean Time|GMT]]
| utc_offset_DST = +1
| time_zone_DST = [[British Summer Time|BST]]{{Efn|Also observed by the [[Crown Dependencies]]. For further information, see [[Time in the United Kingdom]].}}
| DST_note =
| date_format = {{Abbr|dd|day}}/{{Abbr|mm|month}}/{{Abbr|yyyy|year}} ([[Anno Domini|AD]]){{efn|The UK Government uses the [[ISO 8601]] format, {{Abbr|yyyy|year}}-{{Abbr|mm|month}}-{{Abbr|dd|day}}, for machine-readable dates and times.<ref>{{cite web |title=Formatting dates and times in data |url=https://www.gov.uk/government/publications/open-standards-for-government/date-times-and-time-stamps-standard |date=9 August 2022 |website=[[gov.uk]] |publisher=[[Government of the United Kingdom|HM Government]] |access-date=1 June 2024 |archive-date=9 May 2024 |archive-url=https://web.archive.org/web/20240509092813/https://www.gov.uk/government/publications/open-standards-for-government/date-times-and-time-stamps-standard |url-status=live}}</ref> See [[Date and time notation in the United Kingdom]].}}
| calling_code = [[Telephone numbers in the United Kingdom|+44]]{{Efn|Excludes most overseas territories. See [[Telephone numbers in the United Kingdom#Telephone numbers in Overseas Territories]].}}
| cctld = [[.uk]]{{Efn|The [[.gb]] domain is also reserved for the UK, but has been little used.}}
}}
The '''United Kingdom of Great Britain and Northern Ireland''', commonly known as the '''United Kingdom''' ('''UK''') or '''Britain''',<!--DO NOT CHANGE ORDER OF INTRO WITHOUT CONSENSUS-->{{Efn|Usage is mixed. ''[[The Guardian]]''<ref>{{Cite news |date=2021-04-23 |title=Guardian style guide: U |url=https://www.theguardian.com/guardian-style-guide-u |access-date=2025-12-29 |work=The Guardian |language=en-GB |issn=0261-3077}}</ref> and ''[[The Daily Telegraph|The Telegraph]]''<ref>{{Cite news |date=2025-07-25 |title=Places |url=https://www.telegraph.co.uk/style-book/places/ |access-date=2025-12-29 |work=The Telegraph |language=en-GB |issn=0307-1235 |archive-date=17 November 2025 |archive-url=https://web.archive.org/web/20251117111222/https://www.telegraph.co.uk/style-book/places/ |url-status=live }}</ref> use ''Britain'' as a synonym for the United Kingdom. The British [[Cabinet Office]]'s [[Government Digital Service]] style guide<ref>{{Cite web |title=Style guide - A to Z - Guidance - GOV.UK |url=https://www.gov.uk/guidance/style-guide/a-to-z#great-britain |access-date=2026-01-02 |website=www.gov.uk |language=en |archive-date=22 November 2024 |archive-url=https://web.archive.org/web/20241122222025/https://www.gov.uk/guidance/style-guide/a-to-z#great-britain |url-status=live }}</ref> for use on [[gov.uk]] recommends: "Use UK and United Kingdom in preference to Britain and British (UK business, UK foreign policy, ambassador and high commissioner). But British embassy, not UK embassy."}} is a country<!-- The term "country" was chosen as a result of a 2022 Request for Comment. Discuss potential changes on the talk page first. --> in [[northwestern Europe]], off the coast of [[European mainland|the continental mainland]]. It comprises [[England]], [[Scotland]], [[Wales]] and [[Northern Ireland]],{{efn|The [[Isle of Man]], [[Bailiwick of Guernsey|Guernsey]] and [[Jersey]] are [[Crown Dependencies]] and not part of the UK.}} with a population of over 69 million in 2024. The UK includes the island of [[Great Britain]], the north-eastern part of the island of [[Ireland]], and most of [[List of islands of the United Kingdom|the smaller islands]] within the [[British Isles]], covering {{Convert|244376|km2|sqmi|order=flip}}.{{efn|name=ONSArea}} It shares [[Republic of Ireland–United Kingdom border|a land border]] with the [[Republic of Ireland]] and is surrounded by the [[Atlantic Ocean]], the [[North Sea]], the [[English Channel]], the [[Celtic Sea]] and the [[Irish Sea]], while maintaining sovereignty over the [[Crown Dependencies]] and the [[British Overseas Territories]]. The capital and largest city of England and the UK is [[London]]; [[Edinburgh]], [[Cardiff]] and [[Belfast]] are the national capitals of Scotland, Wales and Northern Ireland, respectively.
The British Isles have been continuously inhabited since the [[Neolithic]]. In AD 43 the [[Roman conquest of Britain]] began. The [[end of Roman rule in Britain|Roman departure]] between 383 and 410 was followed by [[Anglo-Saxon settlement of Britain|Anglo-Saxon settlement]] beginning around 450. In 1066 the [[Norman Conquest|Normans conquered England]]. Over the 17th century the role of the [[British monarchy]] was reduced, particularly as a result of the [[English Civil War]]. In 1707 the Kingdom of England and the [[Kingdom of Scotland]] united under the [[Treaty of Union]] to create the [[Kingdom of Great Britain]]. The [[Acts of Union 1800]] incorporated the [[Kingdom of Ireland]] to create the [[United Kingdom of Great Britain and Ireland]] in 1801. Most of Ireland [[Partition of Ireland|seceded]] from the UK in 1922 as the [[Irish Free State]], and the [[Royal and Parliamentary Titles Act 1927]] created the present United Kingdom.
The UK [[History of industrialisation#Industrial Revolution in Europe|became the first industrialised country]] and was the world's [[foremost power]] for the majority of the 19th and early 20th centuries, particularly during the ''[[Pax Britannica]]'' between 1815 and 1914. The [[British Empire]] was the leading [[economic power]] for most of the 19th century, a position supported by [[British Agricultural Revolution|its agricultural prosperity]], its role as a dominant [[trading nation]], a massive industrial capacity, [[List of British innovations and discoveries in the 19th century|significant technological achievements]], and the rise of [[19th-century London]] as the world's principal financial centre. At its height in the 1920s, the empire encompassed around a quarter of the world's landmass and population, and was the [[List of largest empires#Empires at their greatest extent|largest in history]]. However, [[History of the United Kingdom during the First World War|its involvement in the First World War]] and [[Military history of the United Kingdom during World War II|in the Second World War]] damaged [[Economy of the British Empire|Britain's economic power]], and a global wave of [[decolonisation]] led to the independence of most British colonies.
The UK is a [[constitutional monarchy]] and [[parliamentary democracy]]{{Efn|The United Kingdom does not have a codified constitution but an unwritten one formed of Acts of Parliament, court judgments, traditions, and conventions.<ref>{{Citation |title=What is the UK Constitution? |date=9 August 2018 |url=https://www.ucl.ac.uk/constitution-unit/what-uk-constitution/what-uk-constitution |publisher=The Constitution Unit of UCL |access-date=6 February 2020 |archive-date=7 November 2018 |archive-url=https://web.archive.org/web/20181107060057/http://www.ucl.ac.uk/constitution-unit/whatis/uk-constitution |url-status=live}}</ref>}} with three distinct jurisdictions: [[English law|England and Wales]], [[Scots law|Scotland]], and [[Law of Northern Ireland|Northern Ireland]]. Scotland, Wales and Northern Ireland have their own governments and parliaments which control various [[Devolution in the United Kingdom|devolved]] matters. A [[developed country]] with [[Economy of the United Kingdom|an advanced economy]], the UK ranks amongst the [[List of countries by GDP (nominal)|largest economies by nominal GDP]] and is one of the world's [[List of countries by exports|largest exporters]] and [[List of countries by imports|importers]]. As a [[nuclear state]] with one of the [[List of countries by military expenditures|highest defence budgets]], the UK maintains [[British Armed Forces|one of the strongest militaries in Europe]]. [[Culture of the United Kingdom|British culture]] is globally influential, notably in the [[Anglosphere]] and [[Commonwealth of Nations|the Commonwealth]]; [[Anglicisation|its soft power influence]] is observable in the legal and political systems of many [[List of countries that have gained independence from the United Kingdom|former colonies]], and in its exports [[English-speaking world|of language]], [[British literature|literature]], [[Theatre of the United Kingdom|theatre]], [[Cinema of the United Kingdom|cinema]], [[Music of the United Kingdom|music]], [[Mass media in the United Kingdom|media]], [[Art of the United Kingdom|art]] and [[Sport in the United Kingdom|sport]]. A [[great power]], the UK is part of [[Foreign relations of the United Kingdom#International organisations|numerous international organisations]].
== Etymology and terminology ==
{{Anchor|Etymology}}<!--linked-->
{{See also|Britain (place name)|Terminology of the British Isles}}
The [[Acts of Union 1707]] declared that the [[Kingdom of England]] and the [[Kingdom of Scotland]] were "United into One Kingdom by the Name of Great Britain".{{Efn|Compare to section 1 of both of the 1800 [[Acts of Union (1800)|Acts of Union]] which reads: "the kingdoms of Great Britain and Ireland shall{{spaces}}... be united into one kingdom, by the name of the United Kingdom of Great Britain and Ireland".}}<ref name="Acts of Union 1707">{{Cite web |title=The Treaty (act) of the Union of Parliament 1706 |url=http://www.scotshistoryonline.co.uk/union.html |archive-url=https://web.archive.org/web/20190527074630/http://www.scotshistoryonline.co.uk/union.html |archive-date=27 May 2019 |access-date=23 August 2011 |publisher=Scots History Online |postscript=;}} {{Cite book |last1=Barnett, Hilaire |url=https://books.google.com/books?id=LYc1tSYonrQC&pg=PA165 |title=Constitutional & Administrative Law |last2=Jago, Robert |publisher=Routledge |year=2011 |isbn=978-0-415-56301-7 |edition=8th |location=Abingdon |page=165 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140722/https://books.google.com/books?id=LYc1tSYonrQC&pg=PA165 |url-status=live}}</ref> The term "United Kingdom" has occasionally been used for the former [[Kingdom of Great Britain]], although its official name from 1707 to 1800 was simply "Great Britain".<ref>"After the political union of England and Scotland in 1707, the nation's official name became 'Great Britain{{'"}}, ''The American Pageant, Volume 1'', Cengage Learning (2012); "From 1707 until 1801 ''Great Britain'' was the official designation of the kingdoms of England and Scotland". ''The Standard Reference Work: For the Home, School and Library, Volume 3'', Harold Melvin Stanford (1921); "In 1707, on the union with Scotland, 'Great Britain' became the official name of the British Kingdom, and so continued until the union with Ireland in 1801". ''United States Congressional serial set, Issue 10; Issue 3265'' (1895); {{Cite web |last=Gascoigne, Bamber |author-link=Bamber Gascoigne |title=History of Great Britain (from 1707) |url=http://www.historyworld.net/wrldhis/PlainTextHistories.asp?historyid=ab07 |access-date=18 July 2011 |publisher=History World |archive-date=27 May 2019 |archive-url=https://web.archive.org/web/20190527205230/http://www.historyworld.net/wrldhis/PlainTextHistories.asp?historyid=ab07 |url-status=live}}</ref> The [[Acts of Union 1800]] formed the [[United Kingdom of Great Britain and Ireland]]. Following the [[partition of Ireland]] and the independence of the [[Irish Free State]] in 1922, which left [[Northern Ireland]] as the only part of the island of Ireland within the United Kingdom, the name was changed in 1927 to the "United Kingdom of Great Britain and Northern Ireland".<ref>{{Cite book |last=Cottrell, P. |url=https://archive.org/details/irishcivilwar00cott_573 |title=The Irish Civil War 1922–23 |year=2008 |isbn=978-1-84603-270-7 |page=[https://archive.org/details/irishcivilwar00cott_573/page/n85 85] |publisher=Bloomsbury USA |url-access=limited}}</ref>
Although the United Kingdom is a sovereign country, England, Scotland, Wales and Northern Ireland are widely referred to as [[Countries of the United Kingdom|countries]].<ref>{{Citation |last1=S. Dunn |title=An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict |year=2000 |place=[[Lewiston, New York]] |publisher=[[Edwin Mellen Press]] |quote=One specific problem – in both general and particular senses – is to know what to call Northern Ireland itself: in the general sense, it is not a country, or a province, or a state – although some refer to it contemptuously as a statelet: the least controversial word appears to be jurisdiction, but this might change. |last2=H. Dawson |postscript=;}} {{Cite web |date=15 December 2011 |title=Changes in the list of subdivision names and code elements |url=http://www.iso.org/iso/iso_3166-2_newsletter_ii-3_2011-12-13.pdf |access-date=28 May 2012 |website=ISO 3166-2 |publisher=International Organization for Standardization |archive-date=19 September 2016 |archive-url=https://web.archive.org/web/20160919073956/http://www.iso.org/iso/iso_3166-2_newsletter_ii-3_2011-12-13.pdf |url-status=live}}</ref> The UK Prime Minister's website has used the phrase "countries within a country" to describe it.<ref name="page823">{{Cite web |date=10 January 2003 |title=Countries within a country |url=http://www.number10.gov.uk/Page823 |archive-url=http://webarchive.nationalarchives.gov.uk/20080909013512/http://www.number10.gov.uk/Page823 |archive-date=9 September 2008 |access-date=8 March 2015 |publisher=Prime Minister's Office}}</ref> Some statistical summaries, such as those for the twelve [[NUTS of the United Kingdom|NUTS 1 regions]], refer to Scotland, Wales and Northern Ireland as "regions".<ref>{{Cite web |title=Statistical bulletin: Regional Labour Market Statistics |url=http://www.ons.gov.uk/ons/dcp171778_346117.xml |archive-url=https://web.archive.org/web/20141224045523/http://www.ons.gov.uk/ons/dcp171778_346117.xml |archive-date=24 December 2014 |access-date=5 March 2014 |postscript=;}} {{Cite web |title=13.4% Fall In Earnings Value During Recession |url=http://www.gmb.org.uk/newsroom/fall-in-earnings-value-during-recession |archive-url=https://web.archive.org/web/20140103194604/http://www.gmb.org.uk/newsroom/fall-in-earnings-value-during-recession |archive-date=3 January 2014 |access-date=5 March 2014}}</ref> Northern Ireland is also referred to as a "province".<ref>{{Cite book |last1=Dunn, Seamus |title=An Alphabetical Listing of Word, Name and Place in Northern Ireland and the Living Language of Conflict |last2=Dawson, Helen |publisher=[[Edwin Mellen Press]] |year=2000 |isbn=978-0-7734-7711-7 |location=[[Lewiston, New York]] |postscript=;}} {{Cite book |last=Murphy, Dervla |title=[[A Place Apart (Murphy book)|A Place Apart]] |publisher=Penguin |year=1979 |isbn=978-0-14-005030-1 |location=London}}</ref> With regard to Northern Ireland, the descriptive name used "can be controversial, with the choice often revealing one's political preferences".<ref>{{Cite book |last1=Whyte |first1=John |title=Interpreting Northern Ireland |last2=FitzGerald |first2=Garret |publisher=Clarendon Press |year=1991 |isbn=978-0-19-827380-6 |location=Oxford |author-link=John Henry Whyte |author-link2=Garret FitzGerald}}</ref>
The term "Great Britain" conventionally refers to the island of Great Britain, or politically to England, Scotland and Wales in combination.<ref>{{Cite news |date=19 December 2008 |title=Guardian Unlimited Style Guide |publisher=Guardian News and Media Limited |location=London |url=https://www.theguardian.com/styleguide/page/0,,184840,00.html |access-date=23 August 2011 |postscript=;}} {{Cite news |date=19 August 2002 |title=BBC style guide (Great Britain) |work=BBC News |url=http://news.bbc.co.uk/1/hi/programmes/radio_newsroom/1099593.stm#g |access-date=23 August 2011 |archive-date=15 February 2009 |archive-url=https://web.archive.org/web/20090215074832/http://news.bbc.co.uk/1/hi/programmes/radio_newsroom/1099593.stm#g |url-status=live |postscript=;}} {{Cite web |title=Key facts about the United Kingdom |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |archive-url=http://webarchive.nationalarchives.gov.uk/20121015000000/http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012517 |archive-date=15 October 2012 |access-date=8 March 2015 |website=Government, citizens and rights |publisher=HM Government}}</ref> It is sometimes used as a loose synonym for the United Kingdom as a whole.<ref>[[New Oxford American Dictionary]]: "Great Britain: England, Wales, and Scotland considered as a unit. The name is also often used loosely to refer to the United Kingdom."</ref> The word ''England'' is occasionally used incorrectly to refer to the United Kingdom as a whole, a mistake principally made by people from outside the UK.<ref>"When people say England, they sometimes mean Great Britain, sometimes the United Kingdom, sometimes the British Isles — but never England." — {{Citation |last=George Mikes |title=How To Be An Alien |year=1946 |publisher=Penguin}} {{ISBN|978-0-582-41686-4|postscript=;}} {{Cite web |title=England OR United Kingdom (UK)? {{!}} Vocabulary {{!}} EnglishClub |url=https://www.englishclub.com/vocabulary/cw-uk-england.htm |access-date=16 October 2022 |website=englishclub.com |archive-date=16 October 2022 |archive-url=https://web.archive.org/web/20221016192638/https://www.englishclub.com/vocabulary/cw-uk-england.htm |url-status=live}}</ref>
The term "Britain" is used as a synonym for [[Great Britain]],<ref>{{Cite web |title=Britain Meaning in the Cambridge English Dictionary |url=https://dictionary.cambridge.org/dictionary/english/britain |website=dictionary.cambridge.org |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024348/https://dictionary.cambridge.org/dictionary/english/britain |url-status=live |postscript=;}} {{Cite web |title=Definition of Britain in English by Oxford Dictionaries |url=https://en.oxforddictionaries.com/definition/britain |archive-url=https://web.archive.org/web/20160926204707/https://en.oxforddictionaries.com/definition/britain |archive-date=26 September 2016 |website=Oxford Dictionaries – English}}</ref><ref name="Britain-Col">{{Cite web |title=Britain definition and meaning |url=https://www.collinsdictionary.com/dictionary/english/britain |website=collinsdictionary.com |publisher=Collins English Dictionary |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024837/https://www.collinsdictionary.com/dictionary/english/britain |url-status=live}}</ref> but also sometimes for the United Kingdom.<ref>{{Cite web |title=Britain – Definition for English-Language Learners |url=http://learnersdictionary.com/definition/Britain |website=learnersdictionary.com |publisher=Merriam-Webster's Learner's Dictionary |access-date=19 June 2018 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620024648/http://learnersdictionary.com/definition/Britain |url-status=live}}</ref><ref name="Britain-Col" /> Usage is mixed: the [[style guide]] of the [[Government of the United Kingdom|UK Government]] prefers the term "UK" rather than "Britain" or "British" (except when referring to embassies{{Efn|"UK" embassies became "British" embassies in 1961.<ref>{{Cite news |date=21 October 1961 |title='Cold U.K.' Becomes British |work=[[The Times]] |page=8}}</ref>}}),<ref>{{Cite web |date=21 November 2024 |orig-date=23 February 2016 |title=Style guide: A to Z |url=https://www.gov.uk/guidance/style-guide/a-to-z |url-status=live |archive-url=https://web.archive.org/web/20241122222025/https://www.gov.uk/guidance/style-guide/a-to-z |archive-date=22 November 2024 |publisher=UK Government}}</ref> while other government documents acknowledge that both terms refer to the United Kingdom and that elsewhere "British government" is used at least as frequently as "United Kingdom government".<ref name="PCGN-uk-guide">{{Cite web |last=Permanent Committee on Geographical Names |title=Toponymic guidelines for the United Kingdom |url=https://www.gov.uk/government/publications/toponymic-guidelines |website=gov.uk |date=17 May 2023 |publisher=UK Government |access-date=17 June 2018 |archive-date=17 June 2018 |archive-url=https://web.archive.org/web/20180617165832/https://www.gov.uk/government/publications/toponymic-guidelines |url-status=live}}</ref> The UK [[Permanent Committee on Geographical Names for British Official Use|Permanent Committee on Geographical Names]] recognises "United Kingdom", "UK" and "U.K." as shortened and abbreviated geopolitical terms for the United Kingdom of Great Britain and Northern Ireland in its toponymic guidelines; it does not list "Britain" but notes that "it is only the one specific nominal term 'Great Britain' which invariably excludes Northern Ireland".<ref name="PCGN-uk-guide" /> The [[BBC]] historically preferred to use "Britain" as shorthand only for Great Britain, though the present style guide does not take a position except that "Great Britain" excludes Northern Ireland.<ref>{{Cite web |title=BBC News style guide – Names |url=https://www.bbc.co.uk/academy/en/articles/art20130702112133537 |archive-url=https://web.archive.org/web/20191110082858/https://www.bbc.co.uk/academy/en/articles/art20130702112133537 |archive-date=10 November 2019 |access-date=9 November 2019 |website=BBC Academy |publisher=BBC |postscript=;}} {{Cite web |title=Alphabetical checklist |url=https://www.bbc.co.uk/academy/journalism/news-style-guide/article/art20130702112133551 |archive-url=https://web.archive.org/web/20180326162901/http://www.bbc.co.uk/academy/journalism/news-style-guide/article/art20130702112133551 |archive-date=26 March 2018 |access-date=17 June 2018 |website=BBC News |publisher=BBC}}</ref>
The adjective "British" is commonly used to refer to matters relating to the United Kingdom and is used in law to refer to United Kingdom citizenship and [[British nationality law|nationality]].<ref>{{Cite book |last1=Bradley, Anthony Wilfred |url=https://books.google.com/books?id=HT_GS2zgN5QC&pg=PA36 |title=Constitutional and administrative law |last2=Ewing, Keith D. |publisher=Pearson Longman |year=2007 |isbn=978-1-4058-1207-8 |edition=14th |volume=1 |location=Harlow |page=36 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140723/https://books.google.com/books?id=HT_GS2zgN5QC&pg=PA36 |url-status=live}}</ref>{{Efn|Historically, the term ''British'' was used to refer to members and institutions within the British Empire and later Commonwealth and was not limited to the geographical British Isles. The UK Government adopted the term for its exclusive use only in 1961, but in recognition of its wider usage first sought the prior consent of Australia, Canada and New Zealand.<ref>{{Cite book |last1=Curran |first1=James |title=The Unknown Nation: Australia after Empire |last2=Ward |first2=Stuart |date=2010 |publisher=Melbourne University Publishing |isbn=978-0-522-85645-3 |location=Carlton, Vic |pages=26–7}}</ref><ref>{{Cite book |last=Ward |first=Stuart |title=Untied kingdom: A Global History of the End of Britain |date=2023 |publisher=Cambridge University Press |isbn=978-1-107-14599-3 |at=Chapter 1}}</ref>}} People of the United Kingdom use several different terms to describe their national identity and may identify themselves as being [[British people|British]], [[English people|English]], [[Scottish people|Scottish]], [[Welsh people|Welsh]], [[People of Northern Ireland|Northern Irish]] or [[Irish people|Irish]];<ref>{{Cite web |year=2010 |title=Which of these best describes the way you think of yourself? |url=http://www.ark.ac.uk/nilt/2010/Community_Relations/NINATID.html |access-date=1 July 2010 |website=Northern Ireland Life and Times Survey 2010 |publisher=ARK – Access Research Knowledge |archive-date=23 September 2015 |archive-url=https://web.archive.org/web/20150923175111/http://www.ark.ac.uk/nilt/2010/Community_Relations/NINATID.html |url-status=live}}</ref> or as having a combination of different national identities.<ref>{{Cite web |title=Ethnicity and National Identity in England and Wales |url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/ethnicity/articles/ethnicityandnationalidentityinenglandandwales/2012-12-11 |access-date=25 June 2020 |website=Office for National Statistics |archive-date=21 January 2022 |archive-url=https://web.archive.org/web/20220121012603/https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/ethnicity/articles/ethnicityandnationalidentityinenglandandwales/2012-12-11 |url-status=live |postscript=;}} {{Cite book |last=Schrijver, Frans |url=https://books.google.com/books?id=u8gZklxHTMUC&pg=PA275 |title=Regionalism after regionalisation: Spain, France and the United Kingdom |publisher=Amsterdam University Press |year=2006 |isbn=978-90-5629-428-1 |pages=275–277 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140905/https://books.google.com/books?id=u8gZklxHTMUC&pg=PA275#v=onepage&q&f=false |url-status=live}}</ref>
== History ==
{{Main|Formation of the United Kingdom of Great Britain and Northern Ireland|History of the British Isles}}
{{Further|History of the constitution of the United Kingdom|Timeline of British history}}
=== Prior to the Treaty of Union ===
{{Main|History of England|History of Wales|History of Scotland|History of Ireland}}
{{further|Kingdom of England|Kingdom of Scotland}}
[[File:Stonehenge2007 07 30.jpg|thumb|[[Stonehenge]] in [[Wiltshire]] is a ring of stones, each about {{Cvt|13|ft|0|order=flip}} high, {{Cvt|7|ft|0|order=flip}} wide and 25 [[tonne]]s, erected 2400–2200 BC.]]
Settlement by [[Cro-Magnon]]s of what is now the United Kingdom occurred in waves beginning by about 30,000 years ago.<ref>[http://news.bbc.co.uk/1/hi/wales/south_west/7069001.stm "Ancient skeleton was 'even older'] {{Webarchive|url=https://web.archive.org/web/20210213081240/http://news.bbc.co.uk/2/hi/uk_news/wales/south_west/7069001.stm |date=13 February 2021}}". [[BBC News]]. 30 October 2007. Retrieved 27 April 2011.</ref> The island has been continuously inhabited since the last retreat of ice around 11,500 years ago.<ref>{{Cite web |date=9 February 2018 |title=A 12,000-year story - revealing the history of settlers in Britain from the end of the Ice Age to the present day {{!}} University of Oxford |url=https://www.ox.ac.uk/news/2018-02-09-12000-year-story-revealing-history-settlers-britain-end-ice-age-present-day |access-date=6 July 2025 |website=ox.ac.uk |language=en }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref> By the end of the [[Prehistoric Britain|region's prehistoric period]], the population is thought to have belonged largely to a culture termed [[Insular Celts|Insular Celtic]], comprising [[Britons (historical)|Brittonic Britain]] and [[Gaelic Ireland]].<ref>{{Cite book |last=Koch, John T. |url=https://archive.org/details/celticculturehis00koch_128 |title=Celtic culture: A historical encyclopedia |publisher=ABC-CLIO |year=2006 |isbn=978-1-85109-440-0 |location=Santa Barbara, CA |page=[https://archive.org/details/celticculturehis00koch_128/page/n1016 973] |url-access=limited}}</ref>
The [[Roman conquest of Britain|Roman conquest]], beginning in AD 43, and the 400-year [[Roman Britain|rule of southern Britain]], was followed by an invasion by [[Germanic peoples|Germanic]] [[Anglo-Saxon]] settlers, reducing the Brittonic area mainly [[Wales#Post-Roman era|to what was to become Wales]], [[Cornwall]] and, until the latter stages of the Anglo-Saxon settlement, the [[Hen Ogledd]] (northern England and parts of southern Scotland).<ref>{{Cite book |title=[[Encyclopaedia of Wales|The Welsh Academy Encyclopaedia of Wales]] |publisher=University of Wales Press |year=2008 |isbn=978-0-7083-1953-6 |editor-last=Davies |editor-first=John |editor-link=John Davies (historian) |location=Cardiff |page=915 |editor-last2=Jenkins |editor-first2=Nigel |editor-link2=Nigel Jenkins |editor-last3=Baines |editor-first3=Menna |editor-last4=Lynch |editor-first4=Peredur I. |editor-link4=Peredur Lynch}}</ref> Most of the [[Anglo-Saxon England|region settled by the Anglo-Saxons]] became unified as the Kingdom of England in the 10th century.<ref>{{Cite magazine |title=Short Athelstan biography |url=https://www.bbc.co.uk/history/historic_figures/athelstan.shtml |magazine=BBC History |access-date=9 April 2013 |archive-date=13 February 2007 |archive-url=https://web.archive.org/web/20070213191353/http://www.bbc.co.uk/history/historic_figures/athelstan.shtml |url-status=live}}</ref> [[Dál Riata|Gaelic speakers in north-west Britain]] (with connections to the north-east of Ireland and traditionally supposed to have migrated from there in the 5th century)<ref>{{Cite book |last=Mackie, J.D. |url=https://archive.org/details/historyofscotlan00mack_0/page/18 |title=A History of Scotland |publisher=Penguin |year=1991 |isbn=978-0-14-013649-4 |location=London |pages=[https://archive.org/details/historyofscotlan00mack_0/page/18 18–19] |author-link=J.D. Mackie |postscript=;}} {{Cite book |last=Campbell |first=Ewan |title=Saints and Sea-kings: The First Kingdom of the Scots |publisher=Canongate |year=1999 |isbn=978-0-86241-874-8 |location=Edinburgh |pages=8–15}}</ref> united with the [[Picts]] to create the [[Kingdom of Scotland]] in the 9th century.<ref>{{Cite book |last=Haigh |first=Christopher |url=https://archive.org/details/cambridgehistori0000unse_a9n8/page/30 |title=The Cambridge Historical Encyclopedia of Great Britain and Ireland |publisher=Cambridge University Press |year=1990 |isbn=978-0-521-39552-6 |page=[https://archive.org/details/cambridgehistori0000unse_a9n8/page/30 30]}}</ref>
[[File:Roman Baths in Bath Spa, England - July 2006.jpg|alt=Photograph of the Baths showing a rectangular area of greenish water surrounded by yellow stone buildings with pillars. In the background is the tower of the abbey.|thumb|The [[Roman Baths (Bath)|Roman Baths]] in [[Bath, Somerset]], are a well-preserved ''[[thermae]]'' from [[Roman Britain]].]]
In 1066, the [[Normans]] invaded England from northern France. After [[Norman conquest of England|conquering England]] they seized [[Norman invasion of Wales|large parts of Wales]], [[Norman invasion of Ireland|conquered much of Ireland]] and were invited to settle in Scotland, bringing to each country [[feudalism]] on the Northern French model and [[Norman-French]] culture.<ref>{{Cite book |last=Ganshof, F.L. |url=https://archive.org/details/feudalism0000gans_j4b5 |title=Feudalism |publisher=University of Toronto |year=1996 |isbn=978-0-8020-7158-3 |page=165 |url-access=registration}}</ref> The [[Anglo-Normans|Anglo-Norman]] [[ruling class]] greatly influenced, but eventually assimilated with, the local cultures.<ref>{{Cite book |last=Chibnall, Marjorie |url=https://books.google.com/books?id=qJl5Jm-IndUC&pg=PA115 |title=The Debate on the Norman Conquest |publisher=Manchester University Press |year=1999 |isbn=978-0-7190-4913-2 |pages=115–122 |author-link=Marjorie Chibnall |access-date=20 March 2023 |archive-date=26 March 2023 |archive-url=https://web.archive.org/web/20230326164802/https://books.google.com/books?id=qJl5Jm-IndUC&pg=PA115 |url-status=live}}</ref> Subsequent [[House of Plantagenet|medieval English kings]] completed the [[conquest of Wales]] and tried unsuccessfully [[Wars of Scottish Independence|to annex Scotland]]. Asserting its independence in the 1320 [[Declaration of Arbroath]], Scotland maintained its independence thereafter, albeit in [[Anglo-Scottish Wars|near-constant conflict with England]].<ref>{{Cite web |date=3 June 2023 |title=The Declaration of Arbroath |url=https://www.nms.ac.uk/past-exhibitions/the-declaration-of-arbroath |access-date=6 July 2025 |website=NMS |language=en}}</ref>
In 1215, [[Magna Carta]] was the first document to state that no government was above the law and that citizens have rights protecting them.<ref>{{Cite web |title=Magna Carta |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/ |access-date=27 May 2024 |publisher=parliament.uk}} {{Cite web |title=The contents of Magna Carta |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/magnacartaclauses/ |access-date=27 May 2024 |publisher=parliament.uk |archive-date=28 August 2022 |archive-url=https://web.archive.org/web/20220828101448/https://www.parliament.uk/about/living-heritage/evolutionofparliament/originsofparliament/birthofparliament/overview/magnacarta/magnacartaclauses/ |url-status=live}} {{Cite web |title=Magna Carta Key Facts |url=https://www.britannica.com/summary/Magna-Carta-Key-Facts |access-date=27 May 2024 |publisher=Britannica |archive-date=27 May 2024 |archive-url=https://web.archive.org/web/20240527191804/https://www.britannica.com/summary/Magna-Carta-Key-Facts |url-status=live}}</ref>
The English monarchs, through inheritance of [[Angevin Empire|substantial territories in France]] and claims to the French crown, were also heavily involved in conflicts in France, most notably the [[Hundred Years' War]], while the [[List of Scottish monarchs|Kings of Scots]] were in [[Auld Alliance|an alliance with the French]] during this period.<ref>Keen, Maurice. [https://www.bbc.co.uk/history/british/middle_ages/hundred_years_war_01.shtml "The Hundred Years' War"] {{Webarchive|url=https://web.archive.org/web/20131214092949/http://www.bbc.co.uk/history/british/middle_ages/hundred_years_war_01.shtml |date=14 December 2013 }}. BBC History.</ref> [[Early modern Britain]] saw religious conflict resulting from the [[Reformation]] and the introduction of [[Protestant]] state churches in each country.<ref>[https://www.britannica.com/EBchecked/topic/479892/Protestantism/41558/The-Reformation-in-England-and-Scotland The Reformation in England and Scotland] {{Webarchive|url=https://web.archive.org/web/20150515015218/https://www.britannica.com/EBchecked/topic/479892/Protestantism/41558/The-Reformation-in-England-and-Scotland |date=15 May 2015 }} and [https://www.britannica.com/EBchecked/topic/293754/Ireland/22978/The-Reformation-period Ireland: The Reformation Period & Ireland under Elizabeth I] {{Webarchive|url=https://web.archive.org/web/20150521133445/http://www.britannica.com/EBchecked/topic/293754/Ireland/22978/The-Reformation-period |date=21 May 2015 }}, Encyclopædia Britannica Online.</ref> The [[English Reformation]] ushered in political, constitutional, social and cultural change in the 16th century and [[State religion|established]] the [[Church of England]]. It defined a national identity for England and slowly, but profoundly, changed people's religious beliefs.<ref>{{Cite web |title=English Reformation c1527-1590 |url=https://www.nationalarchives.gov.uk/education/resources/the-english-reformation-c1527-1590/ |access-date=20 January 2023 |website=The National Archives |archive-date=2 December 2022 |archive-url=https://web.archive.org/web/20221202002512/https://www.nationalarchives.gov.uk/education/resources/the-english-reformation-c1527-1590/ |url-status=live}}</ref> Wales was [[Laws in Wales Acts 1535 and 1542|fully incorporated into the Kingdom of England]],<ref>{{Cite magazine |date=5 November 2009 |title=British History in Depth – Wales under the Tudors |url=https://www.bbc.co.uk/history/british/tudors/wales_tudors_01.shtml |magazine=BBC History |access-date=21 September 2010 |archive-date=7 February 2012 |archive-url=https://web.archive.org/web/20120207145836/http://www.bbc.co.uk/history/british/tudors/wales_tudors_01.shtml |url-status=live}}</ref> and Ireland was constituted as a kingdom in personal union with the English crown.<ref>{{Cite book |last=Nicholls |first=Mark |url=https://archive.org/details/historyofmodernb0000nich |title=A history of the modern British Isles, 1529–1603: The two kingdoms |publisher=Blackwell |year=1999 |isbn=978-0-631-19334-0 |location=Oxford |pages=171–172 |url-access=registration}}</ref> During the [[Plantation of Ulster]] in the 17th century, the lands of the Catholic Gaelic nobility were confiscated by the Crown and granted to Protestant settlers from England and Scotland.<ref>{{Cite book |last=Canny |first=Nicholas P. |url=https://archive.org/details/makingirelandbri00cann |title=Making Ireland British, 1580–1650 |publisher=Oxford University Press |year=2003 |isbn=978-0-19-925905-2 |pages=189–200 |url-access=registration}}</ref>
[[File:Bayeux Tapestry WillelmDux.jpg|thumb|The [[Bayeux Tapestry]] depicts the [[Battle of Hastings]], 1066, and the events leading to it.]]
The [[Union of the Crowns]] occurred in 1603 when [[James VI of Scotland]] inherited the thrones of England and Ireland, subsequently moving his court from Edinburgh to London. Although unified under a single monarch, the three realms remained entirely separate political entities, preserving their respective parliaments, judicial systems, and established churches.<ref>Ross, D. (2002). ''[[iarchive:chronologyofscot0000ross|Chronology of Scottish History]]''. Glasgow: Geddes & Grosset. p. 56. {{ISBN|978-1-85534-380-1}}; Hearn, J. (2002). ''Claiming Scotland: National Identity and Liberal Culture''. Edinburgh University Press. p. 104. {{ISBN|978-1-902930-16-9}}.</ref>
In the mid-17th century, all three kingdoms [[Wars of the Three Kingdoms|were involved in a series of connected wars]] (including the [[English Civil War]]) which led to the temporary overthrow of the monarchy, with [[Execution of Charles I|the execution]] of [[Charles I of England|King Charles I]], and the establishment of the short-lived [[unitary republic]] of the [[Commonwealth of England]], Scotland and Ireland.<ref>{{Cite encyclopedia |title=English Civil Wars |encyclopedia=Encyclopædia Britannica |url=https://www.britannica.com/EBchecked/topic/187936/English-Civil-Wars |access-date=28 April 2013 |archive-date=2 May 2015 |archive-url=https://web.archive.org/web/20150502204708/https://www.britannica.com/EBchecked/topic/187936/English-Civil-Wars |url-status=live}}; {{Cite web |date=14 March 2010 |title=Scotland and the Commonwealth: 1651–1660 |url=http://www.archontology.org/nations/uk/scotland/01_laws.php |access-date=9 March 2015 |publisher=Archontology.org |archive-date=16 July 2012 |archive-url=https://web.archive.org/web/20120716194016/http://www.archontology.org/nations/uk/scotland/01_laws.php |url-status=live}}</ref>
Although the [[Restoration (1660)|monarchy was restored]], the [[Interregnum (1649–1660)|Interregnum]] along with the [[Glorious Revolution]] of 1688 and the subsequent [[Bill of Rights 1689]] in England and [[Claim of Right Act 1689]] in Scotland ensured that, unlike much of the rest of Europe, [[royal absolutism]] would not prevail, and a professed Catholic could never accede to the throne. The [[British constitution]] would develop on the basis of [[constitutional monarchy]] and the [[parliamentary system]].<ref>{{Cite book |last=Lodge |first=Richard |url=https://books.google.com/books?id=EBSpvBxGyqcC |title=The History of England – From the Restoration to the Death of William III (1660–1702) |publisher=Read Books |year=2007 |isbn=978-1-4067-0897-4 |page=8 |orig-date=1910 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328140723/https://books.google.com/books?id=EBSpvBxGyqcC |url-status=live}}</ref> With the founding of the [[Royal Society]] in 1660, science was greatly encouraged. During this period, particularly in England, the development of [[English navy|naval power]] and an interest in [[Age of Discovery|voyages of discovery]] led to the acquisition and settlement of overseas colonies, particularly in North America and the Caribbean.<ref>{{Cite web |title=Tudor Period and the Birth of a Regular Navy |url=http://www.royal-navy.org/lib/index.php?title=Tudor_Period_and_the_Birth_of_a_Regular_Navy_Part_Two |archive-url=https://web.archive.org/web/20111103013901/http://www.royal-navy.org/lib/index.php?title=Tudor_Period_and_the_Birth_of_a_Regular_Navy_Part_Two |archive-date=3 November 2011 |access-date=8 March 2015 |website=Royal Navy History |url-status=usurped |publisher=Institute of Naval History}}; {{Cite book |last=Canny |first=Nicholas |url=https://books.google.com/books?id=eQHSivGzEEMC |title=The Origins of Empire, The Oxford History of the British Empire Volume I |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924676-2 |ref=refOHBEv1 |access-date=29 September 2020 |archive-date=11 January 2023 |archive-url=https://web.archive.org/web/20230111135256/https://books.google.com/books?id=eQHSivGzEEMC |url-status=live}}</ref>
Though previous attempts at uniting the two kingdoms within Great Britain in 1606, 1667 and 1689 had proved unsuccessful, the attempt initiated in 1705 led to the [[Treaty of Union]] of 1706 being agreed and ratified by both parliaments.
{{Clear left}}
=== Union of England and Scotland ===
{{Main|Treaty of Union|Kingdom of Great Britain}}
[[File:Articles of Union between England and Scotland 28 Jan 1707.png|thumb|right|170px|The [[Treaty of Union]] which unified the [[Kingdom of England]] and [[Kingdom of Scotland]] on 1 May 1707]]
On 1 May 1707 the Kingdom of Great Britain was formed, the result of the [[Acts of Union 1707]] between the [[Kingdom of England]] and [[Kingdom of Scotland]].<ref>{{Cite web |title=Articles of Union with Scotland 1707 |url=http://www.nationalarchives.gov.uk/pathways/citizenship/rise_parliament/docs/articles_union.htm |access-date=19 October 2008 |publisher=UK Parliament |archive-date=8 June 2012 |archive-url=https://web.archive.org/web/20120608152446/http://www.nationalarchives.gov.uk/pathways/citizenship/rise_parliament/docs/articles_union.htm |url-status=live}}; {{Cite web |title=Acts of Union 1707 |url=http://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny |access-date=6 January 2011 |publisher=UK Parliament |archive-date=27 December 2010 |archive-url=https://web.archive.org/web/20101227033859/http://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny/ |url-status=live}}; {{Cite web |title=Treaty (act) of Union 1706 |url=http://www.scotshistoryonline.co.uk/union.html |archive-url=https://web.archive.org/web/20190527074630/http://www.scotshistoryonline.co.uk/union.html |archive-date=27 May 2019 |access-date=3 February 2011 |publisher=Scottish History online}}</ref> In the 18th century cabinet government developed under [[Robert Walpole]], who is considered the ''[[de facto]]'' first [[Prime Minister of the United Kingdom|prime minister]] from 1721 to 1742. A series of [[Jacobite uprisings]] sought to remove the Protestant [[House of Hanover]] from the throne and restore the Catholic [[House of Stuart]]. In 1746, the Jacobites were defeated at the [[Battle of Culloden]], after which the [[Scottish Highlanders]] were forcibly assimilated into Scotland by revoking the feudal independence of [[Scottish clan chief|clan chiefs]]. The British colonies in North America that broke away in the [[American Revolutionary War|American War of Independence]] became the [[United States]]. British imperial ambition turned towards Asia, particularly to [[British Raj|India]].<ref>Library of Congress, [https://books.google.com/books?id=BQDgr_XvsHoC&pg=PA73 ''The Impact of the American Revolution Abroad''] {{Webarchive|url=https://web.archive.org/web/20240328140724/https://books.google.com/books?id=BQDgr_XvsHoC&pg=PA73 |date=28 March 2024 }}, p. 73.</ref>
British merchants played a leading part in the [[Atlantic slave trade]], mainly between 1662 and 1807 when British or British-colonial [[slave ships]] transported nearly 3.3 million slaves from Africa.<ref>{{Cite book |last=Morgan |first=Kenneth |url=https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA12 |title=Slavery and the British Empire: From Africa to America |publisher=Oxford University Press, USA |year=2007 |isbn=978-0-19-156627-1 |page=12 |access-date=5 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141229/https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA12#v=onepage&q&f=false |url-status=live}}</ref> The slaves were taken to [[Plantation economy|work on plantations]], principally [[History of the British West Indies|in the Caribbean]] but also [[British America|in North America]].<ref>{{Cite book |last=Morgan |first=Kenneth |url=https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA15 |title=Slavery and the British Empire: From Africa to America |publisher=Oxford University Press, US |year=2007 |isbn=978-0-19-156627-1 |page=15 |access-date=5 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141229/https://books.google.com/books?id=SGcwgJz5rQMC&pg=PA15#v=onepage&q&f=false |url-status=live}}</ref> However, with pressure from the [[Abolitionism in the United Kingdom|abolitionist movement]], Parliament banned the trade in 1807, banned slavery in the British Empire in 1833, and Britain took a leading role in the movement to abolish slavery worldwide through the [[blockade of Africa]] and pressing other nations to end their trade with a series of treaties.<ref>[https://www.bbc.co.uk/devon/content/articles/2007/03/20/abolition_navy_feature.shtml Sailing against slavery] {{Webarchive|url=https://web.archive.org/web/20081103004954/https://www.bbc.co.uk/devon/content/articles/2007/03/20/abolition_navy_feature.shtml |date=3 November 2008 }}. BBC Devon. 2007.; {{Cite book |last=Lovejoy |first=Paul E. |url=https://archive.org/details/transformationsi0000love/page/290 |title=Transformations in Slavery: A History of Slavery in Africa |publisher=Cambridge University Press |year=2000 |isbn=978-0-521-78012-4 |edition=2nd |location=New York |page=[https://archive.org/details/transformationsi0000love/page/290 290]}}</ref>
=== United Kingdom of Great Britain and Ireland ===
{{Main|History of the United Kingdom|Acts of Union 1800|United Kingdom of Great Britain and Ireland}}
[[File:Victoria in her Coronation robes.jpg|upright|thumb|[[Queen Victoria|Victoria]] reigned as [[Monarchy of the United Kingdom|Queen of the United Kingdom]] and [[Empress of India]] during the 19th century.]]
In 1800, the parliaments of Great Britain and Ireland each passed an Act of Union, uniting the two kingdoms and creating the United Kingdom of Great Britain and Ireland on 1 January 1801.<ref>{{Cite web |title=The Act of Union |url=http://www.actofunion.ac.uk/actofunion.htm#act |archive-url=https://web.archive.org/web/20120415061235/http://www.actofunion.ac.uk/actofunion.htm#act |archive-date=15 April 2012 |access-date=15 May 2006 |publisher=Act of Union Virtual Library}}</ref>
After the defeat of France at the end of the [[French Revolutionary Wars]] and [[Napoleonic Wars]] (1792–1815), the United Kingdom emerged as the principal naval and imperial power (with London the [[List of largest cities throughout history|largest city in the world from about 1830]]).<ref>Tellier, L.-N. (2009). ''Urban World History: an Economic and Geographical Perspective''. Quebec: PUQ. p. 463. {{ISBN|978-2-7605-1588-8}}.</ref> [[History of the Royal Navy (after 1707)#Pax Britannica, 1815–1914|Unchallenged at sea]], British dominance was later described as the ''[[Pax Britannica]]'' ("British Peace"), a period of [[International relations of the Great Powers (1814–1919)|relative peace amongst the great powers]] (1815–1914) during which the British Empire became the global [[hegemon]]<ref>{{Cite book |last=Mathias |first=P. |title=The First Industrial Nation: the Economic History of Britain, 1700–1914 |publisher=Routledge |year=2001 |isbn=978-0-415-26672-7 |location=London}}; {{Cite book |last=Ferguson |first=Niall |url=https://archive.org/details/empire00nial |title=Empire: The rise and demise of the British world order and the lessons for global power |publisher=Basic Books |year=2004 |isbn=978-0-465-02328-8 |location=New York |url-access=registration}}</ref><ref>{{Cite encyclopedia |title=20th-century international relations |encyclopedia=[[Encyclopædia Britannica]] |url=https://www.britannica.com/topic/20th-century-international-relations-2085155 |access-date=6 May 2023 |last=McDougall |first=Walter A. |date=4 May 2023 |author-link=Walter A. McDougall |archive-url=https://web.archive.org/web/20190712124130/https://www.britannica.com/topic/20th-century-international-relations-2085155 |archive-date=12 July 2019 |url-status=live}}</ref> and adopted the role of [[global policeman]].<ref>Sondhaus, L. (2004). ''Navies in Modern World History''. London: Reaktion Books. p. 9. {{ISBN|978-1-86189-202-7}}.</ref><ref>{{Cite book |last=Porter |first=Andrew |url=https://books.google.com/books?id=oo3F2X8IDeEC |title=The Nineteenth Century, The Oxford History of the British Empire Volume III |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924678-6 |page=332 |ref=refOHBEv3}}</ref> From 1853 to 1856 Britain took part in the [[Crimean War]], allied with the [[Ottoman Empire]] against [[Russian Empire|Tsarist Russia]].<ref>{{Cite journal |last=Benn |first=David Wedgwood |title=The Crimean War and its lessons for today |journal=[[International Affairs (journal)|International Affairs]] |volume=88 |issue=2 |date=March 2012 |pages=387–391 |jstor=41428613 |publisher=Oxford University Press |doi=10.1111/j.1468-2346.2012.01078.x}}</ref> Following the [[Indian Rebellion of 1857]] the British government led by [[Henry John Temple, 3rd Viscount Palmerston|Lord Palmerston]] assumed [[direct rule]] over [[British Raj|India]]. Alongside the formal control it exerted over its own colonies, British dominance of much of world trade meant that it [[Informal empire|effectively controlled]] the economies of regions such as [[East Asia]] and [[Latin America]].<ref>{{Cite book |last=Porter |first=Andrew |url=https://books.google.com/books?id=oo3F2X8IDeEC |title=The Nineteenth Century, The Oxford History of the British Empire Volume III |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924678-6 |page=8 |ref=refOHBEv3}}; {{Cite book |last=Marshall |first=P.J. |url=https://books.google.com/books?id=S2EXN8JTwAEC |title=The Cambridge Illustrated History of the British Empire |publisher=Cambridge University Press |year=1996 |isbn=978-0-521-00254-7 |pages=156–157 |ref=refMarshall |access-date=29 September 2020 |archive-date=16 January 2023 |archive-url=https://web.archive.org/web/20230116094154/https://books.google.com/books?id=S2EXN8JTwAEC |url-status=live}}</ref>
Throughout the [[Victorian era]] (1837–1901) political attitudes favoured [[free trade]] and ''[[laissez-faire]]'' policies. Beginning with the [[Great Reform Act]] in 1832, Parliament gradually [[Reform Acts|widened the voting franchise]], with the [[Representation of the People Act 1884|1884 Reform Act]] championed by [[William Ewart Gladstone|William Gladstone]] granting [[suffrage]] to a majority of males for the first time. The British population increased at a dramatic rate, accompanied by rapid [[urbanisation]], causing significant social and economic stresses.<ref>{{Cite book |last=Tompson |first=Richard S. |url=https://books.google.com/books?id=H5kcJqmXk2oC&pg=PA63 |title=Great Britain: a reference guide from the Renaissance to the present |publisher=Facts on File |year=2003 |isbn=978-0-8160-4474-0 |location=New York |page=63}}</ref> By the late 19th century, [[Conservative Party (UK)|Conservative governments]] under [[Benjamin Disraeli]] and [[Robert Gascoyne-Cecil, 3rd Marquess of Salisbury|Lord Salisbury]] accelerated [[Scramble for Africa|imperial expansion in Africa]], sustained a foreign policy of "[[splendid isolation]]" from European alliances, and intensified strategic containment of the [[Russian Empire]] in [[Central Asia]], a competition known as the [[Great Game]].<ref>{{Cite journal |last=Fromkin |first=David |date=1980 |title=The Great Game in Asia |url=https://www.jstor.org/stable/20040512 |journal=Foreign Affairs |volume=58 |issue=4 |pages=936–951 |doi=10.2307/20040512 |jstor=20040512 |issn=0015-7120 |access-date=4 June 2023 |archive-date=12 April 2021 |archive-url=https://web.archive.org/web/20210412053528/https://www.jstor.org/stable/20040512 |url-status=live |url-access=subscription}}</ref> During this time, [[Canada]], [[Australia]] and [[New Zealand]] were granted self-governing [[dominion]] status.<ref>{{Cite book |last=Hosch, William L. |title=World War I: People, Politics, and Power |publisher=Britannica Educational Publishing |year=2009 |isbn=978-1-61530-048-8 |series=America at War |location=New York |page=21}}</ref> At the turn of the 20th century, Britain's industrial dominance became challenged by the [[German Empire]] and the [[United States]].<ref>{{Cite book |last=Zarembka |first=Paul |url=https://books.google.com/books?id=NSrwpggmHigC&pg=PP1 |title=Contradictions: Finance, Greed, and Labor Unequally Paid |date=2013 |publisher=Emerald Group Publishing |isbn=978-1-78190-670-5 |access-date=21 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141231/https://books.google.com/books?id=NSrwpggmHigC&pg=PP1#v=onepage&q&f=false |url-status=live}}</ref> The [[Edwardian era]] (1901–1910) saw [[Liberal welfare reforms|social reform]] and [[Irish Home Rule movement|home rule for Ireland]] become important domestic issues, while the [[Labour Party (UK)|Labour Party]] emerged from an alliance of [[Trade unions in the United Kingdom|trade unions]] and small socialist groups in 1900, and [[suffragettes]] campaigned for women's right to vote.<ref>Sophia A. Van Wingerden, ''The women's suffrage movement in Britain, 1866–1928'' (1999) ch 1.</ref>
=== World wars and partition of Ireland ===
{{Main|History of the United Kingdom during the First World War|Partition of Ireland|Interwar Britain|United Kingdom home front during the Second World War|Military history of the United Kingdom during World War II}}
[[File:Wreaths Are Laid at the Cenotaph, London During Remembrance Sunday Service MOD 45152052.jpg|thumb|Wreaths being laid during the [[Remembrance Sunday]] service at the [[The Cenotaph|Cenotaph]] in [[Whitehall]], London]]
[[File:Spitfire and Hurricane in the Battle of Britain Memorial Flight.jpg|thumb|A [[Supermarine Spitfire|Spitfire]] and a [[Hawker Hurricane|Hurricane]] as flown in the [[Battle of Britain]] during the [[Second World War]]]]
Britain was one of the principal [[Allies of World War I|Allies]] that defeated the [[Central Powers]] in the [[First World War]] (1914–1918). Alongside their French, Russian and (after 1917) American counterparts,<ref>Turner, John (1988). ''Britain and the First World War''. London: Unwin Hyman. pp. 22–35. {{ISBN|978-0-04-445109-9}}.</ref> British armed forces were engaged across much of the British Empire and in several regions of Europe, particularly on the [[Western Front (World War I)|Western Front]].<ref name="Westwell&Cove" /> The high fatalities of [[trench warfare]] caused the loss of much of a generation of men, with lasting social effects in the nation and a great disruption in the social order. Britain had suffered 2.5 million casualties and finished the war with a huge national debt.<ref name="Westwell&Cove">Westwell, I.; Cove, D. (eds) (2002). ''History of World War I, Volume 3''. London: Marshall Cavendish. pp. 698, 705. {{ISBN|978-0-7614-7231-5}}.</ref>
The consequences of the war persuaded the government to expand the right to vote in national and local elections to all adult men and most adult women with the [[Representation of the People Act 1918]].<ref name="Westwell&Cove" /> After the war Britain became a permanent member of the Executive Council of the [[League of Nations]] and received [[League of Nations mandate|a mandate]] over a number of former German and [[Ottoman Empire|Ottoman]] colonies. Under the leadership of [[David Lloyd George]], the British Empire reached its greatest extent, covering a fifth of the world's land surface and a quarter of its population.<ref>Turner, J. (1988). ''Britain and the First World War''. Abingdon: Routledge. p. 41. {{ISBN|978-0-04-445109-9}}.</ref>
By the mid-1920s most of the British population could listen to [[BBC]] radio programmes.<ref>{{Cite web |date=15 June 2020 |title=100 years of radio since Marconi's big breakthrough |url=https://www.ofcom.org.uk/about-ofcom/latest/features-and-news/100-years-of-radio |access-date=17 November 2020 |website=Ofcom |archive-date=4 August 2020 |archive-url=https://web.archive.org/web/20200804031332/https://www.ofcom.org.uk/about-ofcom/latest/features-and-news/100-years-of-radio |url-status=live}}</ref><ref>{{Cite web |title=History of the BBC: The origins of BBC Local Radio |url=https://www.bbc.com/historyofthebbc/research/local-radio |access-date=18 September 2022 |website=[[BBC]] |last=Linfoot |first=Matthew |archive-date=20 September 2022 |archive-url=https://web.archive.org/web/20220920232207/https://www.bbc.com/historyofthebbc/research/local-radio/ |url-status=live}}</ref> Experimental [[Television in the United Kingdom|television]] broadcasts [[History of television#United Kingdom|began in 1929]] and the [[First day of BBC television|first scheduled BBC Television Service]] commenced in 1936.<ref>{{Cite web |title=History of the BBC: 1920s |url=https://www.bbc.com/historyofthebbc/timelines/1920s |access-date=18 September 2022 |website=[[BBC]] |archive-date=26 September 2022 |archive-url=https://web.archive.org/web/20220926064808/https://www.bbc.com/historyofthebbc/timelines/1920s |url-status=live}}</ref> The rise of [[Irish nationalism]], and disputes within Ireland over the terms of [[Irish Home Rule]], led eventually to the [[Partition of Ireland|partition of the island]] in 1921.<ref>[[SR&O 1921]]/533 of 3 May 1921.</ref> [[The Troubles in Ulster (1920–1922)|A period of conflict in what is now Northern Ireland]] occurred from June 1920 until June 1922. The [[Irish Free State]] became independent, initially with [[Dominion]] status in 1922, and [[Statute of Westminster 1931#Irish Free State|unambiguously independent in 1931]]. Northern Ireland remained part of the United Kingdom.<ref>{{Cite web |title=The Anglo-Irish Treaty, 6 December 1921 |url=http://cain.ulst.ac.uk/issues/politics/docs/ait1921.htm |access-date=15 May 2006 |website=CAIN Web Service |archive-date=14 May 2012 |archive-url=https://web.archive.org/web/20120514145108/http://cain.ulst.ac.uk/issues/politics/docs/ait1921.htm |url-status=live}}</ref> The [[1928 Equal Franchise Act]] gave women electoral equality with men in national elections. Strikes in the mid-1920s culminated in the [[General Strike of 1926]]. Still suffering from the long-term economic effects of the First World War, Britain was severely impacted by the [[Great Depression in the United Kingdom|Great Depression]] (1929–1932), which intensified hardship in old industrial areas in traditional sectors, led to mass unemployment peaking near 3 million, and precipitated widespread political instability and social unrest. [[National Government (1931)|A coalition government]] was formed in 1931.<ref>Rubinstein, W.D. (2004). ''Capitalism, Culture, and Decline in Britain, 1750–1990''. Abingdon: Routledge. p. 11. {{ISBN|978-0-415-03719-8}}.</ref>
Nonetheless, Britain was described as "a very wealthy country, formidable in arms, ruthless in pursuit of its interests and sitting at the heart of a global production system."<ref name="Edgerton2012">{{Cite book |last=Edgerton |first=David |date=2012 |title=Britain's War Machine |url=https://www.penguin.co.uk/books/55731/britain-s-war-machine/9780141026107.html |access-date=10 May 2020 |publisher=Penguin |postscript=none |archive-date=28 April 2020 |archive-url=https://web.archive.org/web/20200428080558/https://www.penguin.co.uk/books/55731/britain-s-war-machine/9780141026107.html |url-status=live}}; {{Cite web |title=Britain's War Machine: Weapons, Resources and Experts in the Second World War |url=https://reviews.history.ac.uk/review/1114 |access-date=10 May 2020 |website=[[Reviews in History]] |archive-date=12 June 2020 |archive-url=https://web.archive.org/web/20200612173058/https://reviews.history.ac.uk/review/1114 |url-status=live}}</ref> After [[Nazi Germany]]'s [[invasion of Poland]] in 1939, Britain entered the [[Second World War]]. Despite the defeat of its European allies in the first year, Britain and its empire continued the war against Germany.<ref name="Edgerton2012" />
In 1940 the [[Royal Air Force]] successfully defended British airspace by repelling the German ''[[Luftwaffe]]'' in the [[Battle of Britain]]. Urban areas suffered heavy bombing during [[the Blitz]]. The [[Grand Alliance (World War II)|Grand Alliance]] of Britain, the United States and the [[Soviet Union]] formed in 1941, leading the [[Allies of World War II|Allies]] against the [[Axis powers]]. There were eventual hard-fought victories in the [[Battle of the Atlantic]], the [[North Africa campaign]] and the [[Italian campaign (World War II)|Italian campaign]]. British forces played important roles in the [[Normandy landings]] of 1944 and the [[liberation of Europe]]. The British Army led the [[Burma campaign]] against Japan, and the [[British Pacific Fleet]] fought Japan at sea. [[British contribution to the Manhattan Project|British scientists contributed]] to the American [[Manhattan Project]], whose task was to build a [[nuclear weapon]].<ref>{{cite book |author=Septimus H. Paul |url=https://books.google.com/books?id=fSZpgW-N628C&pg=PA1 |title=Nuclear Rivals: Anglo-American Atomic Relations, 1941–1952 |publisher=Ohio State U.P. |year=2000 |isbn=978-0-8142-0852-6 |pages=1–5}}</ref>
=== Post-war 20th century ===
{{Main|Post-war Britain (1945–1979)|Social history of post-war Britain (1945–1979)}}
[[File:British Empire 1921.png|thumb|right|upright=1.4|The [[British Empire]] at its territorial peak in 1921]]
The United Kingdom was one of the [[Big Three (World War II)|Big Three]] powers (with the United States and the Soviet Union) who met to plan the [[Aftermath of World War II|post-war world]];<ref>{{Cite book |last1=Doenecke |first1=Justus D. |url=https://books.google.com/books?id=xdMF9rX6mX8C&pg=PA62 |title=Debating Franklin D. Roosevelt's foreign policies, 1933–1945 |last2=Stoler |first2=Mark A. |year=2005 |publisher=Rowman & Littlefield |isbn=978-0-8476-9416-7 |access-date=19 March 2016 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141231/https://books.google.com/books?id=xdMF9rX6mX8C&pg=PA62#v=onepage&q&f=false |url-status=live|author-link=Justus Drew Doenecke}}; {{Cite book |last=Kelly |first=Brian |url=https://www.iup.edu/WorkArea/DownloadAsset.aspx?id=37681 |title=The Four Policemen and Postwar Planning, 1943–1945: The Collision of Realist and Idealist Perspectives |publisher=Indiana University of Pennsylvania |access-date=25 August 2015 |archive-date=22 October 2015 |archive-url=https://web.archive.org/web/20151022125442/https://www.iup.edu/WorkArea/DownloadAsset.aspx?id=37681 |url-status=live}}</ref> it drafted the [[Declaration by United Nations]] with the United States and became one of the five permanent members of the [[United Nations Security Council]]. It worked closely with the United States to establish the [[International Monetary Fund]], the [[World Bank]] and [[NATO]].<ref>{{Cite web |date=22 July 2010 |title=The "Special Relationship" between Great Britain and the United States Began with FDR |work=Roosevelt Institute |url=http://rooseveltinstitute.org/special-relationship-between-great-britain-and-united-states-began-fdr |archive-url=https://web.archive.org/web/20180125021103/http://rooseveltinstitute.org/special-relationship-between-great-britain-and-united-states-began-fdr |archive-date=25 January 2018 |access-date=24 January 2018 |quote=and the joint efforts of both powers to create a new post-war strategic and economic order through the drafting of the Atlantic Charter; the establishment of the International Monetary Fund and the World Bank; and the creation of the United Nations.}}; {{Cite press release |title=Remarks by the President Obama and Prime Minister Cameron in Joint Press Conference |date=22 April 2016 |publisher=The White House |url=https://obamawhitehouse.archives.gov/the-press-office/2016/04/22/remarks-president-obama-and-prime-minister-cameron-joint-press |quote=That's what we built after World War II. The United States and the UK designed a set of institutions – whether it was the United Nations, or the Bretton Woods structure, IMF, World Bank, NATO, across the board. |access-date=24 January 2018 |archive-date=8 June 2021 |archive-url=https://web.archive.org/web/20210608110653/https://obamawhitehouse.archives.gov/the-press-office/2016/04/22/remarks-president-obama-and-prime-minister-cameron-joint-press |url-status=live}}</ref> The war left the UK severely weakened and financially dependent on the American [[Marshall Plan]],<ref>{{Cite news |date=28 December 2006 |title=Britain to make its final payment on World War II loan from U.S. |work=The New York Times |url=https://www.nytimes.com/2006/12/28/business/worldbusiness/28iht-nazi.4042453.html |access-date=25 August 2011 |archive-date=20 August 2017 |archive-url=https://web.archive.org/web/20170820022220/http://www.nytimes.com/2006/12/28/business/worldbusiness/28iht-nazi.4042453.html |url-status=live}}</ref> but it was spared the total war that devastated [[eastern Europe]].<ref>{{Cite news |last=Reynolds |first=David |date=17 April 2011 |title=Britain's War Machine by David Edgerton – review |work=The Guardian |location=London |url=https://www.theguardian.com/books/2011/apr/17/britains-war-machine-david-edgerton-review |access-date=10 May 2020 |archive-date=12 June 2020 |archive-url=https://web.archive.org/web/20200612130213/https://www.theguardian.com/books/2011/apr/17/britains-war-machine-david-edgerton-review |url-status=live}}</ref>
In the immediate post-war years the [[Labour Government 1945–1951|Labour government]] under [[Clement Attlee]] initiated a radical programme of reforms, which significantly affected British society [[Post-war consensus|in the following decades]].<ref>{{Cite book |last=Francis |first=Martin |title=Ideas and policies under Labour, 1945–1951: Building a new Britain |publisher=Manchester University Press |year=1997 |isbn=978-0-7190-4833-3 |pages=225–233}}</ref> Major industries and public utilities were [[nationalised]], a [[welfare state]] was established, and a comprehensive, publicly funded healthcare system, the [[National Health Service]], was created.<ref>{{Cite book |last=Lee |first=Stephen J. |url=https://archive.org/details/aspectsbritishpo00lees |title=Aspects of British political history, 1914–1995 |publisher=Routledge |year=1996 |isbn=978-0-415-13103-2 |location=London; New York |pages=[https://archive.org/details/aspectsbritishpo00lees/page/n183 173]–199 |url-access=limited}}</ref> The rise of nationalism in the colonies coincided with Britain's much-diminished economic position after [[History of the United Kingdom during the First World War|its involvement in the First World War]] and [[Military history of the United Kingdom during World War II|in the Second World War]], so that a policy of [[decolonisation]] was unavoidable.<ref>{{cite book |last=Brown |first=Judith |author-link=Judith M. Brown |url=https://books.google.com/books?id=CpSvK3An3hwC |title=The Twentieth Century, The Oxford History of the British Empire Volume IV |publisher=Oxford University Press |year=1998 |isbn=978-0-19-924679-3 |ref=refOHBEv4 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20140103114315/http://books.google.com/books?id=CpSvK3An3hwC |archive-date=3 January 2014 |url-status=live}} p. 319.</ref><ref>{{cite book |last=Louis |first=Wm. Roger |url=https://books.google.com/books?id=NQnpQNKeKKAC |title=Ends of British Imperialism: The Scramble for Empire, Suez and Decolonization |publisher=I.B. Tauris |year=2006 |isbn=978-1-84511-347-6 |ref=refLouis2006 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20170222045215/https://books.google.com/books?id=NQnpQNKeKKAC |archive-date=22 February 2017 |url-status=live}} p. 337.</ref><ref>{{cite book |last=Abernethy |first=David |url=https://books.google.com/books?id=ennqNS1EOuMC |title=The Dynamics of Global Dominance, European Overseas Empires 1415–1980 |publisher=Yale University Press |year=2000 |isbn=978-0-300-09314-8 |ref=refAbernethy2000 |access-date=22 July 2009 |archive-url=https://web.archive.org/web/20111214082531/http://books.google.com/books?id=ennqNS1EOuMC |archive-date=14 December 2011 |url-status=live}} p. 146.</ref> Independence was granted to India and Pakistan in 1947.<ref>{{Cite book |last=Larres |first=Klaus |url=https://books.google.com/books?id=7D66_9YOof4C&pg=PA118 |title=A companion to Europe since 1945 |publisher=Wiley-Blackwell |year=2009 |isbn=978-1-4051-0612-2 |location=Chichester |page=118 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141350/https://books.google.com/books?id=7D66_9YOof4C&pg=PA118 |url-status=live}}</ref> Over the next three decades, most colonies of the British Empire gained their independence, and many became members of the [[Commonwealth of Nations]].<ref>{{Cite web |date=19 March 2009 |title=Country List |url=http://www.thecommonwealth.org/Templates/System/YearbookHomePage.asp?NodeID=152099&load=countrylist |archive-url=https://web.archive.org/web/20130506071236/http://www.thecommonwealth.org/Templates/System/YearbookHomePage.asp?NodeID=152099&load=countrylist |archive-date=6 May 2013 |access-date=8 March 2015 |publisher=[[Commonwealth Secretariat]]}}</ref>
The UK was the third country to develop [[Nuclear weapons and the United Kingdom|a nuclear weapons arsenal]], with its first atomic bomb test, [[Operation Hurricane]], in 1952, although the post-war limitations of Britain's international role were illustrated by the [[Suez Crisis]] of 1956. As a result of a shortage of workers in the 1950s, the government [[Modern immigration to the United Kingdom|encouraged immigration]] from [[Commonwealth countries]]. In the following decades the UK became a more [[Multiracialism|multiracial]] and [[Multiculturalism|multicultural]] society.<ref>{{Cite book |last=Julios |first=Christina |url=https://books.google.com/books?id=s3RQ4dsFEkoC&pg=PA84 |title=Contemporary British identity: English language, migrants, and public discourse |publisher=Ashgate |year=2008 |isbn=978-0-7546-7158-9 |series=Studies in migration and diaspora |location=Aldershot |page=84 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141350/https://books.google.com/books?id=s3RQ4dsFEkoC&pg=PA84 |url-status=live}}</ref> Despite rising living standards in the late 1950s and 1960s, the United Kingdom's economic performance was less successful than many of its main competitors such as France, [[West Germany]] and Japan. In 1969, the United Kingdom was the first democratic nation to [[Representation of the People Act 1969|lower its voting age to 18]].<ref>{{Cite journal |last1=Loughran |first1=Thomas |last2=Mycock |first2=Andrew |last3=Tonge |first3=Jonathan |date=3 April 2021 |title=A coming of age: how and why the UK became the first democracy to allow votes for 18-year-olds |url=https://www.tandfonline.com/doi/full/10.1080/13619462.2021.1890589 |journal=Contemporary British History |volume=35 |issue=2 |pages=284–313 |doi=10.1080/13619462.2021.1890589 |issn=1361-9462 |s2cid=233956982 |access-date=24 May 2024 |archive-date=4 June 2023 |archive-url=https://web.archive.org/web/20230604093606/https://www.tandfonline.com/doi/full/10.1080/13619462.2021.1890589 |url-status=live |url-access=subscription}}</ref>
In the decades-long process of [[European integration]] the UK was a founding member of the [[Western European Union]], established with the [[London and Paris Conferences]] in 1954. In 1960 the UK was one of the seven founding members of the [[European Free Trade Association]] (EFTA), but in 1973 it left to join the [[European Communities]] (EC). In a [[1975 United Kingdom European Communities membership referendum|1975 referendum]] 67 per cent voted to stay in it.<ref>{{Cite news |title=1975: UK embraces Europe in referendum |work=BBC News |url=http://news.bbc.co.uk/onthisday/hi/dates/stories/june/6/newsid_2499000/2499297.stm |access-date=8 March 2015 |archive-date=20 June 2018 |archive-url=https://web.archive.org/web/20180620044520/http://news.bbc.co.uk/onthisday/hi/dates/stories/june/6/newsid_2499000/2499297.stm |url-status=live}}</ref> When the EC became the [[European Union]] (EU) in 1993, the UK was one of the 12 founding member states.
From the late 1960s, Northern Ireland experienced communal and [[paramilitary]] violence, sometimes affecting other parts of the UK, known as [[the Troubles]]. It is usually considered to have ended with the 1998 [[Belfast Agreement|Belfast "Good Friday" Agreement]].<ref>{{Cite book |last=Aughey |first=Arthur |url=https://archive.org/details/politicsnorthern00augh |title=The Politics of Northern Ireland: Beyond the Belfast Agreement |publisher=Routledge |year=2005 |isbn=978-0-415-32788-6 |location=London |page=[https://archive.org/details/politicsnorthern00augh/page/n15 7] |url-access=limited}}; "The troubles were over, but the killing continued. Some of the heirs to Ireland's violent traditions refused to give up their inheritance." {{Cite book |last=Holland |first=Jack |url=https://archive.org/details/hopeagainsthisto00holl/page/221 |title=Hope against History: The Course of Conflict in Northern Ireland |publisher=Henry Holt |year=1999 |isbn=978-0-8050-6087-4 |location=New York |page=[https://archive.org/details/hopeagainsthisto00holl/page/221 221]}}; Elliot, Marianne (2007). ''The Long Road to Peace in Northern Ireland: Peace Lectures from the Institute of Irish Studies at Liverpool University.'' University of Liverpool Institute of Irish Studies, Liverpool University Press. p. 2. {{ISBN|978-1-84631-065-2}}.</ref> Following a period of widespread economic slowdown and industrial strife in the 1970s, the [[Conservative Party (UK)|Conservative]] government of the 1980s led by [[Margaret Thatcher]] initiated a radical policy of [[monetarism]], [[deregulation]], particularly of the financial sector (for example, the [[Big Bang (financial markets)|Big Bang]] in 1986) and labour markets, the sale of state-owned companies (privatisation), and the withdrawal of subsidies to others.<ref>{{Cite book |last=Dorey |first=Peter |title=British politics since 1945 |publisher=Blackwell |year=1995 |isbn=978-0-631-19075-2 |series=Making contemporary Britain |location=Oxford |pages=164–223}}</ref>
In 1982, [[Argentina]] invaded the British territories of [[South Georgia and the South Sandwich Islands|South Georgia]] and the [[Falkland Islands]], leading to the 10-week [[Falklands War]] in which Argentine forces were defeated. The inhabitants of the islands strongly favour British sovereignty, expressed in a [[2013 Falkland Islands sovereignty referendum|2013 referendum]]. From 1984 the British economy was helped by the inflow of substantial [[North Sea oil]] revenues.<ref>{{Cite book |last1=Griffiths, Alan |url=http://vig.pearsoned.co.uk/catalog/uploads/Griffiths_C01.pdf |title=Applied Economics |last2=Wall, Stuart |publisher=Financial Times Press |year=2007 |isbn=978-0-273-70822-3 |edition=11th |location=Harlow |page=6 |access-date=26 December 2010 |archive-date=23 August 2009 |archive-url=https://web.archive.org/web/20090823124048/http://vig.pearsoned.co.uk/catalog/uploads/Griffiths_C01.pdf |url-status=dead}}</ref> Another British Overseas Territory, [[Gibraltar]],<ref>{{cite wikisource |title=Peace and Friendship Treaty of Utrecht between Spain and Great Britain}}</ref> is [[Port of Gibraltar|a key military base]]; a [[2002 Gibraltar sovereignty referendum|referendum in 2002]] on shared sovereignty with Spain was rejected.
By the late 20th century, major changes were made to the governance of the UK with the establishment of [[devolution|devolved]] administrations for Scotland, Wales and Northern Ireland.<ref>{{Cite journal |last=Keating |first=Michael |date=1 January 1998 |title=Reforging the Union: Devolution and Constitutional Change in the United Kingdom |journal=Publius: The Journal of Federalism |volume=28 |issue=1 |pages=217–234 |doi=10.1093/oxfordjournals.pubjof.a029948}}</ref> [[Human Rights Act 1998|The statutory incorporation]] followed acceptance of the [[European Convention on Human Rights]]. The UK remained a [[List of modern great powers#United Kingdom|great power]] with global diplomatic and military influence and a leading role in the United Nations and NATO.<ref name="David M. McCourt">{{Cite book |last=McCourt |first=David |url=https://books.google.com/books?id=lwpOnwEACAAJ&q=Britain+and+World+Power+Since+1945:+Constructing+a+Nation%27s+Role+in+International+Politics |title=Britain and World Power Since 1945: Constructing a Nation's Role in International Politics |publisher=[[University of Michigan Press]] |year=2014 |isbn=978-0-472-07221-7 |access-date=21 October 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141741/https://books.google.com/books?id=lwpOnwEACAAJ&q=Britain+and+World+Power+Since+1945:+Constructing+a+Nation%27s+Role+in+International+Politics |url-status=live}}</ref>
=== 21st century ===
{{Main|Political history of the United Kingdom (1979–present)|Social history of the United Kingdom (1979–present)}}
[[File:Johnson signed Brexit Withdrawal Agreement.jpg|thumb|Prime Minister [[Boris Johnson]] signs the [[Brexit withdrawal agreement]] in 2020, formally [[Brexit|withdrawing the UK]] from the [[European Union]] (EU).]]
The United Kingdom broadly supported the United States' approach to the "[[war on terror]]" in the early 21st century.<ref>{{Cite news |last=McSmith |first=Andy |date=5 July 2016 |title=The inside story of how Tony Blair led Britain to war in Iraq |work=Independent |location=London |url=https://www.independent.co.uk/news/uk/politics/chilcot-report-iraq-war-inquiry-tony-blair-george-bush-us-uk-what-happened-a7119761.html |access-date=17 February 2022 |archive-date=4 July 2016 |archive-url=https://web.archive.org/web/20160704200931/https://www.independent.co.uk/news/uk/politics/chilcot-report-iraq-war-inquiry-tony-blair-george-bush-us-uk-what-happened-a7119761.html |url-status=live}}</ref> British troops fought in the [[War in Afghanistan (2001–2021)|war in Afghanistan]], but controversy surrounded Britain's [[Iraq War|military deployment in Iraq]], which saw the [[15 February 2003 anti-war protests|largest protest in British history]] in opposition to the government led by [[Tony Blair]].<ref>{{Cite news |last=Adams |first=Tim |date=11 February 2023 |title='A beautiful outpouring of rage': did Britain's biggest ever protest change the world? |work=The Observer |location=London |url=https://www.theguardian.com/uk-news/2023/feb/11/slugs-iraq-war-london-protest-2003-legacy |access-date=5 June 2023 |archive-date=6 April 2023 |archive-url=https://web.archive.org/web/20230406052000/https://www.theguardian.com/uk-news/2023/feb/11/slugs-iraq-war-london-protest-2003-legacy |url-status=live}}</ref>
The [[Great Recession]] (2007–2010) severely affected the British economy,<ref name="Latest UK GDP data">{{cite web |date=20 December 2013 |title=Quarterly National Accounts – National accounts aggregates (ABMI Gross Domestic Product: chained volume measures: Seasonally adjusted £m, constant prices) |url=http://www.ons.gov.uk/ons/datasets-and-tables/data-selector.html?cdid=ABMI&dataset=qna&table-id=A2 |publisher=Office for National Statistics |access-date=28 July 2023 |archive-date=29 September 2015 |archive-url=https://web.archive.org/web/20150929150429/http://www.ons.gov.uk/ons/datasets-and-tables/data-selector.html?cdid=ABMI&dataset=qna&table-id=A2 |url-status=live}}</ref> and was followed by a period of weak growth and stagnation.<ref>{{Cite web |last=Harari |first=Daniel |date=16 July 2024 |title=Low growth: The economy's biggest challenge |url=https://commonslibrary.parliament.uk/low-growth-the-economys-biggest-challenge/#:~: |access-date=16 April 2025 |website=House of Commons Library}}</ref><ref>{{Cite news |last1=Rees |first1=Tom |last2=Atkinson |first2=Andrew |last3=Aldrick |first3=Philip |date=12 March 2023 |title=A Lost Decade Worse Than Japan's Threatens to Change UK Forever |url=https://www.bloomberg.com/news/articles/2023-03-12/a-lost-decade-worse-than-japan-s-threatens-to-change-uk-forever |access-date=16 April 2025 |work=[[Bloomberg News]] |archive-date=13 March 2023 |archive-url=https://web.archive.org/web/20230313051724/https://www.bloomberg.com/news/articles/2023-03-12/a-lost-decade-worse-than-japan-s-threatens-to-change-uk-forever |url-status=live }}</ref> The [[Cameron–Clegg coalition]] government of 2010 introduced [[United Kingdom government austerity programme|austerity measures]] intended to tackle the substantial public deficits.<ref>{{Cite news |date=7 November 2022 |title=What is austerity and where could 'eye-watering' cuts fall now? |work=BBC News |url=https://www.bbc.com/news/63304224 |access-date=28 July 2023 |archive-date=28 July 2023 |archive-url=https://web.archive.org/web/20230728105646/https://www.bbc.com/news/63304224 |url-status=live}}</ref> [[2014 Scottish independence referendum|A referendum]] on [[Scottish independence]] in 2014 resulted in the Scottish electorate voting by 55.3 to 44.7 per cent to remain part of the United Kingdom.<ref>{{Cite web |title=Scottish independence referendum – Results |url=https://www.bbc.co.uk/news/events/scotland-decides/results |access-date=18 February 2022 |website=BBC News |archive-date=18 September 2014 |archive-url=https://web.archive.org/web/20140918212409/https://www.bbc.co.uk/news/events/scotland-decides/results |url-status=live}}</ref>
In 2016, 51.9 per cent of voters in the UK [[2016 United Kingdom European Union membership referendum|voted to leave the European Union]] (EU).<ref>{{Cite news |date=24 June 2016 |title=In stunning decision, Britain votes to leave the E.U. |newspaper=[[The Washington Post]] |url=https://www.washingtonpost.com/world/britons-head-to-the-polls-for-historic-vote-on-eu/2016/06/23/0d466fb0-34a7-11e6-ab9d-1da2b0f24f93_story.html |access-date=24 June 2016 |first1=Griff |last1=Witte |first2=Karla |last2=Adam |first3=Dan |last3=Balz |archive-date=30 November 2022 |archive-url=https://web.archive.org/web/20221130215030/https://www.washingtonpost.com/world/britons-head-to-the-polls-for-historic-vote-on-eu/2016/06/23/0d466fb0-34a7-11e6-ab9d-1da2b0f24f93_story.html |url-status=live}}</ref> The [[Brexit|UK left the EU]] in 2020.<ref>{{Cite news |date=1 January 2021 |title=Brexit: New era for UK as it completes separation from European Union |work=BBC News |url=https://www.bbc.com/news/uk-politics-55502781 |access-date=18 February 2022 |archive-date=14 January 2021 |archive-url=https://web.archive.org/web/20210114212309/https://www.bbc.com/news/uk-politics-55502781 |url-status=live}}</ref> On 1 May 2021 the [[EU–UK Trade and Cooperation Agreement]], a free trade agreement between the UK and the EU, came into force.<ref name="commission.europa.eu">{{Cite web |title=The EU-UK Trade and Cooperation Agreement |url=https://commission.europa.eu/strategy-and-policy/relations-non-eu-countries/relations-united-kingdom/eu-uk-trade-and-cooperation-agreement_en |archive-url=https://web.archive.org/web/20230325155905/https://commission.europa.eu/strategy-and-policy/relations-non-eu-countries/relations-united-kingdom/eu-uk-trade-and-cooperation-agreement_en |archive-date=25 March 2023 |access-date=25 March 2023}}</ref><ref>{{Cite web |access-date=12 September 2025 |title=Free Trade Agreements EU-UK |url=https://rtais.wto.org/UI/PublicShowRTAIDCard.aspx?rtaid=1137}}</ref>
The [[COVID-19 pandemic in the United Kingdom|COVID-19 pandemic]] had a severe [[Economic impact of the COVID-19 pandemic in the United Kingdom|impact on the British economy]], caused major [[Impact of the COVID-19 pandemic on education in the United Kingdom|disruptions to education]] and had [[Social impact of the COVID-19 pandemic in the United Kingdom|far-reaching impacts on society and politics]] in 2020 and 2021.<ref name="GOVUK">{{cite web |url=https://coronavirus.data.gov.uk/ |title=Coronavirus (COVID-19) in the UK |website=[[gov.uk]] |publisher=Government of the United Kingdom |access-date=15 April 2020 |archive-url=https://web.archive.org/web/20210501022145/https://coronavirus.data.gov.uk/ |archive-date=1 May 2021}}</ref><ref>{{Cite web |title=Coronavirus and the impact on output in the UK economy: April 2020 |url=https://www.ons.gov.uk/economy/grossdomesticproductgdp/articles/coronavirusandtheimpactonoutputintheukeconomy/april2020 |access-date=2 August 2020 |publisher=Government of the United Kingdom |website=ons.gov.uk |archive-date=2 August 2020 |archive-url=https://web.archive.org/web/20200802031859/https://www.ons.gov.uk/economy/grossdomesticproductgdp/articles/coronavirusandtheimpactonoutputintheukeconomy/april2020 |url-status=live}}</ref><ref>{{Cite news |last=Walker |first=Andrew |date=10 June 2020 |title=Coronavirus: UK economy could be among worst hit of leading nations, says OECD |work=BBC News |url=https://www.bbc.com/news/business-52991913 |access-date=2 August 2020 |archive-date=18 August 2020 |archive-url=https://web.archive.org/web/20200818031423/https://www.bbc.com/news/business-52991913 |url-status=live}}</ref> The United Kingdom was the first country in the world to use an approved [[COVID-19 vaccine]]. Developing a [[Oxford–AstraZeneca COVID-19 vaccine|vaccine in the UK]] allowed the rollout to be amongst the fastest in the world.<ref>{{Cite web |title=Landmark moment as first NHS patient receives COVID-19 vaccination |url=https://www.england.nhs.uk/2020/12/landmark-moment-as-first-nhs-patient-receives-covid-19-vaccination/ |archive-url=https://web.archive.org/web/20230225194320/https://www.england.nhs.uk/2020/12/landmark-moment-as-first-nhs-patient-receives-covid-19-vaccination/ |archive-date=25 February 2023 |website=NHS |date=8 December 2020}}</ref><ref>{{Cite web |title=Oxford University/AstraZeneca COVID-19 vaccine approved |url=https://www.gov.uk/government/news/oxford-universityastrazeneca-covid-19-vaccine-approved |archive-url=https://web.archive.org/web/20230225194442/https://www.gov.uk/government/news/oxford-universityastrazeneca-covid-19-vaccine-approved |archive-date=25 February 2023 |website=UK Government}}</ref>
== Geography ==
{{Main|Geography of the United Kingdom|Fauna of Great Britain|Flora of Great Britain and Ireland}}
[[File:MODIS - Great Britain and Northern Ireland - 2012-06-04 during heat wave (cropped).jpg|thumb|upright|A satellite image of the United Kingdom excluding [[Shetland]]]]
The total area of the United Kingdom is approximately {{Convert|244376|km2|sqmi|order=flip}},{{efn|name=ONSArea}}<ref name="ONS Standard Area Measurement" /> with a land area of {{convert|242741|km2|sqmi|order=flip}}.<ref name="ONS Standard Area Measurement" /> It occupies the major part of the [[British Isles]]<ref>[[Oxford English Dictionary]]: "British Isles: a geographical term for the islands comprising Great Britain and Ireland with all their offshore islands including the Isle of Man and the Channel Islands."</ref> and includes the island of Great Britain, the north-eastern one-sixth of the island of Ireland and [[List of islands of the United Kingdom|some smaller surrounding islands]], meaning it comprises [[England]], [[Scotland]], [[Wales]] and [[Northern Ireland]].<ref name="ONS Geography Guide">{{cite web |url=https://geoportal.statistics.gov.uk/datasets/d1f39e20edb940d58307a54d6e1045cd/about |title=A Beginner's Guide to UK Geography (2023) |author=<!--Not stated--> |date=4 February 2025 |website=Open Geography Portal |publisher=Office for National Statistics |access-date=14 May 2025}}</ref>
Geographically, the United Kingdom lies between the [[North Atlantic Ocean]] and the [[North Sea]] with the southeast coast coming within {{Convert|35|km|mi|0|order=flip}} of the coast of northern France, from which it is separated by the [[English Channel]].<ref name="factbook">{{Cite web |title=United Kingdom |url=https://www.cia.gov/the-world-factbook/countries/united-kingdom |access-date=21 January 2007 |website=[[The World Factbook]] |publisher=Central Intelligence Agency |archive-date=9 January 2021 |archive-url=https://web.archive.org/web/20210109221834/https://www.cia.gov/the-world-factbook/countries/united-kingdom |url-status=dead}}</ref>
The nearby island polities of the [[Isle of Man]], [[Jersey]] and [[Guernsey]] are [[Crown Dependencies]], in union with the [[Monarchy of the United Kingdom|British monarch]], but do not strictly form part of the United Kingdom or any of its three jurisdictions or four countries, although the British government retains responsibility for their external affairs. The Isle of Man lies roughly midway between Great Britain and the [[Ireland|island of Ireland]] in the [[Irish Sea]], while the Channel Islands lie just off the northern French coast.
The [[Royal Observatory, Greenwich|Royal Greenwich Observatory]] in London was chosen as the defining point of the [[Prime Meridian]]<ref>{{Cite web |last=ROG Learning Team |date=23 August 2002 |title=The Prime Meridian at Greenwich |url=http://www.rmg.co.uk/explore/astronomy-and-time/astronomy-facts/history/the-prime-meridian-at-greenwich |archive-url=https://web.archive.org/web/20151107023957/http://www.rmg.co.uk/explore/astronomy-and-time/astronomy-facts/history/the-prime-meridian-at-greenwich |archive-date=7 November 2015 |access-date=11 September 2012 |website=Royal Museums Greenwich}}</ref> at the [[International Meridian Conference]] in 1884.<ref>{{Cite news |date=13 August 2015 |title=Greenwich Royal Observatory: How the Prime Meridian line is actually 100 metres away from where it was believed to be |work=Independent |location=London |url=https://www.independent.co.uk/news/science/greenwich-royal-observatory-how-the-prime-meridian-line-is-actually-100-metres-away-from-where-it-10452386.html |access-date=13 December 2018 |archive-date=23 March 2019 |archive-url=https://web.archive.org/web/20190323081414/https://www.independent.co.uk/news/science/greenwich-royal-observatory-how-the-prime-meridian-line-is-actually-100-metres-away-from-where-it-10452386.html |url-status=live}}</ref>
The UK lies between latitudes [[49th parallel north|49°]] and [[61st parallel north|61° N]], and longitudes [[9th meridian west|9° W]] and [[2nd meridian east|2° E]]. Northern Ireland shares a {{Convert|499|km|mi|0|adj=on|order=flip}} land boundary with the Republic of Ireland<ref name="factbook" /> and has a {{Convert|650|km|mi|0|adj=on|order=flip}} coastline.<ref name="NI coastline">{{Cite web |title=Northern Ireland Coastal and Marine Forum |url=https://library2.nics.gov.uk/pdf/dard/2014/EEUD.pdf |archive-url=https://web.archive.org/web/20241123094028/https://library2.nics.gov.uk/pdf/dard/2014/EEUD.pdf |archive-date=23 November 2024 |access-date=13 March 2025 |publisher=Northern Ireland Coastal and Marine Forum}}</ref> The length of coastline of Great Britain plus its principal islands is about {{Convert|31368|km|mi|0|order=flip}} long, with the coastline of the main island Great Britain being {{Convert|17820|km|mi|0|order=flip}} of that,<ref name="UK coastline">{{Cite web |last=Darkes |first=Giles |date=January 2008 |title=How long is the UK coastline? |url=http://www.cartography.org.uk/default.asp?contentID=749 |archive-url=https://web.archive.org/web/20120522042745/http://www.cartography.org.uk/default.asp?contentID=749 |archive-date=22 May 2012 |access-date=24 January 2015 |publisher=The [[British Cartographic Society]]}}</ref> though measurements can vary greatly due to the [[coastline paradox]].<ref>{{Cite web |last=Weiner |first=Sophie |date=3 March 2018 |title=Why it's Impossible to Accurately Measure a Coastline |url=https://www.popularmechanics.com/science/environment/a19068718/why-its-impossible-to-accurately-measure-a-coastline/ |access-date=29 June 2024 |website=Popular Mechanics |archive-date=29 June 2024 |archive-url=https://web.archive.org/web/20240629025825/https://www.popularmechanics.com/science/environment/a19068718/why-its-impossible-to-accurately-measure-a-coastline/ |url-status=live}}</ref> It is connected to continental Europe by the [[Channel Tunnel]], which at {{Convert|50|km|mi|0|order=flip}} ({{Convert|38|km|mi|0|order=flip}} underwater) is the longest underwater tunnel in the world.<ref>{{Cite web |title=The Channel Tunnel |url=http://www.eurotunnel.com/ukcP3Main/ukcCorporate/ukcTunnelInfrastructure/ukcInfrastructure |archive-url=https://web.archive.org/web/20101218114514/http://www.eurotunnel.com/ukcP3Main/ukcCorporate/ukcTunnelInfrastructure/ukcInfrastructure |archive-date=18 December 2010 |access-date=8 March 2015 |publisher=Eurotunnel}}</ref>
The UK contains four terrestrial [[ecoregion]]s: [[Celtic broadleaf forests]], [[English Lowlands beech forests]], [[North Atlantic moist mixed forests]], and [[Caledonian Forest|Caledonian conifer forests]].<ref>{{Cite journal |last1=Dinerstein |first1=Eric |last2=Olson |first2=David |last3=Joshi |first3=Anup |last4=Vynne |first4=Carly |last5=Burgess |first5=Neil D. |last6=Wikramanayake |first6=Eric |last7=Hahn |first7=Nathan |last8=Palminteri |first8=Suzanne |last9=Hedao |first9=Prashant |last10=Noss |first10=Reed |last11=Hansen |first11=Matt |last12=Locke |first12=Harvey |last13=Ellis |first13=Erle C |last14=Jones |first14=Benjamin |last15=Barber |first15=Charles Victor |display-authors=1 |year=2017 |title=An Ecoregion-Based Approach to Protecting Half the Terrestrial Realm |journal=BioScience |volume=67 |issue=6 |pages=534–545 |doi=10.1093/biosci/bix014 |issn=0006-3568 |pmc=5451287 |pmid=28608869 |doi-access=free |last16=Hayes |first16=Randy |last17=Kormos |first17=Cyril |last18=Martin |first18=Vance |last19=Crist |first19=Eileen |last20=Sechrest |first20=Wes |last21=Price |first21=Lori |last22=Baillie |first22=Jonathan E. M. |last23=Weeden |first23=Don |last24=Suckling |first24=Kierán |last25=Davis |first25=Crystal |last26=Sizer |first26=Nigel |last27=Moore |first27=Rebecca |last28=Thau |first28=David |last29=Birch |first29=Tanya |last30=Potapov |first30=Peter |last31=Turubanova |first31=Svetlana |last32=Tyukavina |first32=Alexandra |last33=de Souza |first33=Nadia |last34=Pintea |first34=Lilian |last35=Brito |first35=José C. |last36=Llewellyn |first36=Othman A. |last37=Miller |first37=Anthony G. |last38=Patzelt |first38=Annette |last39=Ghazanfar |first39=Shahina A. |last40=Timberlake |first40=Jonathan |last41=Klöser |first41=Heinz |last42=Shennan-Farpón |first42=Yara |last43=Kindt |first43=Roeland |last44=Lillesø |first44=Jens-Peter Barnekow |last45=van Breugel |first45=Paulo |last46=Graudal |first46=Lars |last47=Voge |first47=Maianna |last48=Al-Shammari |first48=Khalaf F. |last49=Saleem |first49=Muhammad}}</ref> The area of woodland in the UK was estimated to be 3.25 million hectares in 2023, which represents 13 per cent of its land area.<ref>{{Cite web |url=https://www.forestresearch.gov.uk/tools-and-resources/statistics/statistics-by-topic/woodland-statistics/ |title=Woodland Statistics, Key findings |work=Forest Research |access-date=8 July 2023 |archive-date=2 August 2023 |archive-url=https://web.archive.org/web/20230802030149/https://www.forestresearch.gov.uk/tools-and-resources/statistics/statistics-by-topic/woodland-statistics/ |url-status=live}}</ref>
=== Climate ===
{{Main|Climate of the United Kingdom|Climate change in the United Kingdom}}
{{Further|Climate of England|Climate of Scotland|Climate of Wales|Climate of Northern Ireland}}
Most of the United Kingdom has a temperate climate, with generally cool temperatures and plentiful rainfall all year round.<ref name="factbook" /> The temperature varies with the seasons rarely dropping below {{Convert|0|C|lk=on}} or rising above {{Convert|30|C}}.<ref>{{Cite web |title=Hottest day of each year from 1900 |url=https://www.trevorharley.com/hottest-day-of-each-year-from-1900.html |website=trevorharley.com |access-date=23 November 2019 |archive-date=16 June 2023 |archive-url=https://web.archive.org/web/20230616173152/https://www.trevorharley.com/hottest-day-of-each-year-from-1900.html |url-status=live}}; {{Cite web |title=Coldest day of each year from 1900 |url=https://www.trevorharley.com/coldest-days-of-each-year-from-1900.html |website=trevorharley.com |access-date=23 November 2019 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709173537/https://www.trevorharley.com/coldest-days-of-each-year-from-1900.html |url-status=live}}</ref> Some parts, away from the coast, of upland England, Wales, Northern Ireland and most of Scotland, experience a [[subpolar oceanic climate]]. Higher elevations in Scotland experience a [[Subarctic climate|continental subarctic climate]] and the mountains experience a [[tundra climate]].<ref>{{Cite web |date=9 August 2016 |title=English: A map of Köppen climate types in the United Kingdom (SVG version) |url=https://commons.wikimedia.org/wiki/File:UK_K%C3%B6ppen.svg |access-date=23 November 2019 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709202702/https://commons.wikimedia.org/wiki/File:UK_K%C3%B6ppen.svg |url-status=live}}</ref>
The prevailing wind is from the southwest and bears frequent spells of mild and wet weather from the Atlantic Ocean,<ref name="factbook" /> although the eastern parts are mostly sheltered from this wind. Since the majority of the rain falls over the western regions, the eastern parts are the driest. Atlantic currents, warmed by the [[Gulf Stream]], bring mild winters, especially in the west where winters are wet and even more so over high ground. Summers are warmest in the southeast of England and coolest in the north. Heavy snowfall can occur in winter and early spring on high ground, and occasionally settles to great depth away from the hills.<ref>{{Cite web |title=Atlantic Ocean Circulation (Gulf Stream) |url=http://ukclimateprojections.metoffice.gov.uk/23152 |access-date=8 March 2015 |website=UK Climate Projections |publisher=Met Office |archive-date=17 October 2018 |archive-url=https://web.archive.org/web/20181017162552/http://ukclimateprojections.metoffice.gov.uk/23152 |url-status=live}}</ref>
The average total annual sunshine in the United Kingdom was 1,339.7 hours between 1971 and 2000.<ref name="ukaverages">{{cite web |title=UK 1971–2000 averages |url=http://www.metoffice.gov.uk/climate/uk/averages/19712000/areal/uk.html |url-status=dead |archive-url=https://web.archive.org/web/20090705140124/http://www.metoffice.gov.uk/climate/uk/averages/19712000/areal/uk.html |archive-date=5 July 2009 |access-date=4 August 2007 |publisher=Met Office}}</ref> The hours of sunshine vary from 1,200 to about 1,580 hours per year.<ref name="met off climate series">{{Cite web |url=https://www.metoffice.gov.uk/research/climate/maps-and-data/uk-temperature-rainfall-and-sunshine-time-series |title=UK temperature, rainfall and sunshine time series |website=Met Office |access-date=31 December 2022 |archive-date=17 October 2019 |archive-url=https://web.archive.org/web/20191017203556/https://www.metoffice.gov.uk/research/climate/maps-and-data/uk-temperature-rainfall-and-sunshine-time-series |url-status=live}}</ref>
Climate change has serious impacts on the country. A third of food price rise in 2023 was attributed to it.<ref>{{cite web |last1=Smeeton |first1=George |title=Families hit by £605 food bill as extreme weather and energy crisis bites |url=https://eciu.net/media/press-releases/2023/families-hit-by-605-food-bill-as-extreme-weather-and-energy-crisis-bites |website=Energy & Climate Intelligence Unit |date=28 November 2023 |access-date=19 July 2024 |archive-date=16 July 2024 |archive-url=https://web.archive.org/web/20240716124143/https://eciu.net/media/press-releases/2023/families-hit-by-605-food-bill-as-extreme-weather-and-energy-crisis-bites |url-status=live}}</ref> In 2024 the United Kingdom ranked 5th out of 180 countries in the [[Environmental Performance Index]].<ref>{{Cite web |title=2024 Environmental Performance Index |url=https://epi.yale.edu/measure/2024/EPI |access-date=27 May 2025 |website=Environmental Performance Index |language=en |archive-date=10 July 2024 |archive-url=https://web.archive.org/web/20240710023935/https://epi.yale.edu/measure/2024/EPI |url-status=live }}</ref> A law has been passed that [[Greenhouse gas emissions by the United Kingdom|UK greenhouse gas emissions]] will be [[net zero]] by 2050.<ref>{{Cite web |title=UK net zero target |url=https://www.instituteforgovernment.org.uk/explainers/net-zero-target#:~:text=In%20June%202019%2C%20parliament%20passed,to%201990%20levels%20by%202050.&text=Prior%20to%20this%2C%20the%20UK,1990%20levels%2C%20also%20by%202050. |access-date=20 March 2024 |website=Institute for Government |date=20 April 2020|last=Shepheard|first=Marcus}}</ref>{{Update after|2050|01|01|category|reason=Hello from 2024! By the time you're reading this, that law will be a little older than 30 years old. Could you check if the UK ever ended up hitting that net zero GHG target?}}
=== Topography ===
[[File:uk topo en.jpg|thumb|right|The United Kingdom's topography]]
[[Geography of England|England]] accounts for 53 per cent of the UK, covering {{Convert|130395|km2|sqmi|order=flip|-1}}.<ref>{{Cite news |date=11 February 2010 |title=England – Profile |work=BBC News |url=http://news.bbc.co.uk/2/hi/europe/country_profiles/7327029.stm |access-date=9 October 2010 |archive-date=15 April 2018 |archive-url=https://web.archive.org/web/20180415064122/http://news.bbc.co.uk/1/hi/world/europe/country_profiles/7327029.stm |url-status=live}}</ref> Most of the country consists of lowland terrain,<ref name="Atlapedia">{{Cite web |last=Latimer Clarke Corporation Pty Ltd |title=United Kingdom – Atlapedia Online |url=http://www.atlapedia.com/online/countries/unitedki.htm |access-date=26 October 2010 |website=Atlapedia.com |archive-date=21 March 2012 |archive-url=https://web.archive.org/web/20120321191308/http://www.atlapedia.com/online/countries/unitedki.htm |url-status=live}}{{better source needed|date=July 2023}}</ref> with upland and mountainous terrain northwest of the [[Tees–Exe line]] which roughly divides the UK into [[lowland and upland]] areas. Lowland areas include [[Cornwall]], the [[New Forest]], the [[South Downs]] and the [[The Broads|Norfolk Broads]]. Upland areas include the [[Lake District]], the [[Pennines]], the [[Yorkshire Dales]], [[Exmoor]] and [[Dartmoor]]. The main rivers and estuaries are the [[River Thames|Thames]], [[River Severn|Severn]], and the [[Humber]]. England's highest mountain is [[Scafell Pike]], at {{Convert|978|m|ft|0}} in the Lake District; its largest island is the [[Isle of Wight]].
[[Geography of Scotland|Scotland]] accounts for 32 per cent of the UK, covering {{Convert|78772|km2|sqmi|order=flip|-1}}.<ref>{{Cite web |title=Scotland Facts |url=http://www.scotland.org/about/fact-file/index.html |archive-url=https://web.archive.org/web/20080621045248/http://www.scotland.org/about/fact-file/index.html |archive-date=21 June 2008 |access-date=16 July 2008 |publisher=Scotland Online Gateway}}</ref> This includes [[List of islands of Scotland|nearly 800 islands]],<ref>{{Cite news |last=Winter |first=Jon |date=1 June 2000 |title=The complete guide to the ... Scottish Islands |work=Independent |location=London |url=https://www.independent.co.uk/travel/uk/the-complete-guide-to-the--scottish-islands-633851.html |access-date=8 March 2015 |archive-date=2 April 2015 |archive-url=https://web.archive.org/web/20150402164423/http://www.independent.co.uk/travel/uk/the-complete-guide-to-the--scottish-islands-633851.html |url-status=live}}</ref> notably the [[Hebrides]], [[Orkney]] Islands and [[Shetland Islands]]. Scotland is the most mountainous constituent country of the UK. The [[Scottish Highlands|Highlands]] to the north and west are the more rugged region containing the majority of Scotland's mountainous land, including the [[Cairngorms]], [[Loch Lomond and The Trossachs]] and [[Ben Nevis]] which at {{Convert|1345|m|ft|0}}<ref>{{Cite web |date=18 March 2016 |title=Great Britain's tallest mountain is taller |work=Ordnance Survey Blog |url=https://www.ordnancesurvey.co.uk/blog/2016/03/britains-tallest-mountain-is-taller |access-date=9 September 2018 |publisher=Ordnance Survey |archive-date=9 September 2018 |archive-url=https://web.archive.org/web/20180909000504/https://www.ordnancesurvey.co.uk/blog/2016/03/britains-tallest-mountain-is-taller/ |url-status=live}}</ref> is the highest point in the British Isles.<ref>{{Cite web |title=Ben Nevis Weather |url=http://www.bennevisweather.co.uk/index.asp |archive-url=https://web.archive.org/web/20120510193022/http://www.bennevisweather.co.uk/index.asp |archive-date=10 May 2012 |access-date=26 October 2008 |publisher=Ben Nevis Weather}}</ref>
[[Geography of Wales|Wales]] accounts for less than 9 per cent of the UK, covering {{Convert|20779|km2|sqmi|order=flip|-1}}.<ref>{{Cite news |date=9 June 2010 |title=Profile: Wales |work=BBC News |url=http://news.bbc.co.uk/2/hi/europe/country_profiles/6233450.stm |access-date=7 November 2010 |archive-date=26 August 2018 |archive-url=https://web.archive.org/web/20180826085704/http://news.bbc.co.uk/2/hi/europe/country_profiles/6233450.stm |url-status=live}}</ref> It is mostly mountainous, though [[South Wales]] is less mountainous than [[North Wales|North]] and [[Mid Wales]]. The highest mountains in Wales are in [[Snowdonia]] and include [[Snowdon]] ({{Langx|cy|Yr Wyddfa}}) which, at {{Convert|1085|m|ft|0}}, is the highest peak in Wales.<ref name="Atlapedia" /> Wales has over {{Convert|1680|mi|0|abbr=off}} of coastline including the [[Pembrokeshire Coast]].<ref name="UK coastline" /> Several islands lie off the Welsh mainland, the largest of which is [[Anglesey]] (''Ynys Môn'').
[[Geography of Ireland|Northern Ireland]], separated from Great Britain by the [[Irish Sea]] and [[North Channel (Great Britain and Ireland)|North Channel]], has an area of {{Convert|14160|km2|sqmi|order=flip|-1}} and is mostly hilly. It includes [[Lough Neagh]] which, at {{Convert|388|km2|sqmi|order=flip|0}}, is the largest lake in the British Isles by area,<ref>{{Cite web |title=Geography of Northern Ireland |url=http://cain.ulst.ac.uk/ni/geog.htm |access-date=22 May 2006 |publisher=University of Ulster |archive-date=18 January 2012 |archive-url=https://web.archive.org/web/20120118133131/http://cain.ulst.ac.uk/ni/geog.htm |url-status=live}}</ref> [[Lough Erne]], which has over 150 islands, and the [[Giant's Causeway]], which is listed by [[UNESCO]] as a [[World Heritage Site]]. The highest peak in Northern Ireland is [[Slieve Donard]] in the [[Mourne Mountains]] at {{Convert|852|m|ft|0}}.<ref name="Atlapedia" />
== Government and politics ==
{{Main|Politics of the United Kingdom|Government of the United Kingdom|Monarchy of the United Kingdom}}
{{Further|Constitution of the United Kingdom}}{{Multiple image
| direction = horizontal
| align = right
| caption_align = center
| total_width = 320
| image1 = King Charles III (July 2023).jpg
| image2 = Prime Minister Andy Burnham portrait (cropped).jpg
| caption1 = {{nowrap|[[Charles III]]}}<br>[[Monarch of the United Kingdom|King]]
| caption2 = {{nowrap|[[Andy Burnham]]}}<br>{{nowrap|[[Prime Minister of the United Kingdom|Prime Minister]]}}
| alt1 =
| alt2 =
}}
The United Kingdom is a [[constitutional monarchy]] and a [[parliamentary democracy]]<ref>[http://www.royal.gov.uk/MonarchUK/HowtheMonarchyworks/Whatisconstitutionalmonarchy.aspx The British Monarchy, "What is constitutional monarchy?"] {{Webarchive|url=https://web.archive.org/web/20190604151257/http://www.royal.gov.uk/MonarchUK/HowtheMonarchyworks/Whatisconstitutionalmonarchy.aspx|date=4 June 2019}}. Retrieved 17 July 2013; [https://www.cia.gov/the-world-factbook/countries/united-kingdom/ "United Kingdom"] {{Webarchive|url=https://web.archive.org/web/20210109221834/https://www.cia.gov/the-world-factbook/countries/united-kingdom/|date=9 January 2021}} CIA ''The World Factbook''. Retrieved 17 July 2013</ref> operating under the [[Westminster system]], otherwise known as a "democratic parliamentary monarchy".<ref>{{Cite journal |last1=Stepan |first1=Alfred |last2=Linz |first2=Juan J. |last3=Minoves |first3=Juli F. |date=2014 |title=Democratic Parliamentary Monarchies |url=http://muse.jhu.edu/content/crossref/journals/journal_of_democracy/v025/25.2.stepan.html |journal=Journal of Democracy |volume=25 |issue=2 |pages=35–36 |doi=10.1353/jod.2014.0032 |issn=1086-3214 |s2cid=154555066 |url-access=subscription |archive-date=31 January 2026 |access-date=11 January 2023 |archive-url=https://web.archive.org/web/20260131155632/https://muse.jhu.edu/content/crossref/journals/journal_of_democracy/v025/25.2.stepan.html |url-status=live }}</ref> It is a [[Centralized government|centralised]], [[unitary state]]<ref>{{Cite web |last=Lewer |first=Andrew |date=5 May 2021 |title=The UK is one of the most centralised advanced democracies – it's time that changed |url=https://www.newstatesman.com/spotlight/2021/05/the-uk-is-one-of-the-most-centralised-advanced-democracies-its-time-that-changed |access-date=3 July 2023 |website=[[New Statesman]] |archive-date=3 July 2023 |archive-url=https://web.archive.org/web/20230703131907/https://www.newstatesman.com/spotlight/2021/05/the-uk-is-one-of-the-most-centralised-advanced-democracies-its-time-that-changed |url-status=live|author-link=Andrew Lewer}}</ref><ref>{{Cite web |title=Centralisation Nation: Britain's system of local government and its impact on the national economy |url=https://www.centreforcities.org/?post_type=publication&p=40951 |access-date=3 July 2023 |website=Centre for Cities |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141833/https://www.centreforcities.org/publication/centralisation-nation/ |url-status=live}}</ref> wherein the [[Parliament of the United Kingdom]] is [[Parliamentary sovereignty in the United Kingdom|sovereign]].<ref>{{Cite web |title=Parliamentary Sovereignty |url=https://www.parliament.uk/site-information/glossary/parliamentary-sovereignty |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=11 August 2021 |archive-url=https://web.archive.org/web/20210811195135/https://www.parliament.uk/site-information/glossary/parliamentary-sovereignty/ |url-status=live}}</ref> Parliament is made up of the elected [[House of Commons of the United Kingdom|House of Commons]], the appointed [[House of Lords]] and [[the Crown]] (as personified by [[Monarchy of the United Kingdom|the monarch]]).{{Efn|British [[sovereignty]] derives from the Crown, a [[corporation sole]] occupied by the monarch. It is therefore by and through the monarch that Parliament exercises supreme legislative authority over both the executive and judiciary. Distinguished Professor of [[Public Law]] Maurice Sunkin opined the Crown symbolically occupies "...what in other places would be a core element of a written constitution."<ref>{{Cite web |url=https://www.ibanet.org/Relationship-between-UK-Crown-and-law-in-focus-as-Carolean-era-begins |title=Relationship between UK Crown and law in focus as Carolean era begins |author=Polly Botsford |publisher=International Bar Association |publication-date=22 September 2022 |access-date=4 July 2023 |archive-date=6 May 2023 |archive-url=https://web.archive.org/web/20230506211218/https://www.ibanet.org/Relationship-between-UK-Crown-and-law-in-focus-as-Carolean-era-begins |url-status=live}}</ref> As a result of this state of constitutional affairs, the monarch is formally referred to as "[[Sovereign|the Sovereign]]" in legislation.<ref>{{Cite web |url=https://www.legislation.gov.uk/ukpga/1978/30/section/10 |title=Interpretation Act 1978 (c. 30, s. 10) |publisher=The National Archives |access-date=4 July 2023 |archive-date=30 July 2023 |archive-url=https://web.archive.org/web/20230730073659/https://www.legislation.gov.uk/ukpga/1978/30/section/10 |url-status=live}}</ref>}}<ref name="parliament.uk">{{Cite web |title=Parliament |url=https://www.parliament.uk/about/how/role |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=18 February 2026 |archive-url=https://web.archive.org/web/20260218150954/https://www.parliament.uk/about/how/role/ |url-status=live }}</ref> The main business of Parliament takes place in the two houses,<ref name="parliament.uk" /> but [[royal assent]] is required for a bill to become an [[Act of Parliament (UK)|act of Parliament]] (that is, [[statute law]]).<ref>{{Cite web |title=Royal Assent |url=https://www.parliament.uk/about/how/laws/passage-bill/lords/lrds-royal-assent |access-date=19 July 2021 |website=[[parliament.uk]] |archive-date=16 July 2021 |archive-url=https://web.archive.org/web/20210716022947/https://www.parliament.uk/about/how/laws/passage-bill/lords/lrds-royal-assent/ |url-status=live}}</ref> As a result of parliamentary sovereignty, the [[Constitution of the United Kingdom|British constitution]] is [[Uncodified constitution|uncodified]], consisting mostly of disparate written sources, including parliamentary [[statute]]s, judge-made [[case law]] and international treaties, together with [[British Constitution#Conventions|constitutional conventions]].<ref>{{Cite web |last=Carter, Sarah |title=A Guide To the UK Legal System |url=http://www.llrx.com/features/uk2.htm#UK%20Legal%20System |archive-url=https://web.archive.org/web/20120505115306/http://www.llrx.com/features/uk2.htm |archive-date=5 May 2012 |access-date=16 May 2006 |publisher=[[University of Kent]] at Canterbury}}</ref> Nevertheless, the [[Supreme Court of the United Kingdom|Supreme Court]] recognises a number of principles underlying the British constitution, such as parliamentary sovereignty, the [[rule of law]], [[democracy]] and upholding [[Internationalism (politics)|international law]].<ref>See ''[[R (Miller) v Prime Minister]]'' [2019] UKSC 41 (Parliamentary sovereignty), ''[[R (UNISON) v Lord Chancellor]]'' [2017] [http://www.bailii.org/uk/cases/UKSC/2017/51.html UKSC 51] {{Webarchive|url=https://web.archive.org/web/20230104095357/https://www.bailii.org/uk/cases/UKSC/2017/51.html|date=4 January 2023}}, [67] ff (rule of law), ''[[R (Animal Defenders International) v Secretary of State for Culture Media and Sport]]'' [2008] UKHL 15, [48] (democracy), ''[[R v Lyons]]'' [2002] [https://www.bailii.org/uk/cases/UKHL/2002/44.html UKHL 44] {{Webarchive|url=https://web.archive.org/web/20230122064021/https://www.bailii.org/uk/cases/UKHL/2002/44.html|date=22 January 2023}}, [27] (international law).</ref>
[[Charles III|King Charles III]] is the [[monarch]] and [[head of state]] of the United Kingdom and 14 other independent [[sovereign state]]s, referred to as "[[Commonwealth realm]]s". The monarch is formally vested with all executive authority as the personal embodiment of [[the Crown]] and is "fundamental to the law and working of government in the UK".<ref>{{Cite journal |url=https://kclpure.kcl.ac.uk/portal/en/publications/the-constitutional-role-and-working-of-the-monarchy-in-the-united |title=The Constitutional Role and Working of the Monarchy in the United Kingdom |author=Robert Blackburn |journal=Jahrbuch des Öffentlichen Rechts der Gegenwart |series=Neue Folge |year=2022 |volume=70 |pages=181–201 |editor=O. Lepsius |editor2=A. Nußberger |editor3=C. Schönberger |editor4=C. Waldhoff |editor5=C. Walter |name-list-style=amp |publisher=Mohr Siebeck |doi=10.1628/joer-2022-0009 |s2cid=257830288 |publication-date=2 June 2022 |access-date=19 June 2023 |archive-date=19 June 2023 |archive-url=https://web.archive.org/web/20230619174428/https://kclpure.kcl.ac.uk/portal/en/publications/the-constitutional-role-and-working-of-the-monarchy-in-the-united |url-status=live}}</ref> The disposition of such powers however, including those belonging to the [[Royal prerogative in the United Kingdom|royal prerogative]], is generally exercised only on the [[Advice (constitutional law)|advice]] of [[ministers of the Crown]] responsible to Parliament and thence to the electorate. Nevertheless, in the performance of official duties the monarch has "the right to be consulted, the right to encourage, and the right to warn".<ref>[[Walter Bagehot|Bagehot, Walter]] (1867). ''The English Constitution''. London: Chapman and Hall. p. 103.</ref> In addition the monarch has a number of [[Reserve power#United Kingdom|reserve powers]] at his disposal to uphold [[responsible government]] and prevent [[constitutional crisis|constitutional crises]].{{Efn|For instance, the monarch alone appoints the prime minister and confers [[Orders, decorations, and medals of the United Kingdom|state honours]] in the personal gift of the Crown. When necessary, the monarch may also refuse a [[dissolution of Parliament|dissolution]] or [[Prorogation in the United Kingdom|prorogation of Parliament]], withhold [[royal assent]] to [[Act of Parliament (UK)|primary legislation]], and prevent illegal use of the [[British Armed Forces]], amongst other reserve powers.<ref>{{Cite web |url=https://researchbriefings.files.parliament.uk/documents/CBP-8885/CBP-8885.pdf |title=The Crown and the Constitution |author=David Torrance |publisher=House of Commons Library |publication-date=11 January 2023 |access-date=19 June 2023 |pages=22 |archive-date=2 March 2023 |archive-url=https://web.archive.org/web/20230302033737/https://researchbriefings.files.parliament.uk/documents/CBP-8885/CBP-8885.pdf |url-status=live}}</ref>}}
The prime minister is the [[head of government]] in the United Kingdom.<ref>{{Cite web |title=The Government, Prime Minister and Cabinet |url=http://direct.gov.uk/en/Governmentcitizensandrights/UKgovernment/Centralgovernmentandthemonarchy/DG_073444 |archive-url=https://web.archive.org/web/20120921004951/http://www.direct.gov.uk/en/Governmentcitizensandrights/UKgovernment/Centralgovernmentandthemonarchy/DG_073444 |archive-date=21 September 2012 |access-date=9 March 2015 |website=Public services all in one place |publisher=[[Directgov]]}}</ref> Acting under the direction and supervision of a [[Cabinet of the United Kingdom|Cabinet]] of senior ministers selected and led by the prime minister, [[His Majesty's Government]] serves as the principal instrument for public policymaking, administers public services and, through the [[Privy Council of the United Kingdom|Privy Council]], promulgates [[statutory instrument (UK)|statutory instruments]] and tenders advice to the monarch.<ref>{{Cite web |url=https://www.instituteforgovernment.org.uk/explainer/cabinet |title=Cabinet |author=Tim Durrant |date=25 March 2020 |publisher=Institute for Government |publication-date=25 March 2020 |access-date=4 July 2023 |archive-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704112925/https://www.instituteforgovernment.org.uk/explainer/cabinet |url-status=live}}</ref><ref>{{Cite web |url=https://www.parliament.uk/about/how/role/relations-with-other-institutions/parliament-government/ |title=Parliament and Government |publisher=UK Parliament |access-date=4 July 2023 |archive-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704112925/https://www.parliament.uk/about/how/role/relations-with-other-institutions/parliament-government/ |url-status=live}}</ref><ref>{{Cite book |url=https://books.google.com/books?id=mN6SzMefot4C |title=The Monarchy and the Constitution, Chapter 3 – The Basic Constitutional Rules: Influence and the Prerogative |author=Vernon Bogdanor |year=1995 |publisher=Clarendon Press |isbn=978-0-19-829334-7 |publication-date=1995 |access-date=4 July 2023}}</ref> Nearly all prime ministers have served concurrently as [[First Lord of the Treasury]]<ref>{{Cite web |last1=Blick |first1=Andrew |last2=Jones |first2=George |date=1 January 2012 |title=The Institution of Prime Minister – History of government |url=https://history.blog.gov.uk/2012/01/01/the-institution-of-prime-minister |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=21 July 2021 |archive-url=https://web.archive.org/web/20210721060401/https://history.blog.gov.uk/2012/01/01/the-institution-of-prime-minister/ |url-status=live}}</ref> and all prime ministers have continuously served as First Lord of the Treasury since 1905,<ref>{{Cite book |last=Brown |first=Jack |title=The Prime Ministers |publisher=[[Hodder & Stoughton]] |year=2020 |isbn=978-1-5293-1214-0 |editor-last=Dale |editor-first=Iain |page=303}}</ref> [[Minister for the Civil Service]] since 1968,<ref>{{Cite web |title=Minister for the Civil Service |url=https://www.gov.uk/government/ministers/minister-for-the-civil-service |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=2 September 2017 |archive-url=https://web.archive.org/web/20170902233116/https://www.gov.uk/government/ministers/minister-for-the-civil-service |url-status=live}}</ref> and [[Minister for the Union]] since 2019.<ref>{{Cite news |last=Woodcock |first=Andrew |date=26 July 2021 |title=Boris Johnson accused of 'cynical rebranding' after appointing himself 'Minister for the Union' |work=[[The Independent|Independent]] |url=https://www.independent.co.uk/news/uk/politics/boris-johnson-minister-union-scotland-independence-referendum-snp-a9022356.html |access-date=19 July 2021 |archive-date=27 July 2019 |archive-url=https://web.archive.org/web/20190727080405/https://www.independent.co.uk/news/uk/politics/boris-johnson-minister-union-scotland-independence-referendum-snp-a9022356.html |url-status=live}}; {{Cite web |title=Minister for the Union |url=https://www.gov.uk/government/ministers/minister-for-the-union |access-date=19 July 2021 |website=[[gov.uk]] |archive-date=19 July 2020 |archive-url=https://web.archive.org/web/20200719053618/https://www.gov.uk/government/ministers/minister-for-the-union |url-status=live}}</ref> While appointed by the monarch, in modern times the prime minister is, by [[Constitutional conventions of the United Kingdom|convention]], an MP, the leader of the political party with the most seats in the House of Commons, and holds office by virtue of their ability to [[Confidence motions in the United Kingdom|command the confidence]] of the House of Commons.<ref>{{Cite web |date=October 2011 |title=The Cabinet Manual |url=https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/60641/cabinet-manual.pdf |access-date=19 July 2021 |website=[[gov.uk]] |pages=7, 21 |archive-date=15 April 2018 |archive-url=https://web.archive.org/web/20180415090557/https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/60641/cabinet-manual.pdf |url-status=live}}</ref><ref>{{Cite book |last=Norton |first=Philip |title=Governing Britain: Parliament, Ministers and Our Ambiguous Constitution |publisher=[[Manchester University Press]] |year=2020 |isbn=978-1-5261-4545-1 |page=130}}</ref> The prime minister as of 20 July 2026, is [[Andy Burnham]], the [[Leader of the Labour Party (UK)|leader of the Labour Party]].
Although not part of the United Kingdom, the three [[Crown Dependencies]] of [[Jersey]], [[Guernsey]] and the [[Isle of Man]], as well as the 14 [[British Overseas Territories]], are subject to the sovereignty of the British Crown.<ref>{{cite book |last=Palan |first=Rolen |editor-last1=Palan |editor-first1=Rolen |editor-last2=Halperin |editor-first2=Sandra |chapter=The second British Empire and the re-emergence of global finance |chapter-url=https://books.google.com/books?id=76QyCgAAQBAJ&dq=%22British+overseas+territories%22+%22crown+dependencies%22+UK+%22British+crown%22&pg=PA48 |title=Legacies of Empire: Imperial Roots of the Contemporary Global Order |year=2015 |publisher=Cambridge University Press |isbn=978-1-107-10946-9 |page=48 |access-date=13 April 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212946/https://books.google.com/books?id=76QyCgAAQBAJ&dq=%22British+overseas+territories%22+%22crown+dependencies%22+UK+%22British+crown%22&pg=PA48#v=onepage&q=%22British%20overseas%20territories%22%20%22crown%20dependencies%22%20UK%20%22British%20crown%22&f=false |url-status=live}}</ref>
[[Democratic backsliding]] was found by the 2026 [[V-Dem Institute#Democracy Report|V-Dem Democracy Report]] for the United Kingdom.<ref name="j496">{{cite web | title=Democracy Report 2026, Unraveling The Democratic Era? | url=https://v-dem.net/documents/75/V-Dem_Institute_Democracy_Report_2026_lowres.pdf | access-date=2026-03-17}}</ref>
===Elections===
{{Main|Elections in the United Kingdom}}
[[File:Houses of Parliament in 2022 (cropped).jpg|thumb|upright=1.25|alt=Large sand-coloured building of Gothic design beside brown river. The building has several large towers, including large clock tower.|The [[Palace of Westminster]] in London is the seat of both houses of the Parliament of the United Kingdom.]]
For [[General elections in the United Kingdom|general elections]] (elections to the House of Commons), the United Kingdom is divided into 650 [[United Kingdom constituencies|constituencies]], each of which is represented by one [[Member of Parliament (United Kingdom)|member of Parliament]] (MP) elected by the [[First-past-the-post voting|first-past-the-post]] system.<ref name="parliament.uk-2">{{Cite web |title=General elections |url=https://www.parliament.uk/about/how/elections-and-voting/general |access-date=19 July 2021 |website=[[parliament.uk]]}}</ref> MPs hold office for up to five years and must then stand for re-election if they wish to continue to be an MP.<ref name="parliament.uk-2" /> The [[Conservative Party (UK)|Conservative Party]], colloquially known as the Tory Party or the Tories, and the [[Labour Party (UK)|Labour Party]] have been the dominant political parties in the country since the 1920s, leading to the UK being described as a [[two-party system]]. However, since the 1920s other [[List of political parties in the United Kingdom|political parties]] have won seats in the House of Commons, although never more than the Conservatives or Labour.<ref>{{Cite web |last=Raymond |first=C |date=2016 |title=Why British Politics is Not a Two-Party System |url=https://pureadmin.qub.ac.uk/ws/portalfiles/portal/107735631/The_United_Kingdom_is_Not_a_Two_Party_System.pdf |website=Queen's University Belfast |access-date=3 July 2023 |archive-date=9 July 2023 |archive-url=https://web.archive.org/web/20230709172832/https://pureadmin.qub.ac.uk/ws/portalfiles/portal/107735631/The_United_Kingdom_is_Not_a_Two_Party_System.pdf |url-status=live}}</ref> The 2020s marked the erosion of the two-party system and the growth of a multi-party system.<ref>{{Cite web |date=2026-05-08 |title=Sir John Curtice: Election results show politics in the UK has fragmented |url=https://www.bbc.com/news/articles/ce8p4yn448vo |access-date=2026-05-09 |website=[[BBC News]] |language=en-GB}}</ref>
=== Administrative divisions ===
{{Main|Countries of the United Kingdom|Administrative geography of the United Kingdom|List of counties in the United Kingdom}}
[[File:United Kingdom labelled map7 vector.svg|thumb|upright=0.8|The four countries of the United Kingdom]]
The geographical division of the United Kingdom into counties or [[shire]]s began in England and Scotland in the [[early Middle Ages]], and was completed throughout Great Britain and Ireland by the [[early modern period]].<ref>Hackwood Frederick William: ''The Story of the Shire, Being the Lore, History and Evolution of English County Institutions'' (1851)</ref> Modern [[local government]] by elected councils, partly based on the ancient counties, was established by separate Acts of Parliament: in England and Wales [[Local Government Act 1888|in 1888]], Scotland [[Local Government (Scotland) Act 1889|in 1889]] and Ireland [[Local Government (Ireland) Act 1898|in 1898]], meaning there is no consistent system of administrative or geographic demarcation across the UK,<ref>{{Cite web |last=United Nations Economic and Social Council |author-link=United Nations Economic and Social Council |date=August 2007 |title=Ninth UN Conference on the standardization of Geographical Names |url=http://unstats.un.org/unsd/geoinfo/UNGEGN/docs/9th-uncsgn-docs/report%20of%209th%20uncsgn%20n0750902%20en.pdf |url-status=live |archive-url=https://web.archive.org/web/20091211213055/http://unstats.un.org/unsd/geoinfo/9th-UNCSGN-Docs/E-CONF-98-48-Add1.pdf |archive-date=11 December 2009 |access-date=21 October 2008 |publisher=UN Statistics Division}}</ref> and [[English law|England and Wales]], [[Scots law|Scotland]] and [[Law of Northern Ireland|Northern Ireland]] each have their own distinct jurisdictions.<ref>{{Cite book |last1=Dewart |first1=Megan |url=https://books.google.com/books?id=XW_EtwEACAAJ |title=The Scottish Legal System |date=2019 |publisher=[[Bloomsbury Academic]] |isbn=978-1-5265-0633-7 |location=London |page=57 |quote=The laws and legal institutions of Scotland and of England and Wales were not merged by the Union of 1707. Thus, they remain separate 'law areas', with separate court systems (as does Northern Ireland), and it is necessary to distinguish Scots law and English law (and Northern Irish law). |access-date=4 July 2023 |archive-url=https://web.archive.org/web/20230704040048/https://books.google.com/books?id=XW_EtwEACAAJ |archive-date=4 July 2023 |url-status=live}}; {{Cite web |title=The justice system and the constitution |url=https://www.judiciary.uk/about-the-judiciary/our-justice-system/jud-acc-ind/justice-sys-and-constitution/#:~:text=The%20United%20Kingdom%20has%20three,of%20Union%201707%20and%201800. |archive-url=https://web.archive.org/web/20230521180341/https://www.judiciary.uk/about-the-judiciary/our-justice-system/jud-acc-ind/justice-sys-and-constitution/ |archive-date=21 May 2023 |access-date=13 June 2023 |publisher=Courts and Tribunals Judiciary |quote=The United Kingdom has three separate legal systems; one each for England and Wales, Scotland and Northern Ireland. This reflects its historical origins and the fact that both Scotland and Ireland, and later Northern Ireland, retained their own legal systems and traditions under the Acts of Union 1707 and 1800.}}</ref> Until the 19th century there was little change to those arrangements, but there has since been a constant evolution of role and function.<ref>{{Cite book |last=Barlow |first=I.M. |title=Metropolitan Government |publisher=Routledge |year=1991 |isbn=978-0-415-02099-2 |location=London}}</ref>
[[Local government in England]] is complex, with the distribution of functions varying according to local arrangements. The upper-tier [[subdivisions of England]] are the nine [[Regions of England|regions]], used primarily for statistical purposes.<ref>{{Cite web |title=Welcome to the national site of the Government Office Network |url=http://www.gos.gov.uk/national |archive-url=https://web.archive.org/web/20090606073647/http://www.gos.gov.uk/national |archive-date=6 June 2009 |access-date=3 July 2008 |publisher=Government Offices}}</ref> One of the regions, [[Greater London Authority|Greater London]], has had a directly elected assembly and mayor since 2000 following popular support for the proposal in a [[1998 Greater London Authority referendum|1998 referendum]].<ref>{{Cite web |title=A short history of London government |url=http://www.london.gov.uk/london-life/city-government/history.jsp |archive-url=https://web.archive.org/web/20080421023053/http://www.london.gov.uk/london-life/city-government/history.jsp |archive-date=21 April 2008 |access-date=4 October 2008 |publisher=Greater London Authority}}</ref>
[[Local government in Scotland]] is divided into [[subdivisions of Scotland|32 council areas]] with a wide variation in size and population. The cities of [[Glasgow]], Edinburgh, [[Aberdeen]] and [[Dundee]] are separate council areas, as is the [[Politics of the Highland council area|Highland Council]], which includes a third of Scotland's area but only just over 200,000 people. Local councils are made up of elected councillors, of whom there are 1,223.<ref name="political-studies-association">{{Cite web |title=STV in Scotland: Local Government Elections 2007 |url=http://www.psa.ac.uk/2007/pps/Bennie.pdf |archive-url=https://web.archive.org/web/20110222124635/http://www.psa.ac.uk/2007/pps/Bennie.pdf |archive-date=22 February 2011 |access-date=2 August 2008 |publisher=Political Studies Association}}</ref>
[[Local government in Wales]] consists of 22 [[Unitary authority|unitary authorities]], each led by a leader and cabinet elected by the council itself. These include the cities of Cardiff, [[Swansea]] and [[Newport, Wales|Newport]], which are unitary authorities in their own right.<ref name="unitary">{{Cite web |year=2014 |title=Unitary authorities |url=http://gov.wales/topics/localgovernment/local-authorities/?lang=en |archive-url=https://web.archive.org/web/20150310210146/http://gov.wales/topics/localgovernment/local-authorities/?lang=en |archive-date=10 March 2015 |access-date=9 March 2015 |publisher=Welsh Government}}</ref> Elections are held every four years under the first-past-the-post system.<ref name="unitary" />
[[Local government in Northern Ireland]] since 2015 has been organised into 11 district councils, each elected by single transferable vote. Their powers are limited to services such as waste collection, dog control, and maintaining parks and cemeteries.<ref name="Devenport">{{Cite news |last=Devenport |first=Mark |date=18 November 2005 |title=NI local government set for shake-up |work=BBC News |url=http://news.bbc.co.uk/1/hi/northern_ireland/4449092.stm |access-date=15 November 2008 |archive-date=12 December 2008 |archive-url=https://web.archive.org/web/20081212221731/http://news.bbc.co.uk/1/hi/northern_ireland/4449092.stm |url-status=live}}</ref> This system was introduced after a 2008 decision by the executive to replace the previous structure of 26 districts which had been in place since 1973.<ref>{{Cite press release |title=Foster announces the future shape of local government |date=13 March 2008 |publisher=Northern Ireland Executive |url=http://www.northernireland.gov.uk/news/news-doe/news-doe-130308-foster-announces-the.htm |access-date=20 October 2008 |archive-url=https://web.archive.org/web/20080725002254/http://www.northernireland.gov.uk/news/news-doe/news-doe-130308-foster-announces-the.htm |archive-date=25 July 2008}}</ref>
=== Devolution ===
{{Main|Devolution in the United Kingdom}}
{{further|Devolved, reserved and excepted matters}}
[[File:Council of Nations and Regions (54059219744) (cropped).jpg|thumb|right|Prime Minister Keir Starmer meets with the first ministers of Scotland, Northern Ireland and Wales during the [[Council of Nations and Regions]] summit.]]
In the United Kingdom a process of devolution has transferred various powers from the UK Government to three of the four UK countries—Scotland, Northern Ireland and Wales—as well as to the regions of England, which since 1999 have their own governments and parliaments that control various devolved matters.<ref>{{Cite web |title=Devolution of powers to Scotland, Wales and Northern Ireland |url=https://www.gov.uk/devolution-of-powers-to-scotland-wales-and-northern-ireland#devolved-administrations |url-status=live |archive-url=https://web.archive.org/web/20130718065448/https://www.gov.uk/devolution-of-powers-to-scotland-wales-and-northern-ireland#devolved-administrations |archive-date=18 July 2013 |access-date=17 April 2013 |publisher=United Kingdom Government |quote=In a similar way to how the government is formed from members from the two Houses of Parliament, members of the devolved legislatures nominate ministers from amongst themselves to comprise executives, known as the devolved administrations...}}; {{Cite web |title=Country Overviews: United Kingdom |url=http://www.transport-research.info/web/countryprofiles/uk.cfm |archive-url=https://web.archive.org/web/20100404062853/http://www.transport-research.info/web/countryprofiles/uk.cfm |archive-date=4 April 2010 |access-date=28 March 2010 |url-status=usurped |publisher=Transport Research Knowledge Centre}}</ref> These powers vary and have been moved to the [[Scottish Government]], the [[Welsh Government]], the [[Northern Ireland Executive]] and (in England) to [[strategic authorities]]: the [[Greater London Authority]], [[Combined authorities and combined county authorities|combined authorities, and combined county authorities]].<ref>{{cite book |last1=Le Sueur |first1=Andrew |last2=Sunkin |first2=Maurice |last3=Murkens |first3=Jo Eric Khushal |title=Public Law: Text, Cases, and Materials |year=2023 |edition=5th |isbn=978-0-19-287061-2 |publisher=Oxford University Press |page=147 |url=https://books.google.com/books?id=6sLDEAAAQBAJ&dq=Le+sueur+Public+Law%C2%A0fifth+edition&pg=PR3 |access-date=13 April 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002213048/https://books.google.com/books?id=6sLDEAAAQBAJ&dq=Le+sueur+Public+Law%C2%A0fifth+edition&pg=PR3#v=onepage&q=Le%20sueur%20Public%20Law%C2%A0fifth%20edition&f=false |url-status=live}}</ref> Amongst the devolved parliaments across the United Kingdom, the [[Scottish Parliament]] has the most extensive responsibilities for [[Devolved, reserved and excepted matters|devolved powers]], and has been described as "one of the most powerful devolved parliaments in the world".<ref>{{cite web |title=The progress of devolution - Erskine May - UK Parliament |url=https://erskinemay.parliament.uk/section/4537/the-progress-of-devolution |website=erskinemay.parliament.uk |access-date=1 March 2025}}</ref><ref>{{cite web |title=David Mundell speech: 20 years of Scottish devolution |url=https://www.gov.uk/government/news/david-mundell-speech-20-years-of-scottish-devolution |website=GOV.UK |access-date=1 March 2025}}</ref>
The United Kingdom has an [[uncodified constitution]] and constitutional matters are not amongst the powers that have been devolved. Under the doctrine of [[Parliamentary sovereignty in the United Kingdom|parliamentary sovereignty]], the UK Parliament could, in theory, therefore, abolish the Scottish Parliament, Senedd or Northern Ireland Assembly.<ref>{{Cite journal |last=Burrows |first=N. |year=1999 |title=Unfinished Business: The Scotland Act 1998 |journal=The Modern Law Review |volume=62 |issue=2 |pages=241–260 [p. 249] |doi=10.1111/1468-2230.00203 |quote=The UK Parliament is sovereign and the Scottish Parliament is subordinate. The White Paper had indicated that this was to be the approach taken in the legislation. The Scottish Parliament is not to be seen as a reflection of the settled will of the people of Scotland or of popular sovereignty but as a reflection of its subordination to a higher legal authority. Following the logic of this argument, the power of the Scottish Parliament to legislate can be withdrawn or overridden...}}; {{Cite journal |last=Elliot |first=M. |year=2004 |title=United Kingdom: Parliamentary sovereignty under pressure |journal=International Journal of Constitutional Law |volume=2 |issue=3 |pages=545–627, 553–554 |doi=10.1093/icon/2.3.545 |quote=Notwithstanding substantial differences among the schemes, an important common factor is that the UK Parliament has not renounced legislative sovereignty in relation to the three nations concerned. For example, the Scottish Parliament is empowered to enact primary legislation on all matters, save those in relation to which competence is explicitly denied ... but this power to legislate on what may be termed "devolved matters" is concurrent with the Westminster Parliament's general power to legislate for Scotland on any matter at all, including devolved matters ... In theory, therefore, Westminster may legislate on Scottish devolved matters whenever it chooses... |doi-access=free}}</ref> Though in the [[Scotland Act 2016]] and the [[Wales Act 2017]] it states that the Scottish Government and the Welsh Government "are a permanent part of the United Kingdom's constitutional arrangements".<ref>{{cite web |title=Scotland Act 2016 |url=https://www.legislation.gov.uk/ukpga/2016/11/part/1/crossheading/the-scottish-parliament-and-the-scottish-government#:~:text=(1)The%20Scottish%20Parliament%20and,the%20United%20Kingdom's%20constitutional%20arrangements. |website=Gov.uk |access-date=28 June 2024 |archive-date=28 June 2024 |archive-url=https://web.archive.org/web/20240628211304/https://www.legislation.gov.uk/ukpga/2016/11/part/1/crossheading/the-scottish-parliament-and-the-scottish-government#:~:text=(1)The%20Scottish%20Parliament%20and,the%20United%20Kingdom's%20constitutional%20arrangements. |url-status=live}}</ref><ref>{{cite web |title=Wales Act 2017 |url=https://www.legislation.gov.uk/ukpga/2017/4/section/1/enacted |access-date=13 July 2024 |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212916/https://www.legislation.gov.uk/ukpga/2017/4/section/1/enacted |url-status=live}}</ref>
In practice it would be politically difficult for the UK Parliament to abolish devolution to the Scottish Parliament and the Senedd because these institutions were created by referendums.<ref>{{Cite journal |last=Gamble |first=A. |year=2006 |title=The Constitutional Revolution in the United Kingdom |journal=Publius |volume=36 |issue=1 |pages=19–35 [p. 29] |doi=10.1093/publius/pjj011 |quote=The British parliament has the power to abolish the Scottish parliament and the Welsh assembly by a simple majority vote in both houses, but since both were sanctioned by referenda, it would be politically difficult to abolish them without the sanction of a further vote by the people. In this way, several of the constitutional measures introduced by the Blair government appear to be entrenched and not subject to a simple exercise of parliamentary sovereignty at Westminster.}}</ref> The political constraints placed upon the UK Parliament's power to interfere with devolution in Northern Ireland are greater still, because devolution in Northern Ireland rests upon an international agreement with the [[Government of Ireland]].<ref>{{Cite journal |last=Meehan |first=E. |year=1999 |title=The Belfast Agreement – Its Distinctiveness and Points of Cross-Fertilization in the UK's Devolution Programme |journal=Parliamentary Affairs |volume=52 |issue=1 |pages=19–31 [p. 23] |doi=10.1093/pa/52.1.19 |quote=[T]he distinctive involvement of two governments in the Northern Irish problem means that Northern Ireland's new arrangements rest upon an intergovernmental agreement. If this can be equated with a treaty, it could be argued that the forthcoming distribution of power between Westminster and Belfast has similarities with divisions specified in the written constitutions of federal states...Although the Agreement makes the general proviso that Westminster's 'powers to make legislation for Northern Ireland' remains 'unaffected', without an explicit categorical reference to reserved matters, it may be more difficult than in Scotland or Wales for devolved powers to be repatriated. The retraction of devolved powers would not merely entail consultation in Northern Ireland backed implicitly by the absolute power of parliamentary sovereignty but also the renegotiation of an intergovernmental agreement. |doi-access=free}}</ref> The UK Parliament restricts the three devolved parliaments' legislative powers in economic policy matters through [[United Kingdom Internal Market Act 2020|an act]] passed in 2020.<ref name="UKIM" />
==== England ====
Unlike Scotland, Northern Ireland and Wales, England does not have a separate devolved government or national parliament,<ref>{{cite web |title=English devolution |url=https://www.instituteforgovernment.org.uk/explainer/english-devolution#:~:text=After%201997%20Labour%20governments%20devolved,assembly%20were%20created%20in%202000. |publisher=Institute for Government |access-date=30 August 2024 |date=21 June 2024 |archive-date=30 August 2024 |archive-url=https://web.archive.org/web/20240830150949/https://www.instituteforgovernment.org.uk/explainer/english-devolution#:~:text=After%201997%20Labour%20governments%20devolved,assembly%20were%20created%20in%202000. |url-status=live}}</ref> rather a process of devolution of powers from the central government to local authorities has taken place, first in 1998.<ref>{{cite web |title=Devolution explained |url=https://www.local.gov.uk/topics/devolution/devolution-hub/devolution-explained |publisher=Local Government Association |access-date=30 August 2024 |archive-date=30 August 2024 |archive-url=https://web.archive.org/web/20240830152450/https://www.local.gov.uk/topics/devolution/devolution-hub/devolution-explained |url-status=live}}</ref> The [[Greater London Authority]] was set up following a [[1998 Greater London Authority referendum|referendum in 1998]]. Colloquially known as City Hall, it is the devolved regional government body for Greater London. It consists of two political branches: a directly elected [[Mayor of London]] and the [[London Assembly]], which serves as a check and balance on the Mayor.
A [[Combined authorities and combined county authorities|combined authority]] is a type of local government institution introduced in England outside Greater London by the [[Local Democracy, Economic Development and Construction Act 2009]]. CAs allow a group of local authorities to pool appropriate responsibility and receive certain devolved functions from central government in order to deliver transport and economic policy more effectively over a wider area.<ref>{{Cite web |date=6 March 2023 |title=English devolution |url=https://www.instituteforgovernment.org.uk/explainer/english-devolution |access-date=4 February 2024 |publisher=Institute for Government |archive-date=2 October 2024 |archive-url=https://web.archive.org/web/20241002212917/https://www.instituteforgovernment.org.uk/explainer/english-devolution |url-status=live}}</ref> A combined county authority is a similar type of local-government institution introduced in England outside Greater London by the [[Levelling-up and Regeneration Act 2023]], but may only be formed by upper-tier authorities: [[county council]]s and [[Unitary authority|unitary authorities]].<ref>{{Cite web |date=6 April 2023 |title=Combined County Authorities – key differences to Combined Authorities |url=https://www.localgovernmentlawyer.co.uk/governance/314-governance-a-risk-articles/53464-combined-county-authorities-key-differences-to-combined-authorities |access-date=4 February 2024 |website=Local Government Lawyer |archive-date=4 February 2024 |archive-url=https://web.archive.org/web/20240204170903/https://www.localgovernmentlawyer.co.uk/governance/314-governance-a-risk-articles/53464-combined-county-authorities-key-differences-to-combined-authorities |url-status=live}}</ref>
==== Scotland ====
{{main|Responsibilities of the Scottish Government}}
[[File:First Minister meets Prime Minister (53840421342).jpg|thumb|Prime Minister Keir Starmer meets with [[First Minister of Scotland]] [[John Swinney]], the head of the [[Scottish Government]], at [[Bute House]], Edinburgh.]]
Since 1999 Scotland has had a devolved national government and parliament with wide-ranging powers over any matter that has not been specifically [[Reserved and excepted matters|reserved]] to the UK Parliament.<ref name="Scottish Parliament">{{cite web |title=Devolved and Reserved Powers |url=https://www.parliament.scot/about/how-parliament-works/devolved-and-reserved-powers |website=parliament.scot |publisher=Scottish Parliament |access-date=28 December 2023 |archive-date=20 September 2023 |archive-url=https://web.archive.org/web/20230920053732/https://www.parliament.scot/about/how-parliament-works/devolved-and-reserved-powers |url-status=live}}</ref><ref>{{Cite news |date=8 April 1999 |title=Scotland's Parliament – powers and structures |work=BBC News |url=http://news.bbc.co.uk/1/hi/events/scotland_99/the_scottish_parliament/310036.stm |access-date=21 October 2008 |archive-date=18 February 2007 |archive-url=https://web.archive.org/web/20070218234816/http://news.bbc.co.uk/1/hi/events/scotland_99/the_scottish_parliament/310036.stm |url-status=live}}</ref> Scotland has the most devolved powers of any of the three devolved parliaments in the United Kingdom, with full legislative control over [[Education in Scotland|education]], [[Scots law|law and order]], [[Economy of Scotland|the economy]], [[Health in Scotland|healthcare]], [[Elections in Scotland|elections]], [[Crown Estate Scotland]], the [[Planning system in Scotland|planning system]] and [[Housing in Scotland|housing]].<ref>{{cite web |title=Devolved and Reserved Matters - Visit & Learn Scottish Parliament |url=http://www.parliament.scot/visitandlearn/Education/18642.aspx |archive-url=https://web.archive.org/web/20170722092046/http://www.parliament.scot/visitandlearn/Education/18642.aspx |url-status=dead |archive-date=22 July 2017 |access-date=1 March 2025 |date=22 July 2017}}</ref>
Additional powers were transferred to the Scottish Parliament via the [[Scotland Act 2012]] and the [[Scotland Act 2016]], such as [[Taxation in Scotland|some taxation powers]], including full control of [[Income tax in Scotland|income tax]] on income earned through employment, [[Land and Buildings Transaction Tax]], [[Scottish Landfill Tax|Landfill Tax]], Aggregates Levy, [[Air Departure Tax]] and [[Revenue Scotland]], as well as aspects of the [[Energy in Scotland|energy network]], including [[Renewable energy in Scotland|renewable energy]], energy efficiency and onshore [[Oil industry in Scotland|oil and gas licensing]].<ref name="Devolved Matters in Scotland">{{cite web |url=https://www.gov.scot/about/what-the-government-does/ |title=What the Scottish Government does |publisher=Scottish Government |access-date=8 August 2019 |archive-date=8 July 2019 |archive-url=https://web.archive.org/web/20190708045359/https://www.gov.scot/about/what-the-government-does/ |url-status=live}}</ref><ref name="Scottish Parliament" /> Their power over economic issues is significantly constrained by an [[United Kingdom Internal Market Act 2020|act of the UK Parliament]] passed in 2020.{{refn|name=UKIM|<ref name="Keating21">{{Cite journal |last=Keating |first=Michael |date=2 February 2021 |title=Taking back control? Brexit and the territorial constitution of the United Kingdom |journal=[[Journal of European Public Policy]] |location=Abingdon |publisher=[[Taylor & Francis]] |volume=28 |issue=4 |pages=6–7 |doi=10.1080/13501763.2021.1876156 |quote=The UK Internal Market Act gives ministers sweeping powers to enforce mutual recognition and non-discrimination across the four jurisdictions. Existing differences and some social and health matters are exempted but these are much less extensive than the exemptions permitted under the EU Internal Market provisions. Only after an amendment in the House of Lords, the Bill was amended to provide a weak and non-binding consent mechanism for amendments (equivalent to the Sewel Convention) to the list of exemptions. The result is that, while the devolved governments retain regulatory competences, these are undermined by the fact that goods and services originating in, or imported into, England can be marketed anywhere. |hdl-access=free |hdl=1814/70296 |s2cid=234066376}}</ref><ref name="KenMcEw21">{{Cite journal |last1=Kenny |first1=Michael |author-link=Michael Kenny (political scientist) |last2=McEwen |first2=Nicola |author-link2=Nicola McEwen |date=1 March 2021 |title=Intergovernmental Relations and the Crisis of the Union |journal=Political Insight |publisher=[[SAGE Publishing]] |volume=12 |issue=1 |pages=12–15 |doi=10.1177/20419058211000996 |quote=That phase of joint working was significantly damaged by the UK Internal Market Act, pushed through by the Johnson government in December 2020...the Act diminishes the authority of the devolved institutions, and was vehemently opposed by them. |doi-access=free |s2cid=232050477}}</ref><ref name="WolffeDevol">{{Cite journal |last=Wolffe |first=W James |author-link=James Wolffe |date=7 April 2021 |title=Devolution and the Statute Book |url=https://academic.oup.com/slr/advance-article/doi/10.1093/slr/hmab003/6213886 |journal=[[Statute Law Review]] |location=Oxford |publisher=[[Oxford University Press]] |doi=10.1093/slr/hmab003 |access-date=18 April 2021 |quote=the Internal Market Bill—a Bill that contains provisions which, if enacted, would significantly constrain, both legally and as a matter of practicality, the exercise by the devolved legislatures of their legislative competence; provisions that would be significantly more restrictive of the powers of the Scottish Parliament than either EU law or Articles 4 and 6 of the Acts of the Union...The UK Parliament passed the European Union (Withdrawal Agreement) Act 2020 and the Internal Market Act 2020 notwithstanding that, in each case, all three of the devolved legislatures had withheld consent. |archive-date=21 April 2021 |archive-url=https://web.archive.org/web/20210421145355/https://academic.oup.com/slr/advance-article/doi/10.1093/slr/hmab003/6213886 |url-status=live |url-access=subscription}}</ref><ref name="Wincott21">{{Cite journal |last1=Wincott |first1=Daniel |author-link=Daniel Wincott |last2=Murray |first2=C. R. G. |last3=Davies |first3=Gregory |date=17 May 2021 |title=The Anglo-British imaginary and the rebuilding of the UK's territorial constitution after Brexit: unitary state or union state? |journal=Territory, Politics, Governance |location=Abingdon/Brighton |publisher=[[Taylor & Francis]]; [[Regional Studies Association]] |volume=10 |issue=5 |pages=696–713 |doi=10.1080/21622671.2021.1921613 |quote=Taken as a whole, the Internal Market Act imposes greater restrictions upon the competences of the devolved institutions than the provisions of the EU Single Market which it replaced, in spite of pledges to use common frameworks to address these issues. [[David Hope, Baron Hope of Craighead|Lord Hope]], responsible for many of the leading judgments relating to the first two decades of devolution, regarded the legislation's terms as deliberately confrontational: 'this Parliament can do what it likes, but a different approach is essential if the union is to hold together'. |doi-access=free}}</ref><ref name="DouganMcEwen20">{{Cite report |url=https://www.centreonconstitutionalchange.ac.uk/publications/uk-and-internal-market-devolution-and-union |title=UK and the Internal Market, Devolution and the Union |last1=Dougan |first1=Michael |last2=Hayward |first2=Katy |date=2020 |publisher=[[University of Edinburgh]]; [[University of Aberdeen]] |pages=2–3 |last3=Hunt |first3=Jo |last4=McEwen |first4=Nicola |last5=McHarg |first5=Aileen |last6=Wincott |first6=Daniel |author-link=Michael Dougan |author-link2=Katy Hayward |access-date=16 October 2020 |author-link4=Nicola McEwen |author-link6=Daniel Wincott |department=Centre on Constitutional Change |archive-date=18 October 2020 |archive-url=https://web.archive.org/web/20201018185830/https://www.centreonconstitutionalchange.ac.uk/publications/uk-and-internal-market-devolution-and-union |url-status=live}}</ref><ref name="Dougan20Brief">{{Cite report |url=https://www.liverpool.ac.uk/media/livacuk/law/2-research/eull/UKIM,Briefing,Paper,-,Prof,Michael,Dougan,15,September,2020.pdf |title=Briefing Paper. United Kingdom Internal Market Bill: Implications for Devolution |last=Dougan |first=Michael |date=2020 |publisher=[[University of Liverpool]] |location=Liverpool |pages=4–5 |author-link=Michael Dougan |access-date=15 October 2020 |archive-date=26 October 2020 |archive-url=https://web.archive.org/web/20201026161836/https://www.liverpool.ac.uk/media/livacuk/law/2-research/eull/UKIM,Briefing,Paper,-,Prof,Michael,Dougan,15,September,2020.pdf |url-status=live}}</ref><ref name="DouHu22">{{cite journal |last1=Dougan |first1=Michael |last2=Hunt |first2=Jo |last3=McEwen |first3=Nicola |last4=McHarg |first4=Aileen |author-link1=Michael Dougan |author-link3=Nicola McEwen |title=Sleeping with an Elephant: Devolution and the United Kingdom Internal Market Act 2020 |journal=[[Law Quarterly Review]] |date=2022 |url=https://dro.dur.ac.uk/35167/ |location=London |publisher=[[Sweet & Maxwell]] |ssrn=4018581 |via=[[Durham University|Durham Research Online]] |access-date=4 March 2022 |quote=The Act has restrictive – and potentially damaging – consequences for the regulatory capacity of the devolved legislatures...This was not the first time since the Brexit referendum that the Convention had been set aside, but it was especially notable given that the primary purpose of the legislation was to constrain the capacity of the devolved institutions to use their regulatory autonomy...in practice, it constrains the ability of the devolved institutions to make effective regulatory choices for their territories in ways that do not apply to the choices made by the UK government and parliament for the English market. |issn=0023-933X |archive-date=2 August 2022 |archive-url=https://web.archive.org/web/20220802185022/https://dro.dur.ac.uk/35167/ |url-status=live}}</ref>}}
The [[Scottish Government]] is a [[Scottish National Party]] (SNP) [[minority government]],<ref>{{cite web |title=Humza Yousaf's precarious position puts the SNP – and Scotland – at a crossroads |url=https://www.instituteforgovernment.org.uk/comment/humza-yousaf-snp-scotland-crossroads |website=Institute for Government |access-date=26 April 2024 |date=26 April 2024 |archive-date=26 April 2024 |archive-url=https://web.archive.org/web/20240426221203/https://www.instituteforgovernment.org.uk/comment/humza-yousaf-snp-scotland-crossroads |url-status=live}}</ref> led by the [[First Minister of Scotland|first minister]], currently [[John Swinney]], the [[leader of the SNP]]. In 2014 the [[2014 Scottish independence referendum|Scottish independence referendum]] was held, with 55.3 per cent voting against independence from the United Kingdom and 44.7 per cent voting in favour, resulting in Scotland staying within the United Kingdom. [[Local government in Scotland]] is divided into [[subdivisions of Scotland|32 council areas]] with a wide variation in size and population. Local councils are made up of elected councillors, of whom there are 1,223.<ref name="political-studies-association" />
The Scottish Parliament is separate from the Scottish Government. It is made up of 129 elected [[members of the Scottish Parliament]] (MSPs). It is the law-making body of Scotland, and thus it scrutinises the work of the incumbent Scottish Government and considers any piece of proposed legislation through parliamentary debates, committees and parliamentary questions.<ref name="Devolved Matters in Scotland"/>
==== Wales ====
Since 1999 Wales has had a devolved national government and legislature, known as the [[Senedd]]. Elections to the Senedd used the [[additional member system]] until 2026 when the voting system was changed to [[closed list]] proportional representation. The number of elected members also increased from 60 to 96, representing 16 [[Senedd constituencies|six-member constituencies]]. The Senedd has more limited powers than those devolved to Scotland.<ref>{{Cite news |date=9 April 1999 |title=Structure and powers of the Assembly |work=BBC News |url=http://news.bbc.co.uk/1/hi/events/wales_99/the_welsh_assembly/309033.stm |access-date=21 October 2008 |archive-date=7 February 2004 |archive-url=https://web.archive.org/web/20040207162926/http://news.bbc.co.uk/1/hi/events/wales_99/the_welsh_assembly/309033.stm |url-status=live}}</ref> It can legislate on any matter not specifically reserved to the UK Parliament by [[Acts of Senedd Cymru]]. The [[Welsh Government]] is currently a [[Plaid Cymru]] minority government led by the [[First Minister of Wales|first minister]], [[Rhun ap Iorwerth]]. [[Local government in Wales]] consists of 22 unitary authorities, each led by a leader and cabinet elected by the council itself.
==== Northern Ireland ====
The devolved form of government in Northern Ireland is based on the 1998 [[Good Friday Agreement]], which brought to an end a 30-year period of [[Unionism in Ireland|unionist]]-[[Irish nationalism|nationalist]] communal conflict known as [[the Troubles]]. The Agreement was [[1998 Northern Ireland Good Friday Agreement referendum|confirmed by referendum]] and implemented later that year. It established [[power sharing]] arrangements for a devolved government and legislature, referred to as the [[Northern Ireland Executive]] and the [[Northern Ireland Assembly]] respectively.<ref>{{cite web |title=Good Friday Agreement: What is it? |url=https://www.bbc.co.uk/news/uk-northern-ireland-61968177 |website=BBC News |date=3 April 2023 |access-date=11 April 2024 |archive-date=15 May 2024 |archive-url=https://web.archive.org/web/20240515131233/https://www.bbc.co.uk/news/uk-northern-ireland-61968177 |url-status=live}}</ref> Elections to the Assembly use the [[single transferable vote]] system. The Executive and Assembly have powers similar to those devolved to Scotland.<ref>{{Cite web |date=8 May 2019 |title=Devolution of powers to Scotland, Wales and Northern Ireland |url=https://www.gov.uk/guidance/devolution-of-powers-to-scotland-wales-and-northern-ireland |access-date=11 June 2024 |website=GOV.UK |archive-date=7 March 2023 |archive-url=https://web.archive.org/web/20230307093336/https://www.gov.uk/guidance/devolution-of-powers-to-scotland-wales-and-northern-ireland |url-status=live}}</ref> The Executive is led by a [[diarchy]] representing [[Designated Unionist|unionist]] and [[Designated Nationalist|nationalist]] members of the Assembly.<ref name="northernireland1">{{Cite web |date=25 September 2015 |title=Your Executive |url=https://www.northernireland.gov.uk/topics/your-executive |publisher=Northern Ireland Executive |access-date=14 August 2016 |archive-date=21 August 2016 |archive-url=https://web.archive.org/web/20160821135048/https://www.northernireland.gov.uk/topics/your-executive |url-status=live}}</ref> The [[First Minister and Deputy First Minister of Northern Ireland|first minister and deputy first minister of Northern Ireland]] are the joint heads of government of Northern Ireland.<ref>{{Cite news |title=Stormont: Why were NI leaders given unequal job titles? |work=BBC News |date=15 May 2022 |url=https://www.bbc.co.uk/news/uk-northern-ireland-61393736 |access-date=2 February 2024 |archive-url=https://web.archive.org/web/20240202190001/https://www.bbc.com/news/uk-northern-ireland-61393736 |archive-date=2 February 2024}}</ref><ref>{{Cite web |title=Northern Ireland Executive: Ministerial Code |date=28 September 2015 |url=https://www.northernireland.gov.uk/topics/your-executive/ministerial-code |access-date=2 February 2024 |archive-url=https://web.archive.org/web/20240202191115/https://www.northernireland.gov.uk/topics/your-executive/ministerial-code |archive-date=2 February 2024}}</ref> [[Local government in Northern Ireland]] since 2015 has been divided between 11 councils with limited responsibilities.<ref name="Devenport" />
=== Foreign relations ===
{{Main|Foreign relations of the United Kingdom}}
[[File:Trump-Starmer bilateral 2025-02-27-16-07.jpg|thumb|right|UK prime minister Keir Starmer and US president [[Donald Trump]] shaking hands in a joint press conference in 2025. The UK and the US share a "[[Special Relationship]]".]]
The United Kingdom is [[Big Five (United Nations)|a permanent member]] of the [[United Nations Security Council]] and a member of [[NATO]], [[AUKUS]], the Commonwealth of Nations, the [[G7]], the [[G-20 major economies|G20]], the [[Organisation for Economic Co-operation and Development|OECD]], the [[World Trade Organization|WTO]], the [[Council of Europe]] and the [[Organization for Security and Co-operation in Europe|OSCE]].<ref>{{Cite web |last=May |first=Theresa |author-link=Theresa May |date=29 March 2017 |title=Prime Minister's letter to Donald Tusk triggering Article 50 |url=https://www.gov.uk/government/publications/prime-ministers-letter-to-donald-tusk-triggering-article-50/prime-ministers-letter-to-donald-tusk-triggering-article-50 |via=Gov.uk |access-date=19 June 2017 |archive-date=5 June 2017 |archive-url=https://web.archive.org/web/20170605184239/https://www.gov.uk/government/publications/prime-ministers-letter-to-donald-tusk-triggering-article-50/prime-ministers-letter-to-donald-tusk-triggering-article-50 |url-status=live}}</ref> It maintains the [[British Council]], an organisation specialising in international cultural and educational opportunities in over 100 countries. The UK remains a [[great power]] with considerable political, cultural, economic and military influence.<ref name="PaulWirtz2004">{{cite book |last1=Paul |first1=T.V. |url=https://books.google.com/books?id=9jy28vBqscQC&pg=PA59 |title=Balance of Power: Theory and Practice in the 21st century |last2=Wirtz |first2=James |last3=Fortmann |first3=Michel |date=2004 |publisher=Stanford University Press |isbn=978-0-8047-5017-2 |page=59}}</ref><ref>{{Cite news |date=10 May 2012 |title=United Kingdom country profile |url=https://www.bbc.com/news/world-europe-18023389 |access-date=6 July 2025 |work=BBC News |language=en-GB |archive-date=3 January 2023 |archive-url=https://web.archive.org/web/20230103160059/https://www.bbc.com/news/world-europe-18023389 |url-status=live }}</ref>
The United Kingdom is said to have a "[[Special Relationship]]" with the United States and a close partnership with France – the "[[Entente cordiale]]" – and shares nuclear weapons technology with both countries;<ref>{{Cite web |last=Swaine |first=Jon |date=13 January 2009 |title=Barack Obama presidency will strengthen special relationship, says Gordon Brown |url=https://www.telegraph.co.uk/news/worldnews/barackobama/4226246/Barack-Obama-presidency-will-strengthen-special-relationship-says-Gordon-Brown.html |url-access=subscription |access-date=30 May 2011 |website=[[The Daily Telegraph|The Telegraph]] |publication-place=[[London]] |archive-date=4 July 2020 |archive-url=https://web.archive.org/web/20200704192159/https://www.telegraph.co.uk/news/worldnews/barackobama/4226246/Barack-Obama-presidency-will-strengthen-special-relationship-says-Gordon-Brown.html |url-status=live}}</ref><ref>{{Cite book |last1=Kirchner |first1=Emil Joseph |title=Global Security Governance: Competing Perceptions of Security in the 21st century |last2=Sperling |first2=James |publisher=[[Routledge]] |year=2007 |isbn=978-0-415-39162-7 |edition=illustrated |location=London |page=100}}</ref> the [[Anglo-Portuguese Alliance]] is considered to be the oldest binding military alliance in the world. The UK is also closely linked with the Republic of Ireland; the two countries share a [[Common Travel Area]] and co-operate through the [[British-Irish Intergovernmental Conference]] and the [[British-Irish Council]]. Britain's global presence and influence is further amplified through its trading relations, foreign investments, [[official development assistance]] and military engagements.<ref>{{Cite web |last=The Committee Office, House of Commons |date=19 February 2009 |title=DFID's expenditure on development assistance |url=http://www.parliament.the-stationery-office.co.uk/pa/cm200809/cmselect/cmintdev/220/22007.htm |archive-url=https://web.archive.org/web/20130112222226/http://www.parliament.the-stationery-office.co.uk/pa/cm200809/cmselect/cmintdev/220/22007.htm |archive-date=12 January 2013 |access-date=28 April 2013 |publisher=UK Parliament}}</ref>
=== Military ===
{{Main|British Armed Forces|Military history of the United Kingdom}}
[[File:United Kingdom overseas military installations and operations.png|thumb|upright=1.4|
{{Legend|#0000FF|Overseas military installations of the United Kingdom, and locally raised units of the [[British Overseas Territories]]}}
{{Legend|#F0002B|Military interventions since 2000: [[British military intervention in the Sierra Leone Civil War|Palliser]] (Sierra Leone); [[Operation Herrick|Herrick]] (Afghanistan); [[Operation Enduring Freedom – Horn of Africa|Enduring Freedom]] (Horn of Africa); [[Operation Telic|Telic]] (Iraq); [[Operation Ellamy|Ellamy]] (Libya); and [[Operation Shader|Shader]] (Islamic State of Iraq and the Levant).}}]]
The British Armed Forces consist of three professional service branches: the [[Royal Navy]] and [[Royal Marines]] (forming the [[Naval Service (United Kingdom)|Naval Service]]), the [[British Army]] and the [[Royal Air Force]].<ref>{{Cite web |title=Ministry of Defence |url=http://www.mod.uk/DefenceInternet/Home |access-date=21 February 2012 |publisher=Ministry of Defence |archive-date=19 February 2012 |archive-url=https://web.archive.org/web/20120219194140/http://mod.uk/DefenceInternet/Home/ |url-status=live}}</ref> The armed forces of the United Kingdom are managed by the [[Ministry of Defence (United Kingdom)|Ministry of Defence]] and controlled by the [[Defence Council of the United Kingdom|Defence Council]], chaired by the [[Secretary of State for Defence]]. The [[Commander-in-Chief]] is the [[Monarchy of the United Kingdom|British monarch]], to whom members of the forces swear an oath of allegiance.<ref>{{Cite web |date=30 March 2012 |title=Speaker addresses Her Majesty Queen Elizabeth II |url=http://www.parliament.uk/business/news/2012/march/speaker-addresses-hm-the-queen |access-date=28 April 2013 |publisher=UK Parliament |archive-date=1 May 2013 |archive-url=https://web.archive.org/web/20130501221305/http://www.parliament.uk/business/news/2012/march/speaker-addresses-hm-the-queen/ |url-status=live}}</ref>
The armed forces are charged with protecting the United Kingdom and its overseas territories, promoting the UK's global security interests and supporting international peacekeeping efforts. They are active and regular participants in [[NATO]] (including the [[Allied Rapid Reaction Corps]]), the [[Five Power Defence Arrangements]], [[RIMPAC]] and other worldwide coalition operations. [[Overseas military bases of the United Kingdom|Overseas garrisons]] and facilities are maintained in [[RAF Ascension Island|Ascension Island]], [[Mina Salman|Bahrain]], [[Military of Belize|Belize]], [[Military Forces based in Brunei|Brunei]], [[British Army Training Unit Suffield|Canada]], [[British Forces Cyprus|Cyprus]], [[Diego Garcia]], the [[Military of the Falkland Islands|Falkland Islands]], [[British Forces Germany|Germany]], [[British Forces Gibraltar|Gibraltar]], [[British Army Training Unit Kenya|Kenya]], [[Oman]], [[Al Udeid Air Base|Qatar]] and [[Singapore]].<ref>{{Cite web |title=House of Commons Hansard |url=https://publications.parliament.uk/cgi-bin/newhtml_hl?DB=semukparl&STEMMER=en&WORDS=raf%20diego%20garcia&ALL=RAF&ANY=&PHRASE=%22Diego%20Garcia%20%22&CATEGORIES=&SIMPLE=&SPEAKER=&COLOUR=red&STYLE=s&ANCHOR=50221w33.html_spnew0&URL=/pa/cm200405/cmhansrd/vo050221/text/50221w33.htm#50221w33.html_spnew0 |archive-url=https://web.archive.org/web/20090309114107/http://www.publications.parliament.uk/cgi-bin/newhtml_hl?DB=semukparl&STEMMER=en&WORDS=raf%20diego%20garcia&ALL=RAF&ANY=&PHRASE=%22Diego%20Garcia%20%22&CATEGORIES=&SIMPLE=&SPEAKER=&COLOUR=red&STYLE=s&ANCHOR=50221w33.html_spnew0&URL=%2Fpa%2Fcm200405%2Fcmhansrd%2Fvo050221%2Ftext%2F50221w33.htm#50221w33.html_spnew0 |archive-date=9 March 2009 |access-date=23 October 2008 |publisher=UK Parliament}}; {{Cite web |title=House of Commons Hansard Written Answers for 17 Jun 2013 (pt 0002) |url=https://publications.parliament.uk/pa/cm201314/cmhansrd/cm130617/text/130617w0002.htm#13061746000236 |archive-url=https://web.archive.org/web/20150214025754/http://www.publications.parliament.uk/pa/cm201314/cmhansrd/cm130617/text/130617w0002.htm#13061746000236 |archive-date=14 February 2015 |access-date=4 March 2015 |publisher=Publications.parliament.uk}}</ref>
According to the [[Stockholm International Peace Research Institute]]<ref>{{Cite web |date=April 2026|title=Trends in Military Expenditure 2025|url=https://www.sipri.org/sites/default/files/2026-04/2604_milex_2025.pdf#page=2|access-date=31 May 2026|publisher=[[Stockholm International Peace Research Institute]]}}</ref> and the [[International Institute for Strategic Studies]],<ref>{{Cite web |title=The Military Balance 2026: Global defence spending|url=https://www.iiss.org/publications/the-military-balance/2026/the-military-balance-2026/global-defence-spending/|access-date=2026-05-31|website=IISS|language=en}}</ref> the UK had the world's [[List of countries by military expenditures|sixth- or fifth-highest military expenditures]] in 2025. Total defence spending in 2024 was estimated at 2.3 per cent of [[gross domestic product]].<ref>{{Cite web |title=Rishi Sunak vows to boost UK defence spending to 2.5% of GDP by 2030 |url=https://www.bbc.co.uk/news/uk-politics-68880171 |access-date=24 April 2024 |publisher=BBC News |date=24 April 2024 |archive-date=23 April 2024 |archive-url=https://web.archive.org/web/20240423233438/https://www.bbc.co.uk/news/uk-politics-68880171 |url-status=live}}</ref> Following the end of the [[Cold War]], defence policy has a stated assumption that "the most demanding operations" will be undertaken as part of a coalition.<ref>''UK 2005: The Official Yearbook of the United Kingdom of Great Britain and Northern Ireland''. Office for National Statistics. p. 89.</ref>
=== Law and criminal justice ===
<!-- Copyedit done to here -->
{{Main|Law of the United Kingdom|Crime in the United Kingdom}}
{{Further|English law|Northern Ireland law|Scots law}}
[[File:Middlesex Guildhall (cropped).jpg|thumb|The [[Supreme Court of the United Kingdom|Supreme Court]] is the final court of appeal for England, Wales and Northern Ireland, and for Scottish civil cases.]]
The United Kingdom does not have a single legal system as the [[Treaty of Union|1706 Treaty of Union]] provided for the continuation of Scotland's separate legal system.<ref name="Acts of Union 1707" /> The UK has three distinct [[Legal systems of the world|systems of law]]: English law, Northern Ireland law and Scots law. A new [[Supreme Court of the United Kingdom]] came into being in October 2009 to replace the [[judicial functions of the House of Lords|Appellate Committee of the House of Lords]].<ref>{{Cite news |date=1 October 2009 |title=UK Supreme Court judges sworn in |work=BBC News |url=http://news.bbc.co.uk/1/hi/uk/8283939.stm |access-date=6 October 2009 |archive-date=7 February 2020 |archive-url=https://web.archive.org/web/20200207160453/http://news.bbc.co.uk/1/hi/uk/8283939.stm |url-status=live}}; {{Cite web |date=July 2003 |title=Constitutional reform: A Supreme Court for the United Kingdom |url=http://www.dca.gov.uk/consult/supremecourt/supreme.pdf |archive-url=http://webarchive.nationalarchives.gov.uk/20090117132005/http://www.dca.gov.uk/consult/supremecourt/supreme.pdf |archive-date=17 January 2009 |access-date=13 May 2013 |publisher=Department for Constitutional Affairs}}</ref> The [[Judicial Committee of the Privy Council]], including the same members as the Supreme Court, is the highest court of appeal for several independent Commonwealth countries, the [[British Overseas Territories]] and the [[Crown Dependencies]].<ref>{{Cite web |title=Role of the JCPC |url=http://www.jcpc.uk/about/role-of-the-jcpc.html |access-date=28 April 2013 |publisher=Judicial Committee of the Privy Council |archive-date=14 January 2014 |archive-url=https://web.archive.org/web/20140114165910/http://www.jcpc.uk/about/role-of-the-jcpc.html |url-status=live}}</ref>
Both English law, which applies in England and Wales, and Northern Ireland law are based on [[common law]] (or [[case law]]) principles.<ref>{{Cite book |last=Bainham |first=Andrew |url=https://books.google.com/books?id=AF303DEl0MkC&pg=PA298 |title=The international survey of family law: 1996 |publisher=Martinus Nijhoff |year=1998 |isbn=978-90-411-0573-8 |location=The Hague |page=298 |access-date=29 September 2020 |archive-date=28 March 2024 |archive-url=https://web.archive.org/web/20240328141743/https://books.google.com/books?id=AF303DEl0MkC&pg=PA298#v=onepage&q&f=false |url-status=live}}</ref> It originated in England in the [[Middle Ages]] and is the basis for many legal systems around the world.<ref>{{Cite web |title=Common Law |url=https://www.britannica.com/topic/common-law |access-date=27 May 2024 |publisher=Britannica |date=19 May 2024 |archive-date=6 May 2021 |archive-url=https://web.archive.org/web/20210506134920/https://www.britannica.com/topic/common-law |url-status=live}}</ref> The [[courts of England and Wales]] are headed by the [[Senior Courts of England and Wales]], consisting of the [[Court of Appeal of England and Wales|Court of Appeal]], the [[High Court of Justice]] for civil cases and the [[Crown Court]] for criminal cases.<ref>{{Cite web |title=The Australian courts and comparative law |url=http://www.alpn.edu.au/node/66 |archive-url=https://web.archive.org/web/20130414202207/http://alpn.edu.au/node/66 |archive-date=14 April 2013 |access-date=9 March 2015 |publisher=Australian Law Postgraduate Network}}</ref> Scots law is a hybrid system based on common-law and [[Civil law (legal system)|civil-law]] principles. The chief courts are the [[Court of Session]], for civil cases,<ref>{{Cite web |title=Court of Session – Introduction |url=http://www.scotcourts.gov.uk/session/index.asp |archive-url=https://web.archive.org/web/20080731094308/http://www.scotcourts.gov.uk/session/index.asp |archive-date=31 July 2008 |access-date=8 March 2015 |publisher=Scottish Courts}}</ref> and the [[High Court of Justiciary]], for criminal cases.<ref>{{Cite web |title=High Court of Justiciary – Introduction |url=http://www.scotcourts.gov.uk/justiciary/index.asp |archive-url=https://web.archive.org/web/20080912204821/http://www.scotcourts.gov.uk/justiciary/index.asp |archive-date=12 September 2008 |access-date=9 March 2015 |publisher=Scottish Courts}}</ref> The Supreme Court of the United Kingdom serves as the highest court of appeal for civil cases under Scots law.<ref>{{Cite web |title=House of Lords – Practice Directions and Standing Orders Applicable to Civil Appeals |url=https://publications.parliament.uk/pa/ld199697/ldinfo/ld08judg/bluebook/bluebk03.htm |archive-url=https://web.archive.org/web/20131206120915/http://www.publications.parliament.uk/pa/ld199697/ldinfo/ld08judg/bluebook/bluebk03.htm |archive-date=6 December 2013 |access-date=8 March 2015 |publisher=UK Parliament}}</ref> The criminal justice system has been characterised by low [[conviction rate]]s and [[Justice delayed is justice denied|court delays]] for some crime types.<ref name="s576">{{cite journal | last1=Lovett | first1=Jo | last2=Hales | first2=Gavin | last3=Kelly | first3=Liz | last4=Khan | first4=Aneela | last5=Hardiman | first5=Margaret | last6=Trott | first6=Louise | title=What can We Learn from Police Data About Timeliness in Rape and Serious Sexual Offence Investigations in England and Wales? | journal=International Criminology | volume=2 | issue=3 | date=2022 | issn=2662-9976 | doi=10.1007/s43576-022-00069-8 | pages=286–298| pmc=9527390 }}</ref>
Crime in England and Wales increased between 1981 and 1995. Since that peak there has been an overall fall of 66% in recorded crime from 1995 to 2015,<ref>{{Cite web |url=http://www.ons.gov.uk/ons/dcp171778_419450.pdf |title=Crime in England and Wales, Year Ending June 2015 |publisher=Office for National Statistics |website=UK Government Web Archive |access-date=16 March 2023 |archive-date=16 March 2023 |archive-url=https://web.archive.org/web/20230316221317/https://webarchive.nationalarchives.gov.uk/ukgwa/20160105160709/http://www.ons.gov.uk/ons/dcp171778_419450.pdf |url-status=bot: unknown}}</ref> according to [[Crime statistics in the United Kingdom|UK crime statistics]].
[[United Kingdom labour law|UK labour laws]] establish employment rights including [[National Minimum Wage Act 1998|a minimum wage]], a minimum of 28 days annual holiday, parental leave, statutory sick pay and [[Pensions Act 2008|a pension]]. [[Same-sex marriage]] has been legal in England, Scotland, and Wales since 2014, and in [[Northern Ireland]] since 2020.<ref>{{cite web |last1=Wratten |first1=Marcus |title=Tom Allen to host vital new BBC show marking 10th anniversary of same-sex marriage |url=https://www.thepinknews.com/2023/07/03/tom-allen-bbc-my-big-gay-wedding-same-sex-marriage/ |website=PinkNews |date=3 July 2023 |access-date=2 September 2023 |archive-date=2 September 2023 |archive-url=https://web.archive.org/web/20230902195143/https://www.thepinknews.com/2023/07/03/tom-allen-bbc-my-big-gay-wedding-same-sex-marriage/ |url-status=live}}</ref> [[LGBT rights in the United Kingdom|LGBT equality]] in the United Kingdom is considered advanced by modern standards.<ref>{{Cite web |date=5 June 2023 |title=The 203 Worst (& Safest) Countries for LGBTQ+ Travel in 2023 |url=https://www.asherfergusson.com/lgbtq-travel-safety/ |access-date=20 August 2023 |website=Asher & Lyric |archive-date=10 September 2021 |archive-url=https://web.archive.org/web/20210910063408/https://www.asherfergusson.com/lgbtq-travel-safety/ |url-status=live}}</ref><ref>{{cite web |last1=R. Flores |first1=Andrew |title=Social Acceptance of LGBTI People in 175 Countries and Locations |url=https://williamsinstitute.law.ucla.edu/publications/global-acceptance-index-lgbt/ |website=Williams Institute |access-date=11 September 2023 |archive-date=13 September 2023 |archive-url=https://web.archive.org/web/20230913091254/https://williamsinstitute.law.ucla.edu/publications/global-acceptance-index-lgbt/ |url-status=live}}</ref>
Since leaving the [[European Union|EU]] most disputes under UK-EU agreements are addressed through consultation between the parties. If consultation fails to resolve the issue, either party can request [[arbitration]], typically at the [[Permanent Court of Arbitration|PCA]] in [[Peace Palace|The Hague]].<ref name="commission.europa.eu" /><ref>{{Cite web |title=Disputes under the Trade and Cooperation Agreement |date=November 2021 |url=https://www.instituteforgovernment.org.uk/explainer/disputes-trade-and-cooperation-agreement |access-date=26 January 2025 |publisher=Institute for Government}}</ref><ref>{{Cite web |title=Sandeel fishing ban to remain in place |date=2 May 2025 |url=https://www.bbc.co.uk/news/articles/ckgrwxxzxkjo |website=BBC |access-date=4 May 2025 |archive-url=https://web.archive.org/web/20250504203005/https://www.bbc.com/news/articles/ckgrwxxzxkjo |archive-date=4 May 2025}}</ref> The [[EU–UK Trade and Cooperation Agreement]] states that the UK and EU have to cooperate and negotiate with each other with 'full mutual respect and good faith', as defined by international law.<ref>{{Cite web |title=Good Faith in Public Law |date=20 January 2022 |url=https://www.law.ox.ac.uk/news/2022-01-20-good-faith-public-law |website=ox.ac.uk |access-date=13 May 2025 |archive-url=https://web.archive.org/web/20250513165454/https://www.law.ox.ac.uk/news/2022-01-20-good-faith-public-law |archive-date=13 May 2025}}</ref> Under the [[Windsor Framework]], [[Northern Ireland]] matters requiring interpretation of EU law go to the [[European Court of Justice|ECJ]], though the [[Stormont Brake]] can prevent new EU rules from taking effect.
== Economy ==
{{Main|Economy of the United Kingdom}}
{{Further|Economy of England|Economy of Scotland|Economy of Northern Ireland|Economy of Wales}}
[[File:Bank junction - 2020-09-20 (2).jpg|thumb|[[City of London]] skyline from at [[Bank Junction]]. [[London]] is Europe's largest financial centre.<ref>{{Cite web |last=Yanatma |first=Servet |date=16 March 2024 |title=Europe's top financial centres: Where's best to do business? |url=https://www.euronews.com/business/2024/03/16/europes-top-financial-centres-wheres-best-to-do-business |access-date=16 August 2025 |publisher=[[Euronews]] |quote=While the US dominates the upper end of the list, with New York taking the number one spot, London continues to lead in Europe.}}</ref>]]
The United Kingdom has a highly developed [[social market economy]].<ref>{{Cite journal |last1=Thane |first1=Pat |year=2019 |title=The Origins of the British Welfare State |journal=The Journal of Interdisciplinary History |volume=50 |issue=3 |pages=427–433 |doi=10.1162/jinh_a_01448 |s2cid=208223636 |doi-access=free}}</ref><ref name="ftms">{{cite web |last1=Griffiths |first1=Alan |last2=Wall |first2=Stuart |date=16 July 2011 |title=Applied Economics |url=http://www.ftms.edu.my/pdf/Download/UndergraduateStudent/BusinessEconomics/BC215001S%20-%20BE%20Key%20Text%20-%20Applied%20Economics.pdf |url-status=dead |archive-url=https://web.archive.org/web/20130620120524/http://www.ftms.edu.my/pdf/Download/UndergraduateStudent/BusinessEconomics/BC215001S%20-%20BE%20Key%20Text%20-%20Applied%20Economics.pdf |archive-date=20 June 2013 |access-date=25 September 2014}}</ref> With an estimated nominal [[gross domestic product]] (GDP) of £2.819 trillion in 2025,<ref name="IMFWEO.UK" /> it is the [[List of countries by GDP (nominal)|fifth-largest national economy]] in the world and the [[List of sovereign states in Europe by GDP (nominal)|second-largest]] in Europe. Its currency, the [[pound sterling]], is the [[Foreign exchange market#Most traded currencies by value|fourth-most-traded currency]] in the [[foreign exchange market]] and the world's fourth-largest [[reserve currency]], after the [[United States dollar]], the [[euro]] and the [[yen]].<ref>{{Cite web |title=World Currency Composition of Official Foreign Exchange Reserves |url=https://data.imf.org/regular.aspx?key=41175 |access-date=10 October 2021 |website=IMF Data |archive-date=12 May 2016 |archive-url=https://web.archive.org/web/20160512202858/https://data.imf.org/regular.aspx?key=41175 |url-status=live}}</ref> The pound sterling maintains its high nominal value through both its long history of stability and by never undergoing formal [[redenomination]]. Since 2022 the UK has been both the world's [[List of countries by exports|fourth-largest exporter]]<ref>{{Cite web |title=Exports of goods and services (BoP, current US$) |url=https://data.worldbank.org/indicator/BX.GSR.GNFS.CD?end=2024&most_recent_value_desc=true |access-date=22 September 2025 |website=[[World Bank]]}}</ref> and [[List of countries by imports|fourth-largest importer]]<ref>{{Cite web |title=Imports of goods and services (current US$) |url=https://data.worldbank.org/indicator/NE.IMP.GNFS.CD?most_recent_value_desc=true |access-date=22 September 2025 |website=[[World Bank]] |archive-date=13 September 2025 |archive-url=https://web.archive.org/web/20250913065521/https://data.worldbank.org/indicator/NE.IMP.GNFS.CD?most_recent_value_desc=true |url-status=live }}</ref> of goods and services. Despite having one of the highest levels of [[Income inequality in the United Kingdom|income inequality]] in the [[OECD]],<ref>{{Cite web |last1=Francis-Devine |first1=Brigid |title=House of Commons Research Briefing on Income inequality in the UK. |url=https://commonslibrary.parliament.uk/research-briefings/cbp-7484/ |url-status=live |archive-url=https://web.archive.org/web/20220210104536/https://commonslibrary.parliament.uk/research-briefings/cbp-7484/ |archive-date=10 February 2022 |access-date=1 July 2023 |website=UK Parliament}}</ref><ref>{{Cite web |title=Inequality – Income inequality – OECD Data |url=http://data.oecd.org/inequality/income-inequality.htm |archive-url=https://web.archive.org/web/20230629183322/https://data.oecd.org/inequality/income-inequality.htm |archive-date=29 June 2023 |access-date=3 July 2023 |website=theOECD}}</ref> the UK has a very high [[Human Development Index|HDI]] ranking, including when [[List of countries by inequality-adjusted Human Development Index|adjusted for inequality]]. As of 2025 the [[Unemployment in the United Kingdom|UK unemployment rate]] is 4.7%<ref>{{Cite web |last1=Labiak |first1=Mitchell |last2=Smith |first2=Oliver |date=17 July 2025 |title=UK jobs market weakens as unemployment rate rises |url=https://www.bbc.com/news/articles/cg754negn75o |access-date=25 September 2025 |website=www.bbc.com |language=en-GB |archive-date=15 September 2025 |archive-url=https://web.archive.org/web/20250915184829/https://www.bbc.com/news/articles/cg754negn75o |url-status=live }}</ref> and the annual [[List of countries by real GDP per capita growth|real GDP per head growth]] was 1.1%.<ref name="f919">{{cite web | title=GDP quarterly national accounts, UK | website=Office for National Statistics | date=2026 | url=https://www.ons.gov.uk/economy/grossdomesticproductgdp/bulletins/quarterlynationalaccounts/octobertodecember2025 | access-date=2026-04-24}}</ref>
[[HM Treasury]], led by the [[Chancellor of the Exchequer]], is responsible for developing and executing the government's [[public finance]] and [[economic policy]]. The [[Department for Business and Trade]] is responsible for business, international trade, and enterprise. The [[Bank of England]] is the UK's [[central bank]] and responsible for issuing notes and coins in the pound sterling. Banks in Scotland and Northern Ireland retain the right to issue their own notes, subject to retaining enough Bank of England notes in reserve to cover their issue.
=== Industries and services ===
[[File:Bank-of-England.jpg|thumb|The [[Bank of England]] is the [[central bank]] of the United Kingdom and the model on which most modern central banks have been based.]]
[[File:British Airways Concorde G-BOAC 03.jpg|thumb|[[Concorde]] was a [[Supersonic speed|supersonic]] airliner that reduced transatlantic flight time from 8 hours to 3.5 hours.<ref>{{Cite web |title=Celebrating Concorde |url=https://www.britishairways.com/en-gb/information/about-ba/history-and-heritage/celebrating-concorde |archive-url=https://web.archive.org/web/20230317103939/https://www.britishairways.com/en-gb/information/about-ba/history-and-heritage/celebrating-concorde |archive-date=17 March 2023 |access-date=30 March 2023}}</ref>]]
The [[Tertiary sector of the economy|service sector]] made up around 80 per cent of the UK's [[Gross value added|GVA]] in 2023.<ref>{{Cite web |last=Hutton |first=Georgina |date=3 October 2024 |title=Industries in the UK |url=https://commonslibrary.parliament.uk/research-briefings/cbp-8353/ |access-date=19 May 2025 |website=UK Parliament: House of Commons Library |archive-date=7 October 2021 |archive-url=https://web.archive.org/web/20211007134640/https://commonslibrary.parliament.uk/research-briefings/cbp-8353/ |url-status=live }}</ref> As of 2023 it is the world's [[List of countries by service exports|second-largest exporter of services]]<ref>{{Cite web |title=Service exports (BoP, current US$) |url=https://data.worldbank.org/indicator/BX.GSR.NFSV.CD?most_recent_value_desc=true&year_high_desc=false |access-date=19 May 2025 |website=World Bank Open Data |archive-date=17 March 2023 |archive-url=https://web.archive.org/web/20230317140633/https://data.worldbank.org/indicator/BX.GSR.NFSV.CD?most_recent_value_desc=true&year_high_desc=false |url-status=live }}</ref> and in 2024 was the world's largest net exporter of [[Financial services in the United Kingdom|financial services]].<ref>{{Cite web |date=15 January 2025 |title=UK leads world in financial services trade surplus |url=https://www.thecityuk.com/news/uk-leads-world-in-financial-services-trade-surplus/ |access-date=2 June 2025 |website=TheCityUK |language=en}}</ref> [[London]] is the world capital for foreign exchange trading, with a market share of 37.8 per cent in 2022 of the global turnover.<ref>{{Cite web |date=30 September 2025 |title=BIS Triennial Survey of Foreign Exchange and Over-The-Counter Interest Rate Derivatives Markets in April 2025 – UK Data |url=https://www.bankofengland.co.uk/news/2025/september/bis-triennial-survey-of-foreign-exchange-and-over-the-counter-interest-rate-derivatives-markets |access-date=7 December 2025 |publisher=Bank of England}}</ref> It is the largest urban economy in Europe<ref>{{Cite web |last=Florida |first=Richard |date=16 March 2017 |title=The Economic Power of Cities Compared to Nations |url=https://www.bloomberg.com/news/articles/2017-03-16/top-metros-have-more-economic-power-than-most-nations |url-status=live |archive-url=https://web.archive.org/web/20240308074221/https://www.bloomberg.com/news/articles/2017-03-16/top-metros-have-more-economic-power-than-most-nations |archive-date=8 March 2024 |access-date=22 February 2024 |website=Bloomberg}}</ref> and, alongside [[New York City|New York]], the city in the world most integrated with the [[World economy|global economy]].<ref>{{Cite web |title=World Cities 2024 |url=https://gawc.lboro.ac.uk/gawc-worlds/the-world-according-to-gawc/world-cities-2024/ |access-date=21 September 2025 |website=GaWC |language=en-US |archive-date=3 July 2025 |archive-url=https://web.archive.org/web/20250703071437/https://gawc.lboro.ac.uk/gawc-worlds/the-world-according-to-gawc/world-cities-2024/ |url-status=live }}</ref> London is also one of the world's leading financial centres, ranking second in the 2025 [[Global Financial Centres Index]].<ref name="www.longfinance.net">{{Cite web |title=GFCI 36 Rank - Long Finance |url=https://www.longfinance.net/programmes/financial-centre-futures/global-financial-centres-index/gfci-36-explore-the-data/gfci-36-rank/ |access-date=19 May 2025 |website=www.longfinance.net |archive-date=25 September 2024 |archive-url=https://web.archive.org/web/20240925155927/https://www.longfinance.net/programmes/financial-centre-futures/global-financial-centres-index/gfci-36-explore-the-data/gfci-36-rank/ |url-status=live }}</ref> [[Edinburgh]], the UK's second-largest financial centre, ranks 29th in the world in the same index.<ref name="www.longfinance.net" />
The [[Manufacturing in the United Kingdom|UK's manufacturing sector]] in 2024 was the world's [[List of countries by manufacturing output|10th-largest]] and Europe's fourth-largest by value output.<ref>{{Cite web |title=World Bank Open Data |url=https://data.worldbank.org/indicator/NV.IND.MANF.CD?most_recent_value_desc=true |access-date=5 August 2025 |website=World Bank Open Data |archive-date=7 January 2020 |archive-url=https://web.archive.org/web/20200107135049/https://data.worldbank.org/indicator/NV.IND.MANF.CD?most_recent_value_desc=true |url-status=live }}</ref> At the end of 2024 manufacturing in the United Kingdom accounted for 8 per cent of the workforce and 8.6 per cent of national economic output.<ref>{{Cite web |date=22 May 2025 |title=Manufacturing industries: Economic indicators |url=https://commonslibrary.parliament.uk/research-briefings/sn05206/ |access-date=1 June 2025 |website=House of Commons Library}}</ref> As reported in 2017 the [[East Midlands Manufacturing|East Midlands]] and [[West Midlands Manufacturing|West Midlands]] (at 12.6 and 11.8 per cent respectively) were the regions with the highest proportion of employees in manufacturing. [[London manufacturing|London's manufacturing sector]] had the lowest at 2.8 per cent.<ref>Hennik Research. [http://www.themanufacturer.com/wp-content/uploads/2017/01/Annual-Manufacturing-Report-2017-Final-Version.pdf ''Annual Manufacturing Report: 2017'' (Dec. 2016)] {{Webarchive|url=https://web.archive.org/web/20170131192050/http://www.themanufacturer.com/wp-content/uploads/2017/01/Annual-Manufacturing-Report-2017-Final-Version.pdf|date=31 January 2017}}</ref>
The [[Tourism in the United Kingdom|country's tourism sector]] is important to the British economy;<ref>{{Cite web |last1=Chan |first1=Kelvin |date=25 April 2023 |title=King Charles' coronation is bringing millions of tourists and a cash infusion to London but it probably won't save the British economy |url=https://fortune.com/2023/04/25/king-charles-coronation-tourists-money-london-british-economy/ |archive-url=https://web.archive.org/web/20230502144950/https://fortune.com/2023/04/25/king-charles-coronation-tourists-money-london-british-economy/ |archive-date=2 May 2023 |access-date=9 May 2023 |website=[[fortune.com]] |agency=The Associated Press}}</ref> The [[creative industries]] accounted for 5.9 per cent of the UK's GVA in 2019,<ref>{{Cite web |title=DCMS Economic Estimates 2019 (provisional): Gross Value Added |url=https://www.gov.uk/government/statistics/dcms-economic-estimates-2019-gross-value-added/dcms-economic-estimates-2019-provisional-gross-value-added |access-date=31 January 2023 |website=gov.uk |archive-date=31 January 2023 |archive-url=https://web.archive.org/web/20230131001226/https://www.gov.uk/government/statistics/dcms-economic-estimates-2019-gross-value-added/dcms-economic-estimates-2019-provisional-gross-value-added |url-status=live}}</ref> and contributed £111 billion to the UK economy in 2018.<ref>{{Cite web |year=2020 |title=UK's Creative Industries contributes almost £13 million to the UK economy every hour |url=https://www.gov.uk/government/news/uks-creative-industries-contributes-almost-13-million-to-the-uk-economy-every-hour |access-date=21 February 2023 |publisher=UK Government |archive-date=21 February 2023 |archive-url=https://web.archive.org/web/20230221131518/https://www.gov.uk/government/news/uks-creative-industries-contributes-almost-13-million-to-the-uk-economy-every-hour |url-status=live}}</ref> [[Lloyd's of London]], located in London, is the world's largest [[insurance]] and [[reinsurance]] market.<ref>{{Cite web |title=Lloyd's of London – value proposition |url=https://www.lloyds.com/about-lloyds/value-proposition-coverholder |archive-url=https://web.archive.org/web/20230227100951/https://www.lloyds.com/about-lloyds/value-proposition-coverholder |archive-date=27 February 2023 |website=Lloyd's of London}}</ref> [[WPP plc]] is one of the world's biggest advertising companies and also based in London.<ref>{{Cite web |title=Rankings 2025 - Creative 100 |url=https://www.warc.com/creative/rankings/creative-100 |website=WARC |access-date=12 June 2025 |archive-url=https://web.archive.org/web/20250612162216/https://www.warc.com/creative/rankings/creative-100 |archive-date=12 June 2025}}</ref> The UK is one of Europe's leading retail markets and its largest [[e-commerce]] market.<ref>{{Cite web |url=https://www.great.gov.uk/international/content/investment/sectors/retail/ |access-date=18 January 2024 |title=Retail |publisher=great.gov.uk |archive-date=18 January 2024 |archive-url=https://web.archive.org/web/20240118084416/https://www.great.gov.uk/international/content/investment/sectors/retail/ |url-status=live}}</ref> With [[Consumer spending|consumption expenditures]] of over US$2 trillion in 2023, it has the [[List of largest consumer markets|second-largest consumer market]] in Europe.<ref>{{Cite web |title=Households and NPISHs Final consumption expenditure (current US$) |url=https://data.worldbank.org/indicator/NE.CON.PRVT.CD?year_high_desc=true |access-date=17 August 2024 |website=World Bank Group |archive-date=12 June 2018 |archive-url=https://web.archive.org/web/20180612143614/https://data.worldbank.org/indicator/NE.CON.PRVT.CD?year_high_desc=true |url-status=live}}</ref> [[John Lewis Partnership|John Lewis]] is the UK's largest employee-owned business.<ref>{{Cite web |url=https://employeeownership.co.uk/resources/what-the-evidence-tells-us/ |access-date=18 January 2024 |title=Employee owned businesses - What the evidence tells us |archive-date=2 December 2023 |archive-url=https://web.archive.org/web/20231202155249/https://employeeownership.co.uk/resources/what-the-evidence-tells-us/ |url-status=live}}</ref>
The [[Automotive industry in the United Kingdom|British automotive industry]] generates £47 billion of exports (12 per cent of the UK's total exports of goods).<ref name="Auto Output 2025" /> In 2024 the UK produced 779,584 passenger vehicles and 125,649 commercial vehicles; 8 out of 10 cars produced in the UK are exported overseas.<ref name="Auto Output 2025">{{Cite web |date=15 May 2025 |title=SMMT Motor Industry Facts 2025 |url=https://www.smmt.co.uk/smmt-motor-industry-facts-2025/ |access-date=26 May 2025 |website=SMMT |archive-date=26 May 2025 |archive-url=https://web.archive.org/web/20250526074751/https://www.smmt.co.uk/smmt-motor-industry-facts-2025/ |url-status=live}}</ref> Britain is known for iconic cars like [[Mini Hatch|Mini]] and [[Jaguar Cars|Jaguar]],<ref>{{Cite web |date=19 November 2020 |title=Best British cars: Top 50 all-time greatest British-built cars revealed - page 2 |url=https://www.autoexpress.co.uk/best-cars-vans/351729/best-british-cars-top-50-all-time-greatest-british-built-cars-revealed/page-2 |access-date=9 March 2024 |website=Auto Express |archive-date=16 March 2024 |archive-url=https://web.archive.org/web/20240316184015/https://www.autoexpress.co.uk/best-cars-vans/351729/best-british-cars-top-50-all-time-greatest-british-built-cars-revealed/page-2 |url-status=live}}</ref> as well as luxury cars such as [[Rolls-Royce Motor Cars|Rolls-Royce]], [[Bentley]] and [[Range Rover]]. The UK is a major centre for engine manufacturing: 1.59 million engines were produced in 2024.<ref name="Auto Output 2025" /> It was the world's [[List of countries by engine exports|third-largest exporter of engines]] by value in 2023.<ref>{{Cite web |title=Combustion Engines |url=https://oec.world/en/profile/hs/combustion-engines |access-date=26 May 2025 |website=OEC - The Observatory of Economic Complexity |archive-date=26 May 2025 |archive-url=https://web.archive.org/web/20250526073421/https://oec.world/en/profile/hs/combustion-engines |url-status=live}}</ref> The [[Motorsport in the United Kingdom|UK motorsport]] industry has an annual turnover of around £10 billion.<ref>{{Cite web |year=2020 |title=UK motorsport industry in pole position for F1's 70th anniversary |url=https://www.gov.uk/government/news/uk-motorsport-industry-in-pole-position-for-f1s-70th-anniversary |access-date=19 February 2023 |publisher=UK Government |archive-date=19 February 2023 |archive-url=https://web.archive.org/web/20230219100712/https://www.gov.uk/government/news/uk-motorsport-industry-in-pole-position-for-f1s-70th-anniversary |url-status=live}}</ref> Seven of the eleven [[Formula One]] teams are based in the UK, with their technology being used in supercars and hypercars from [[McLaren Automotive|McLaren]], [[Aston Martin]] and [[Lotus Cars|Lotus]].{{Efn|Car brands here are classed as British based on several of the following criteria: historical heritage, cultural significance, design and engineering base, manufacturing location, headquarters location, UK registered company (even with overseas investors).}} The [[Aerospace industry in the United Kingdom|aerospace industry of the UK]] is the second-largest in the world<ref>{{cite web |title=United Kingdom - Country Commercial Guide: Aerospace and Defense |url=https://www.trade.gov/country-commercial-guides/united-kingdom-aerospace-and-defense |website=[[International Trade Administration]] |date=3 November 2023 |access-date=17 December 2024 |archive-date=12 June 2023 |archive-url=https://web.archive.org/web/20230612142750/https://www.trade.gov/country-commercial-guides/united-kingdom-aerospace-and-defense |url-status=live }}</ref> and has an annual turnover of around £30 billion.<ref>{{Cite news |last=Tovey |first=Alan |date=29 June 2016 |title=Britain's aerospace sector soars amid fears Brexit could clip its wings |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/business/2016/06/29/britains-aerospace-sector-soars-amid-fears-brexit-could-clip-its |url-status=live |url-access=subscription |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/business/2016/06/29/britains-aerospace-sector-soars-amid-fears-brexit-could-clip-its |archive-date=10 January 2022}}{{Cbignore}}</ref> The [[British space programme|UK space industry]] was worth £17.5 billion in 2020/21 and employed around 48,800 people.<ref>{{cite web |title=UK space sector income reaches £17.5 billion as jobs and services grow |url=https://www.ukspace.org/uk-space-sector-income-reaches-17-5-billion-as-jobs-and-services-grow/ |website=UKspace |date=27 March 2023}}</ref><ref>{{cite web |title=UK space sector income reaches £17.5 billion as jobs and services grow |url=https://www.gov.uk/government/news/uk-space-sector-income-reaches-175-billion-as-jobs-and-services-grow |website=gov.uk |date=29 March 2023 |access-date=10 August 2025}}</ref> The [[UK Space Agency]] has stated in 2023 that it is investing £1.6 billion in space-related projects.<ref>{{Cite web |url=https://www.gov.uk/government/news/new-funding-to-support-space-exploration-using-moon-resources-and-nuclear-power |title=New funding to support space exploration using Moon resources and nuclear power |access-date=11 March 2023 |archive-date=11 March 2023 |archive-url=https://web.archive.org/web/20230311195622/https://www.gov.uk/government/news/new-funding-to-support-space-exploration-using-moon-resources-and-nuclear-power}} <!-- (last checked 2023-03-11) --></ref>
The [[Agriculture in the United Kingdom|British agriculture industry]] is intensive, highly mechanised and efficient by European standards, producing approximately 60 per cent of the country's overall food requirements and 73 per cent of its indigenous food needs, utilising around 0.9 per cent of the labour force (292,000 workers).<ref>{{Cite web |title=UK Food Security Index 2024 |url=https://www.gov.uk/government/publications/uk-food-security-index-2024/uk-food-security-index-2024 |access-date=19 May 2024 |publisher=Department for the Environment Food & Rural Affairs |archive-date=18 May 2024 |archive-url=https://web.archive.org/web/20240518072412/https://www.gov.uk/government/publications/uk-food-security-index-2024/uk-food-security-index-2024 |url-status=live}};{{Cite web |title=Agricultural workforce in England at 1 June 2023 |url=https://www.gov.uk/government/statistics/agricultural-workforce-in-england-at-1-june/agricultural-workforce-in-england-at-1-june-2023 |access-date=19 May 2024 |publisher=Department for the Environment Food & Rural Affairs |archive-date=19 May 2024 |archive-url=https://web.archive.org/web/20240519211112/https://www.gov.uk/government/statistics/agricultural-workforce-in-england-at-1-june/agricultural-workforce-in-england-at-1-june-2023 |url-status=live}}</ref> Around two-thirds of production is devoted to [[livestock]] and one-third to [[arable crops]]. The UK retains a significant though much reduced fishing industry, with at least 49 per cent of UK fish sustainably caught in 2020.<ref>{{Cite web |url=https://jncc.gov.uk/our-work/ukbi-b2-sustainable-fisheries |title=Sustainable fisheries: fish stocks harvested within safe limits |website=JNCC |access-date=14 December 2024}}</ref> The UK marine natural capital assets were estimated to have a value of £211 billion in 2021.<ref>{{Cite web |title=Marine accounts, natural capital, UK: 2021 |date=6 April 2021 |url=https://www.ons.gov.uk/economy/environmentalaccounts/bulletins/marineaccountsnaturalcapitaluk/2021 |website=ONS |access-date=21 May 2025 |archive-url=https://web.archive.org/web/20250521071820/https://www.ons.gov.uk/economy/environmentalaccounts/bulletins/marineaccountsnaturalcapitaluk/2021 |archive-date=21 May 2025}}</ref> It is rich in a variety of other natural resources including coal, [[petroleum]], [[natural gas]], tin, limestone, iron ore, salt, clay, chalk, [[gypsum]], lead, and silica and has an abundance of arable land.<ref>{{Cite web |url=http://www.bgs.ac.uk/mineralsuk/mines/coal/home.html |title=Coal |website=BGS Minerals UK |access-date=7 July 2015 |archive-date=26 April 2009 |archive-url=https://web.archive.org/web/20090426141109/http://www.bgs.ac.uk/ |url-status=live}}</ref>
=== Science and technology ===
{{Main|Science and technology in the United Kingdom|Telecommunications in the United Kingdom}}
[[File:Cambridge Science Park Napp.jpg|thumb|The [[Cambridge Cluster]] is the most intensive research cluster for science and technology in the world.<ref>{{Cite book |last=WIPO |url=https://www.wipo.int/global_innovation_index/en/2022/index.html |title=Global Innovation Index 2022, 15th Edition |publisher=World Intellectual Property Organization |year=2022 |isbn=978-92-805-3432-0 |doi=10.34667/tind.46596 |access-date=16 November 2022 |archive-date=3 December 2022 |archive-url=https://web.archive.org/web/20221203061259/https://www.wipo.int/global_innovation_index/en/2022/index.html |url-status=live}}; {{Cite web |title=Global Innovation Index 2021 |url=https://www.wipo.int/global_innovation_index/en/2021 |access-date=5 March 2022 |website=[[World Intellectual Property Organization]] |publisher=[[United Nations]] |archive-date=5 March 2022 |archive-url=https://web.archive.org/web/20220305010458/https://www.wipo.int/global_innovation_index/en/2021/ |url-status=live}}; {{Cite web |title=Release of the Global Innovation Index 2020: Who Will Finance Innovation? |url=https://www.wipo.int/global_innovation_index/en/2020/index.html |access-date=2 September 2021 |website=World Intellectual Property Organization |archive-date=3 June 2021 |archive-url=https://web.archive.org/web/20210603121259/https://www.wipo.int/global_innovation_index/en/2020/index.html |url-status=live}}; {{Cite web |title=Global Innovation Index 2019 |url=https://www.wipo.int/global_innovation_index/en/2019/index.html |access-date=2 September 2021 |website=World Intellectual Property Organization |archive-date=2 September 2021 |archive-url=https://web.archive.org/web/20210902101818/https://www.wipo.int/global_innovation_index/en/2019/index.html |url-status=live}}; {{Cite web |title=RTD – Item |url=https://ec.europa.eu/newsroom/rtd/items/691898 |access-date=2 September 2021 |website=ec.europa.eu |archive-date=2 September 2021 |archive-url=https://web.archive.org/web/20210902140715/https://ec.europa.eu/newsroom/rtd/items/691898 |url-status=live}}</ref>]]
England and Scotland were leading centres of the [[Scientific Revolution]] from the 17th century.<ref>Gascoin, J. "A reappraisal of the role of the universities in the Scientific Revolution", in Lindberg, David C. and Westman, Robert S., eds (1990), ''Reappraisals of the Scientific Revolution''. Cambridge University Press. p. 248. {{ISBN|978-0-521-34804-1}}.</ref> The United Kingdom led the [[Industrial Revolution]] from the 18th century, and has continued to produce scientists and [[List of British engineers|engineers]] credited with [[List of British innovations and discoveries|important advances]].<ref>Reynolds, E.E.; Brasher, N.H. (1966). ''Britain in the Twentieth Century, 1900–1964''. Cambridge University Press. p. 336. {{OCLC|474197910}}</ref> Major theorists from the 17th and 18th centuries include [[Isaac Newton]], whose [[Newton's laws of motion|laws of motion]] and illumination of [[gravitation|gravity]] have been seen as a keystone of modern science;<ref>Burtt, E.A. (2003) 1924.[https://books.google.com/books?id=G9WBMa1Rz_kC&pg=PA207 ''The Metaphysical Foundations of Modern Science''] {{Webarchive|url=https://web.archive.org/web/20230326164803/https://books.google.com/books?id=G9WBMa1Rz_kC&pg=PA207 |date=26 March 2023 }}. Mineola, NY: Courier Dover. p. 207. {{ISBN|978-0-486-42551-1}}.</ref> from the 19th century [[Charles Darwin]], whose theory of [[evolution]] by [[natural selection]] was fundamental to the development of modern biology, and [[James Clerk Maxwell]], who formulated classical [[electromagnetic theory]]; and more recently [[Stephen Hawking]], who advanced major theories in the fields of [[cosmology]], [[quantum gravity]] and the investigation of [[black holes]].<ref>Hatt, C. (2006). [https://books.google.com/books?id=BVBvehqrAPQC ''Scientists and Their Discoveries''] {{Webarchive|url=https://web.archive.org/web/20230326164803/https://books.google.com/books?id=BVBvehqrAPQC |date=26 March 2023 }}. London: Evans Brothers. pp. 16, 30 and 46. {{ISBN|978-0-237-53195-9}}.</ref>
The [[Department for Science, Innovation and Technology]] (DSIT) is responsible for helping to develop and manage the UK's scientific, research, and technological outputs. Scientific research and development remains important in [[Universities in the United Kingdom|British universities]], with many establishing [[science park]]s to facilitate production and co-operation with industry.<ref>Castells, M.; Hall, P.; Hall, P.G. (2004). ''Technopoles of the World: the Making of Twenty-First-Century Industrial Complexes''. London: Routledge. pp. 98–100. {{ISBN|978-0-415-10015-1}}.</ref> In 2022, the UK produced [[List of countries by number of scientific and technical journal articles|6.0 per cent of the world's scientific research papers]] and had an 8.8 per cent share of scientific citations, the fourth and third highest among <abbr>G7</abbr> countries and Brazil, China, India, Russia, and South Korea. The UK ranked 1st among these countries for Field-Weighted Citation Impact.<ref>{{Cite web |title=International comparison of the UK research base, 2025 |url=https://www.gov.uk/government/publications/international-comparison-of-the-uk-research-base-2025/international-comparison-of-the-uk-research-base-2025 |access-date=2025-12-07 |website=GOV.UK |language=en}}</ref> Scientific journals produced in the UK include publications by the [[Royal Society]], ''[[Nature (journal)|Nature]]'', the ''[[BMJ|British Medical Journal]]'' and ''[[The Lancet]]''.<ref>{{Cite journal |last=McCook, Alison |year=2006 |title=Is peer review broken? |url=http://gaia.pge.utexas.edu/Good/Materials/scientist_02_28_2006.htm |journal=The Scientist |volume=20 |issue=2 |page=26 |archive-url=https://web.archive.org/web/20110816230933/http://gaia.pge.utexas.edu/Good/Materials/scientist_02_28_2006.htm |archive-date=16 August 2011 |access-date=22 June 2011}}</ref>
By 2024 the UK tech sector reached a value of US$1.2 trillion surpassing the combined values of the French and German sectors.<ref>{{Cite web |last=Greenberg |first=Elizabeth |date=2025-01-14 |title=UK Innovation Economy Worth a Combined $1.2 trillion |url=https://www.digit.fyi/uk-innovation-economy-worth-a-combined-1-2-trillion/ |access-date=2026-05-26 |publisher=Digit News |language=en |quote=Valued at $1.2 trillion collectively, the UK innovation ecosystem is worth more than the French and German ecosystems combined.}}</ref> Cambridge was named the number one university in the world for producing successful technology founders.<ref>{{Cite web |title=UK tech sector retains #1 spot in Europe and #3 in world as sector resilience brings continued growth |date=21 December 2022 |url=https://www.gov.uk/government/news/uk-tech-sector-retains-1-spot-in-europe-and-3-in-world-as-sector-resilience-brings-continued-growth |website=gov.uk |access-date=27 May 2025 |archive-url=https://web.archive.org/web/20250527173044/https://www.gov.uk/government/news/uk-tech-sector-retains-1-spot-in-europe-and-3-in-world-as-sector-resilience-brings-continued-growth |archive-date=27 May 2025}}</ref> The [[Artificial intelligence industry in the United Kingdom|UK's artificial intelligence industry]] is the largest in Europe by value<ref>{{Cite web |date=11 June 2024 |title=UK AI sector most valuable in Europe, new report reveals |url=https://www.holyrood.com/news/view,uk-ai-sector-most-valuable-in-europe-new-report-reveals |access-date=20 July 2025 |website=[[Holyrood (magazine)|Holyrood]] |language=en}}</ref> and the country ranked fifth globally in a 2026 report on artificial intelligence development by [[Stanford University]].<ref>{{Cite web |title=Which countries are leading in AI? {{!}} Stanford HAI |url=https://hai.stanford.edu/ai-index/global-vibrancy-tool |access-date=2026-05-09 |website=hai.stanford.edu |language=en}}</ref> The UK ranked 6th in the 2025 [[Global Innovation Index]].<ref>{{Cite web |title=GII Innovation Ecosystems & Data Explorer 2025 |url=https://www.wipo.int/gii-ranking/en/united-kingdom |access-date=16 October 2025 |website=WIPO}}</ref><ref>{{Cite book |last1=Dutta |first1=Soumitra |url=https://www.wipo.int/web-publications/global-innovation-index-2025/en/index.html |title=Global Innovation Index 2025: Innovation at a Crossroads |last2=Lanvin |first2=Bruno |publisher=[[World Intellectual Property Organization]] |year=2025 |isbn=978-92-805-3797-0 |page=19 |language=en |doi=10.34667/tind.58864 |access-date=17 October 2025}}</ref>
=== Transport ===
{{Main|Transport in the United Kingdom}}
{{further|Transport in England|Transport in Scotland|Transport in Wales|Transport in Northern Ireland}}
[[File:An LNER Azuma train on the East Coast Railway Line, geograph 6275180 by Walter Baxter.jpg|thumb|A high-speed [[East Coast Main Line]] train in [[Northumberland]], England]]
[[File:London City Airport Sunset.jpg|thumb|A plane taking off from [[London City Airport]]. [[Airports of London|London's airports]] make it the city with the [[List of busiest city airport systems by passenger traffic|busiest airport system]] in the world.]]
In the UK, all traffic [[Left- and right-hand traffic|drives on the left]], with distance and speed being measured in miles, yards and miles per hour (mph). All vehicles manufactured for use in the UK have the steering wheel situated on the right side of the vehicle. A radial road network totals {{Convert|29145|mi|km}} of main roads, {{Convert|2173|mi|km}} of motorways and {{Convert|213750|mi|km}} of paved roads.<ref name="factbook" /> The [[M25 motorway|M25]], encircling London, is the largest and busiest bypass in the world.<ref>{{Cite book |last=Moran |first=Joe |url=https://archive.org/details/readingeveryday00mora |title=Reading the Everyday |date=16 November 2005 |publisher=Routledge |isbn=978-1-134-37216-4 |page=[https://archive.org/details/readingeveryday00mora/page/n107 95] |url-access=limited}}</ref> In 2024 there were 41.7 million licensed vehicles in the UK.<ref>{{cite web |title=General facts and figures about roads and road use |url=https://www.racfoundation.org/motoring-faqs/mobility |access-date=31 May 2025 |archive-date=18 May 2025 |archive-url=https://web.archive.org/web/20250518191035/https://www.racfoundation.org/motoring-faqs/mobility}}</ref>
The UK has an extensive railway network of {{Convert|10072|mi|0|abbr=out}}. In Great Britain, the [[British Rail]] network [[privatisation of British Rail|was privatised]] between 1994 and 1997, followed by a rapid rise in passengers. [[Great British Railways]] is a planned state-owned public body that will oversee [[rail transport in Great Britain]]. The UK was ranked eighth amongst national European rail systems in the 2017 European Railway Performance Index assessing intensity of use, quality of service and safety.<ref>{{Cite web |last1=Sylvain Duranton |last2=Agnès Audier |last3=Joël Hazan |last4=Mads Peter Langhorn |last5=Vincent Gauche |date=18 April 2017 |title=The 2017 European Railway Performance Index |url=https://www.bcg.com/en-ch/publications/2017/transportation-travel-tourism-2017-european-railway-performance-index.aspx |publisher=Boston Consulting Group |access-date=4 February 2019 |archive-date=31 May 2020 |archive-url=https://web.archive.org/web/20200531104458/https://www.bcg.com/en-ch/publications/2017/transportation-travel-tourism-2017-european-railway-performance-index.aspx |url-status=live}}</ref>
A train runs directly from London to [[Paris]].<ref>{{Cite web |title=London to Paris Trains |url=https://www.eurostar.com/uk-en/train/london-to-paris |access-date=11 May 2024 |publisher=Eurostar |archive-url=https://web.archive.org/web/20240511114452/https://www.eurostar.com/uk-en/train/london-to-paris |archive-date=11 May 2024}}</ref> Called the [[Eurostar]], it travels through the [[Channel Tunnel]] under the [[English Channel]]. At 23.5 miles long, it is the world's longest undersea tunnel.<ref>{{Cite web |title=Channel Tunnel, Tunnel, Europe |url=https://www.britannica.com/topic/Channel-Tunnel |access-date=11 May 2024 |publisher=Britannica |date=10 May 2024}}</ref> There is also a car service through the tunnel to France called [[LeShuttle]]. The [[Elizabeth line]], a rail link running between [[East London|East]] and [[West London]], was named in honour of [[Queen Elizabeth II]] in 2016 and opened in 2022.<ref>{{Cite news |date=2 January 2012 |title=Crossrail's giant tunnelling machines unveiled |work=BBC News |url=https://www.bbc.co.uk/news/av/uk-16289051 |access-date=20 June 2018 |archive-date=10 April 2016 |archive-url=https://web.archive.org/web/20160410034914/http://www.bbc.co.uk/news/uk-16289051 |url-status=live}}; {{Cite news |last=Leftly |first=Mark |date=29 August 2010 |title=Crossrail delayed to save £1bn |work=Independent |location=London |url=https://www.independent.co.uk/news/business/news/crossrail-delayed-to-save-1631bn-2064629.html |access-date=22 August 2017 |archive-date=16 November 2020 |archive-url=https://web.archive.org/web/20201116062835/https://www.independent.co.uk/news/business/news/crossrail-delayed-to-save-1631bn-2064629.html |url-status=live}}</ref><ref>{{Cite web |title=Crossrail to become the Elizabeth line in honour of Her Majesty the Queen |url=https://tfl.gov.uk/info-for/media/press-releases/2016/february/crossrail-to-become-the-elizabeth-line-in-honour-of-her-majesty-the-queen |archive-url=https://web.archive.org/web/20230225110413/https://tfl.gov.uk/info-for/media/press-releases/2016/february/crossrail-to-become-the-elizabeth-line-in-honour-of-her-majesty-the-queen |archive-date=25 February 2023 |website=Transport for London}}</ref> Another major infrastructure project is [[High Speed 2]] (HS2), a high-speed railway under construction since 2019. It will link London with [[Birmingham]], with the potential to extend further north and capable of speeds of up to 225 mph.<ref>{{Cite web |title=What is HS2 |url=https://www.hs2.org.uk/what-is-hs2 |website=HS2 |access-date=22 June 2022 |archive-date=21 June 2022 |archive-url=https://web.archive.org/web/20220621190841/https://www.hs2.org.uk/what-is-hs2/ |url-status=live}}</ref><ref>{{Cite web |title=HS2 Trains |url=https://www.hs2.org.uk/building-hs2/trains/ |website=HS2 |access-date=24 February 2023 |archive-date=24 February 2023 |archive-url=https://web.archive.org/web/20230224183953/https://www.hs2.org.uk/building-hs2/trains/ |url-status=live}}</ref>
In 2023 there were 4 billion bus journeys in the UK, 1.8 billion of which were in London.<ref>{{Cite web |title=Transport Statistics Great Britain: 2023 Domestic Travel |date=19 December 2024 |url=https://www.gov.uk/government/statistics/transport-statistics-great-britain-2024/transport-statistics-great-britain-2023-domestic-travel |website=gov.uk |access-date=14 March 2025}}</ref> The red [[Double-decker bus|double-decker]] bus has entered popular culture as an internationally recognised icon of London and England.<ref>{{Cite web |title=Our Collection |url=http://www.icons.org.uk/theicons/index.html |access-date=16 August 2014 |publisher=icons.org.uk}}</ref> The [[London Buses|London bus network]] is extensive, with over 6,800 scheduled services every weekday carrying about 6 million passengers on over 700 different routes, making it one of the most extensive bus systems in the world and the largest in Europe.<ref>[http://www.tfl.gov.uk/corporate/modesoftransport/1548.aspx London Buses], Transport for London. Accessed 10 May 2007.</ref>
During 2024 [[List of airports in the United Kingdom and the British Crown Dependencies|British airports]] handled nearly 292.5 million passengers.<ref name="caastats">{{Cite web |title=Size of Reporting Airports 2024 |url=https://www.caa.co.uk/Documents/Download/11910/4d230d1f-dab6-4c1a-992a-431b9cca89a2/16918 |access-date=17 January 2025 |publisher=Civil Aviation Authority}}</ref> In that period the three largest airports were [[London Heathrow Airport]] (83.9 million passengers), [[Gatwick Airport]] (43.2 million passengers) and [[Manchester Airport]] (30.8 million passengers).<ref name="caastats" /> London Heathrow Airport, located {{Convert|15|mi|km|}} west of the capital, is the world's [[List of busiest airports by passenger traffic|second-busiest airport by international passenger traffic]] and has the most international passenger traffic of any airport in the world;<ref>{{Cite news |date=25 June 2008 |title=Heathrow 'needs a third runway' |work=BBC News |url=http://news.bbc.co.uk/1/hi/business/7472432.stm |access-date=17 October 2008}}; {{Cite press release |title=Statistics: Top 30 World airports |date=July 2008 |publisher=Airports Council International |url=http://www.aci.aero/aci/aci/file/Press%20Releases/2008/TOP30_International%20Passengers_2007.pdf |access-date=15 October 2008}}</ref> it is the hub for the UK flag carrier [[British Airways]], as well as [[Virgin Atlantic]].<ref>{{Cite news |date=29 October 2008 |title=BMI being taken over by Lufthansa |work=BBC News |url=http://news.bbc.co.uk/2/hi/7697261.stm |access-date=23 December 2009}}</ref> During 2023, 18.3 million passengers travelled internationally by rail and 18.1 million by sea.<ref>{{Cite web |title=Transport Statistics Great Britain: 2023 International Travel |date=19 December 2024 |url=https://www.gov.uk/government/statistics/transport-statistics-great-britain-2024/transport-statistics-great-britain-2023-international-travel |website=gov.uk |access-date=4 March 2025}}</ref>
=== Energy ===
{{Main|Energy in the United Kingdom}}
{{further|Energy in England|Energy in Scotland|Energy in Wales|Energy in Northern Ireland}}
In 2021 the UK was the world's [[List of countries by energy consumption and production|14th-largest consumer and 22nd-largest producer of energy]].<ref name="United Kingdom Energy Profile">{{Cite web |title=United Kingdom Energy Profile |url=https://www.eia.gov/international/overview/country/GBR |archive-url=https://web.archive.org/web/20230228165225/https://www.eia.gov/international/overview/country/GBR |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=U.S. Energy Information Administration}}</ref> It is home to [[Big Six energy suppliers|many large energy companies]], including two of the six major oil and gas companies{{snd}}[[BP]] and [[Shell plc|Shell]].<ref>{{Cite news |last=Mason |first=Rowena |date=24 October 2009 |title=Let the battle begin over black gold |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/finance/newsbysector/energy/6424030/Let-the-battle-begin-over-black-gold.html |url-status=live |url-access=subscription |access-date=26 November 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/finance/newsbysector/energy/6424030/Let-the-battle-begin-over-black-gold.html |archive-date=10 January 2022}}{{Cbignore}}; {{Cite news |last=Heath |first=Michael |date=26 November 2010 |title=RBA Says Currency Containing Prices, Rate Level 'Appropriate' in Near Term |work=Bloomberg |location=New York |url=https://www.bloomberg.com/news/2010-11-25/rba-s-stevens-says-inflation-unlikely-to-fall-much-further.html |access-date=26 November 2010}}</ref>
[[File:Ardrossan's fan club. - panoramio.jpg|thumb|Wind turbines overlooking [[Ardrossan]] in Scotland. The UK is [[Wind power in the United Kingdom|a major producer of wind energy]] in Europe.<ref>{{Cite web |date=13 September 2023 |title='Success story': Which European countries are leading the way on wind? |url=https://www.euronews.com/green/2023/09/13/winds-of-change-which-european-countries-are-generating-the-most-energy-from-wind |access-date=15 August 2025 |website=[[Euronews]] |language=en}}</ref>]]
Renewable electricity sources provided 51 per cent of the electricity generated in the UK in 2024. [[Wind power in the United Kingdom|Wind power]] was the largest source of electricity in 2024, generating 30 per cent of the UK's total electricity.<ref name="2024 Energy">{{Cite report |title=Britain's Electricity Explained: 2024 Review |url=https://www.neso.energy/news/britains-electricity-explained-2024-review |archive-url=https://web.archive.org/web/20250126085830/https://www.neso.energy/news/britains-electricity-explained-2024-review |archive-date=26 January 2025 |access-date=26 January 2025 |publisher=NESO}}</ref> The UK has the largest offshore wind farm in the world, which is located off the coast of [[Yorkshire]].<ref>{{Cite report |date=14 June 2021 |title=Wind energy in the UK: June 2021 |work=UK Government |url=https://www.ons.gov.uk/economy/environmentalaccounts/articles/windenergyintheuk/june2021 |access-date=8 May 2023}}</ref>
In 2023 the UK had nine nuclear reactors generating about 15 per cent of the UK's electricity.<ref name="coal-ref">{{Cite web |title=Nuclear Power in the United Kingdom |url=https://world-nuclear.org/information-library/country-profiles/countries-t-z/united-kingdom.aspx |archive-url=https://web.archive.org/web/20230228175735/https://world-nuclear.org/information-library/country-profiles/countries-t-z/united-kingdom.aspx |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=World Nuclear Association}}</ref> There are two reactors under construction and more planned.<ref>{{Cite web |date=April 2013 |title=Nuclear Power in the United Kingdom |url=http://www.world-nuclear.org/info/inf84.html |archive-url=https://web.archive.org/web/20130214061431/http://www.world-nuclear.org/info/inf84.html |archive-date=14 February 2013 |access-date=9 April 2013 |publisher=World Nuclear Association}}</ref><ref>{{Cite news |title=Nuclear energy: What you need to know |url=https://www.gov.uk/government/news/nuclear-energy-what-you-need-to-know |archive-url=https://web.archive.org/web/20230228181113/https://www.gov.uk/government/news/nuclear-energy-what-you-need-to-know |archive-date=28 February 2023 |access-date=28 February 2023 |publisher=UK Government}}</ref> In the late 1990s [[Nuclear power plants in the United Kingdom|nuclear power plants]] contributed around 25 per cent of the total annual electricity generation in the UK, but this has gradually declined as old plants have been shut down. The UK government is investing in [[small modular reactors]] that operate via [[nuclear fission]], as well as in research and development towards commercial [[fusion reactors]]. To that end the government entered into a partnership with the US in late 2023 to collaborate on fusion technology, with "a commercial grid-ready fusion reactor by 2040" stated as a goal.<ref>{{Cite news |title=UKAEA implementing the UK's fusion energy strategy |work=Open Access Government |date=7 March 2024 |url=https://www.openaccessgovernment.org/ukaea-implementing-the-uks-fusion-energy-strategy/174384/ |access-date=27 May 2024 |last1=Belderbos |first1=Harriet}};{{Cite magazine |title=UK nuclear fusion reactor sets new world record for energy output |url=https://www.newscientist.com/article/2415909-uk-nuclear-fusion-reactor-sets-new-world-record-for-energy-output/ |magazine=New Scientist |access-date=27 May 2024}}</ref>
At the end of 2023 it was estimated that there were 1.1 billion [[barrels of oil equivalent]] of "proven" and "probable" [[Oil and gas reserves and resource quantification|gas reserves]] and 2.3 billion boe of "proven" and "probable" [[North Sea oil|oil reserves]] offshore, reducing reliance on imports for energy security and transitioning to renewables.<ref>{{Cite report |title=UK Oil and Gas Reserves and Resources |url=https://www.nstauthority.co.uk/media/vtjkyqnf/uk-reserves-and-resources-report-as-at-end-2023.pdf |archive-url=https://web.archive.org/web/20250113172052/https://www.nstauthority.co.uk/media/vtjkyqnf/uk-reserves-and-resources-report-as-at-end-2023.pdf |archive-date=13 January 2025 |access-date=1 February 2025 |publisher=North Sea Transition Authority}}</ref> Emissions from UK gas production are roughly four times lower than imported [[liquefied natural gas]] (LNG), according to the [[North Sea Transition Authority|UK's oil and gas regulator]].<ref>{{Cite news |title=North Sea oil and gas claims fact-checked |work=BBC |date=22 January 2024 |url=https://www.bbc.co.uk/news/science-environment-67945281 |archive-url=https://web.archive.org/web/20250201182137/https://www.bbc.com/news/science-environment-67945281 |archive-date=1 February 2025 |access-date=1 February 2025}}</ref>
In September 2024 the last coal power station was closed, making [[coal]] no longer a power source in the UK.<ref name="2024 Energy" /> The UK currently has no [[fracking]] (hydraulic fracturing) for [[shale gas]] despite a large supply, due to environmental concerns.<ref>{{Cite news |title=UK's last fracking wells to be filled with cement despite dwindling gas stocks |date=29 January 2025 |url=https://www.cityam.com/uks-last-fracking-wells-to-be-filled-with-cement-despite-dwindling-gas-stocks/ |archive-url=https://web.archive.org/web/20250201182917/https://www.cityam.com/uks-last-fracking-wells-to-be-filled-with-cement-despite-dwindling-gas-stocks/ |archive-date=1 February 2025 |access-date=1 February 2025 |work=City AM}}</ref>
=== Water supply and sanitation ===
{{Main|Water supply and sanitation in the United Kingdom}}
Access to improved water supply and sanitation in the UK is universal. It was estimated that 96 per cent of households were connected to the sewer network in 2022.<ref>{{Cite web |url=https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/69582/pb6655-uk-sewage-treatment-020424.pdf |title=Sewage Treatment in the UK |publisher=DEFRA |website=assets.publishing.service.gov.uk |date=March 2022 |page=3 |id=PB 6655 |access-date=8 April 2023}}</ref> According to the [[Environment Agency]], total water abstraction for public water supply in the UK was 16,406 [[megalitre]]s per day in 2007.<ref>{{Cite web |title=Environment Agency |url=http://www.environment-agency.gov.uk/research/library/data/112185.aspx |archive-url=https://web.archive.org/web/20091125040346/http://www.environment-agency.gov.uk/research/library/data/112185.aspx |archive-date=25 November 2009}}</ref>
In England and Wales, water and sewerage services are provided by 10 private regional water and sewerage companies and 13 mostly smaller private "water only" companies. In Scotland, said services are provided by a single public company, [[Scottish Water]]. In Northern Ireland, they are also provided by a single public entity, [[Northern Ireland Water]].<ref>{{Cite web |title=About Us |url=https://www.niwater.com/about |access-date=29 August 2020 |publisher=niwater.com}}</ref>
== Demographics ==
{{Main|Demographics of the United Kingdom|British people}}
{{Further|Ceremonial counties of England|Subdivisions of Scotland|Subdivisions of Wales|Counties of Northern Ireland}}
[[File:Elderly British Couple.jpg|thumb|261x261px|An elderly British Couple. Approximately 24% of people in England and Wales are aged 60 years and over.<ref>{{Cite web |date=2023-03-31 |title=Age groups |url=https://www.ethnicity-facts-figures.service.gov.uk/uk-population-by-ethnicity/demographics/age-groups/latest/#main-facts-and-figures |access-date=2026-08-16 |website=www.ethnicity-facts-figures.service.gov.uk |language=en}}</ref>]]
Whereas the censuses of England and Wales and of Northern Ireland went ahead as planned in 2021, the census in Scotland was delayed until 2022 due to the COVID-19 pandemic. The Office for National Statistics has estimated that the total population of the United Kingdom recorded in the census would have been 66,912,637 had it been conducted in all parts of the UK on 21 March 2021.<ref name=Ethnicity2021/> The UK population is the [[List of European countries by population|fourth-largest]] in Europe and the [[List of countries by population|22nd-largest]] in the world. In 2012 and 2013 births contributed the most to population growth, while in 2014 and 2015 net international migration contributed more.<ref name="pop2015">{{Cite web |date=23 June 2016 |title=Population Estimates for UK, England and Wales, Scotland and Northern Ireland, Mid-2015 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/bulletins/annualmidyearpopulationestimates/latest |publisher=Office for National Statistics}}</ref> Between 2001 and 2011 the population increased at an average annual rate of 0.7 per cent.<ref name="2011census">{{Cite web |date=21 December 2022 |title=Population estimates for the UK, England, Wales, Scotland and Northern Ireland: mid-2021 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/bulletins/annualmidyearpopulationestimates/mid2021 |access-date=16 April 2025 |publisher=Office for National Statistics}}</ref> The [[2011 United Kingdom census|2011 census]] also showed that, over the previous 100 years, the proportion of the population aged 0–14 fell from 31 to 18 per cent, and the proportion of people aged 65 and over rose from 5 to 16 per cent.<ref name="2011census" /> In 2018 the [[median age]] of the UK population was 41.7 years.<ref name="factbook" /> The 2021 census put Scotland's population at 5.48 million, Wales's at 3.1 million and Northern Ireland's at 1.9 million.<ref name="2011census" />
<!-- Self-maintaining population table -->
{{UK population table}}
England's population in 2021 was 56 million, representing some 84 per cent of the UK total.<ref name="2011census" /> England is one of the [[List of countries and dependencies by population density|most-densely-populated countries]] in the world, with 434 people per square kilometre in mid-2021,<ref name="2011census" /> with a particular concentration in London, the capital,<ref>{{Cite news |date=2012-05-10 |title=United Kingdom country profile |url=https://www.bbc.co.uk/news/world-europe-18023389 |access-date=2026-07-24 |work=BBC News |language=en-GB}}</ref><ref>{{Cite web |title=United Kingdom - Country Profile {{!}} OpenFactBook World Factbook |url=https://openfactbook.org/countries/united-kingdom/ |access-date=2026-07-24 |website=openfactbook.org |language=en}}</ref> and the south-east.<ref>{{Cite news |last=Khan |first=Urmee |date=16 September 2008 |title=England is most crowded country in Europe |url=https://www.telegraph.co.uk/news/newstopics/politics/2967374/England-is-most-crowded-country-in-Europe.html |archive-url=https://web.archive.org/web/20080918221002/http://www.telegraph.co.uk/news/newstopics/politics/2967374/England-is-most-crowded-country-in-Europe.html |archive-date=18 September 2008 |access-date=5 September 2009 |work=The Telegraph |location=London}}</ref> [[London metropolitan area|London's wider metropolitan area]] is the largest in [[Western Europe]], with a population of 14.9 million in 2024.<ref>{{Cite web |title=Major Agglomerations |url=http://citypopulation.de/en/world/agglomerations |url-status=live |archive-url=https://web.archive.org/web/20231004094531/https://www.citypopulation.de/en/world/agglomerations/ |archive-date=4 October 2023 |access-date=16 October 2023}}</ref>
{| class="wikitable sortable" style="text-align:right;"
|+ Population of England by region ({{UK subdivision statistics year}})<ref name="ONS mid-year pop est" />
|-
! Rowspan=2 | Region
! Colspan=2 | Land area
! Colspan=2 | Population
! Rowspan=2 | Density<br />(/km<sup>2</sup>)
|-
! (km<sup>2</sup>)
! (%)
! People
! (%)
|-
| style="text-align:left;" | [[North East England|North East]]
| 8,581
| 6%
| 2,683,040
| 5%
| 313
|-
| style="text-align:left;" | [[North West England|North West]]
| 14,108
| 11%
| 7,516,113
| 13%
| 533
|-
| style="text-align:left;" | [[Yorkshire and the Humber]]
| 15,404
| 12%
| 5,541,262
| 10%
| 360
|-
| style="text-align:left;" | [[East Midlands]]
| 15,624
| 12%
| 4,934,939
| 9%
| 316
|-
| style="text-align:left;" | [[West Midlands (region)|West Midlands]]
| 12,998
| 10%
| 6,021,653
| 11%
| 463
|-
| style="text-align:left;" | [[East of England]]
| 19,116
| 15%
| 6,398,497
| 11%
| 335
|-
| style="text-align:left;" | [[Greater London]]
| 1,572
| 1%
| 8,866,180
| 15%
| 5,640
|-
| style="text-align:left;" | [[South East England|South East]]
| 19,072
| 15%
| 9,379,833
| 16%
| 492
|-
| style="text-align:left;" | [[South West England|South West]]
| 23,836
| 18%
| 5,764,881
| 10%
| 242
|-
! style="text-align:left;" | England
! style="text-align:right;" | 130,310
! style="text-align:right;" | 100%
! style="text-align:right;" | 57,106,398
! style="text-align:right;" | 100%
! style="text-align:right;" | 438
|}
In 2021 the [[total fertility rate]] across the UK was 1.53 children born per woman,<ref>{{Cite web |title=Vital statistics: population and health reference tables |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationestimates/datasets/vitalstatisticspopulationandhealthreferencetables |access-date=6 March 2018 |website=Office for National Statistics}}</ref> which remains considerably below the [[Mid-20th century baby boom|baby boom]] peak of 2.95 children per woman in 1964,<ref>{{Cite news |last=Boseley |first=Sarah |date=14 July 2008 |title=The question: What's behind the baby boom? |url=https://www.theguardian.com/lifeandstyle/2008/jul/14/familyandrelationships.women |access-date=28 August 2009 |work=The Guardian |location=London |page=3}}</ref> or the high of 6.02 children born per woman in 1815<ref>{{Citation |last=Roser |first=Max |title=Total Fertility Rate around the world over the last centuries |date=2014 |work=[[Our World in Data]], [[Gapminder Foundation]] |url=https://ourworldindata.org/grapher/children-born-per-woman?year=1800&country=GBR |access-date=10 December 2019 |archive-url=https://web.archive.org/web/20190705121623/https://ourworldindata.org/grapher/children-born-per-woman?year=1800&country=GBR |archive-date=5 July 2019}}</ref> and below the replacement rate of 2.1. In 2011, 47.3 per cent of births in the UK were to unmarried women.<ref>[http://epp.eurostat.ec.europa.eu/tgm/table.do?tab=table&plugin=0&language=en&pcode=tps00018 Tables, Graphs and Maps Interface (TGM) table]. Eurostat (26 February 2013). Retrieved 12 July 2013.</ref> The [[Office for National Statistics]] reported in 2015 that amongst the UK population aged 16 and over, 1.7 per cent identify as gay, lesbian, or bisexual (2.0 per cent of males and 1.5 per cent of females); 4.5 per cent of respondents responded with "other", "I don't know", or did not respond.<ref>{{Cite web |date=5 October 2016 |title=Sexual identity, UK: 2015 – Experimental Official Statistics on sexual identity in the UK in 2015 by region, sex, age, marital status, ethnicity and NS-SEC |url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/sexuality/bulletins/sexualidentityuk/2015 |access-date=19 January 2017 |publisher=[[Office for National Statistics]]}}</ref> The number of [[transgender]] people in the UK was estimated to be between 65,000 and 300,000 by research between 2001 and 2008.<ref>{{Cite web |title=Research report 27: Trans research review |url=http://www.equalityhumanrights.com/about-us/our-work/key-projects/trans-inequalities-reviewed/introduction-to-the-review |url-status=dead |archive-url=https://web.archive.org/web/20150706020643/http://www.equalityhumanrights.com/about-us/our-work/key-projects/trans-inequalities-reviewed/introduction-to-the-review |archive-date=6 July 2015 |access-date=26 November 2021 |website=equalityhumanrights.com |page=v}}</ref>
{{Largest Urban Areas of the United Kingdom}}
=== Ethnicity ===
{{Main|Ethnic groups in the United Kingdom}}
Historically, indigenous British people were thought to be [[Genetic history of the British Isles|descended from ethnic groups]] that settled there before the 12th century: the [[Celts]], Romans, Anglo-Saxons, Norse and the [[Normans]]. [[Welsh people]] could be the oldest ethnic group in the UK.<ref>{{Cite news |date=19 June 2012 |title=Welsh people could be most ancient in UK, DNA suggests |url=https://www.bbc.co.uk/news/uk-wales-18489735 |access-date=28 April 2013 |work=BBC News}}</ref> The UK has a history of non-white immigration with [[Liverpool]] having the oldest black population in the country dating from at least the 1730s,<ref>{{Cite book |last=Winder |first=Robert |url=https://books.google.com/books?id=7ORcaQIgdcEC&q=combed&pg=PT94 |title=Bloody Foreigners: The Story of Immigration to Britain |date=2010 |publisher=Little, Brown Book |isbn=978-0-7481-2396-4}}; {{Cite book |last=Costello |first=Ray |title=Black Liverpool: The Early History of Britain's Oldest Black Community 1730–1918 |date=2001 |publisher=Picton Press |isbn=978-1-873245-07-1 |location=Liverpool}}</ref> in addition to having the oldest [[British Chinese|Chinese]] community in Europe dating from the 19th century.<ref>{{Cite web |title=Culture and Ethnicity Differences in Liverpool – Chinese Community |url=http://www.mersey-gateway.org/server.php?show=ConWebDoc.1369 |archive-url=https://web.archive.org/web/20090724204513/http://www.mersey-gateway.org/server.php?show=ConWebDoc.1369 |archive-date=24 July 2009 |access-date=9 March 2015 |publisher=Chambré Hardman Trust}}</ref>
In 2021, 83.1 per cent of the UK population was classified as white, 8.6 per cent as Asian or Asian British, 3.7 per cent as Black or Black British, 2.7 per cent as mixed ethnicity, and 2.0 per cent other.<ref name=Ethnicity2021/> Ethnic diversity varies significantly across the UK. In 2021, 46.2 per cent of London's population was from a non-white ethnic minority,<ref name=Regionaldiversity>{{cite news|url=https://www.ethnicity-facts-figures.service.gov.uk/uk-population-by-ethnicity/national-and-regional-populations/regional-ethnic-diversity/latest/|title=Regional ethnic diversity|publisher=Office for National Statistics|date=22 December 2022|access-date=28 March 2026}}</ref> compared less than 10 per cent in the South West and North East of England, Wales,<ref name=Regionaldiversity/> Scotland<ref>{{cite news|url=https://www.scotlandscensus.gov.uk/census-results/at-a-glance/ethnicity/|title=Ethnicity|publisher=National Records of Scotland|date=4 February 2025|access-date=28 March 2026}}</ref> and Northern Ireland.<ref>{{cite web|url=https://www.nisra.gov.uk/system/files/statistics/census-2021-ms-b01.xlsx|title=MS-B01: Ethnic group|publisher=Northern Ireland Statistics and Research Agency|date=30 November 2023|access-date=28 March 2026}}</ref>
=== Language ===
{{Main|Languages of the United Kingdom}}
The [[English language]] is the ''[[de facto]]'' official and most widely spoken language in the United Kingdom.<ref>{{Cite web |title=English language – Government, citizens and rights |url=http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012519 |archive-url=http://webarchive.nationalarchives.gov.uk/20121015000000/http://www.direct.gov.uk/en/Governmentcitizensandrights/LivingintheUK/DG_10012519 |archive-date=15 October 2012 |access-date=23 August 2011 |website=[[Directgov]]}}</ref><ref>{{Cite journal |last=Mac Sithigh |first=Daithí |date=17 May 2018 |title=Official status of languages in the UK and Ireland |url=https://pureadmin.qub.ac.uk/ws/portalfiles/portal/141540053/Status_OA_Feb_2018.pdf |journal=Common Law World Review |publisher=Queen's University, Belfast |volume=47 |issue=1 |pages=77–102 |doi=10.1177/1473779518773642 |s2cid=219987922}}</ref> The UK promotes the language globally to build connections, understanding and trust between people in the UK and countries worldwide.<ref>British Council {{Cite web |title=British Council | the UK's international culture and education organisation |url=https://www.britishcouncil.org/ |url-status=live |archive-url=https://web.archive.org/web/20230201181104/https://www.britishcouncil.org/ |archive-date=1 February 2023 |access-date=5 December 2018}} (last checked 6 February 2023)</ref><ref>{{Cite web |title=About BBC Learning English |url=https://www.bbc.com/learningenglish/english/hygiene |url-status=live |archive-url=https://web.archive.org/web/20230204204233/https://www.bbc.com/learningenglish/english/hygiene |archive-date=4 February 2023 |access-date=9 February 2023 |website=BBC}}</ref>
In the UK, the English language is spoken with distinctive characteristics that collectively form what is known as [[British English]]. The variety of dialects and accents is often noted, with nearby regions frequently having highly distinct variations. [[Received Pronunciation]] is traditionally associated with educated speakers in southern England.<ref>{{Cite web |title=British English Pronunciations |url=https://www.oed.com/information/understanding-entries/pronunciation/british-english-pronunciations/?tl=true |archive-url=https://web.archive.org/web/20250605075115/https://www.oed.com/information/understanding-entries/pronunciation/british-english-pronunciations/?tl=true |archive-date=5 June 2025 |access-date=5 June 2025 |website=OED}}</ref> The main national dialects are [[Scottish English]], [[Welsh English]] and [[Northern Irish English]]. Distinctive regional varieties include
[[Brummie dialect|Brummie]], [[Cockney]], [[Geordie]], [[Manchester dialect|Mancunian]], [[Scouse]], [[West Country English|West Country]], [[Yorkshire dialect|Yorkshire]] and [[Multicultural London English|MLE]] (Multicultural London English).<ref>{{Cite web |title=10 British dialects you need to know |url=https://www.ef.com/wwen/blog/language/british-dialects-you-need-to-know/ |website=EF |access-date=5 June 2025}}</ref>
[[File:Bilingual welcome sign Newry.jpg|thumb|[[Bilingual sign]] ([[Irish language|Irish]] and [[English language|English]]) in [[Newry]], Northern Ireland]]Three indigenous [[Celtic languages]] are spoken in the UK: [[Welsh language|Welsh]], [[Irish language|Irish]] and [[Scottish Gaelic]]. [[Cornish language|Cornish]], which became extinct as a first language in the late-18th century, is being revived and has a small group of second-language speakers.<ref>{{Cite book |last1=Track |first1=Robert Lawrence |url=https://books.google.com/books?id=oLx9AgAAQBAJ&q=%E2%80%9Cthese+people+speak+the+dead+language+as+a+second+language%E2%80%9D&pg=PA63 |title=Language and Linguistics: The Key Concepts |last2=Stockwell, Peter |date=2007 |isbn=978-0-415-41358-9 |page=63 |publisher=Routledge |access-date=4 August 2019}}; {{Cite web |title=Framework Convention for the Protection of National Minorities, Strasbourg, 1.II.1995 |url=http://conventions.coe.int/Treaty/en/Treaties/Html/157.htm |access-date=9 March 2015 |publisher=Council of Europe |archive-date=22 February 2005 |archive-url=https://web.archive.org/web/20050222193410/http://conventions.coe.int/Treaty/EN/treaties/Html/157.htm |url-status=dead}}; {{Cite web |title=European Charter for Regional or Minority Languages, Strasbourg, 5.XI.1992 |url=http://conventions.coe.int/treaty/en/Treaties/Html/148.htm |access-date=9 March 2015 |publisher=Council of Europe |archive-date=26 February 2011 |archive-url=https://web.archive.org/web/20110226052008/http://conventions.coe.int/Treaty/EN/Treaties/HTML/148.htm |url-status=dead}}</ref><ref name="reglang" /> In the [[2021 United Kingdom census|2021 census]] the [[Welsh-speaking population]] of Wales aged three or older was 538,300 (17.8 per cent).<ref>{{Cite web |date=6 December 2022 |title=Welsh language in Wales (Census 2021) |url=https://gov.wales/welsh-language-wales-census-2021-html |access-date=6 December 2022 |website=gov.wales}}</ref> In addition it is estimated that about 200,000 Welsh-speakers live in England.<ref>{{Cite web |last=Wynn Thomas |first=Peter |date=March 2007 |title=Welsh today |url=https://www.bbc.co.uk/voices/multilingual/welsh.shtml |access-date=5 July 2011 |website=Voices |publisher=BBC}}</ref> In the 2021 census in Northern Ireland 12.4 per cent of people had some [[Irish language in Northern Ireland|Irish language]] ability and 10.4 per cent had some facility in the [[Ulster Scots dialect|Ulster-Scots]] language.<ref>{{Cite web |title=Census 2021: Main statistics for Northern Ireland |url=https://www.nisra.gov.uk/system/files/statistics/census-2021-main-statistics-for-northern-ireland-phase-1-statistical-bulletin-language.pdf |archive-url=https://web.archive.org/web/20240210110853/https://www.nisra.gov.uk/system/files/statistics/census-2021-main-statistics-for-northern-ireland-phase-1-statistical-bulletin-language.pdf |archive-date=10 February 2024 |access-date=10 February 2024}}</ref>
In 2001, over 92,000 people in Scotland, just under 2 per cent of the population, had some Gaelic language ability, including 72 per cent of those living in the [[Outer Hebrides]].<ref>{{Cite web |title=Scotland's Census 2001 – Gaelic Report |url=http://www.gro-scotland.gov.uk/press/news2005/scotlands-census-2001-gaelic-report.html |archive-url=https://web.archive.org/web/20130522110328/http://www.gro-scotland.gov.uk/press/news2005/scotlands-census-2001-gaelic-report.html |archive-date=22 May 2013 |access-date=28 April 2013 |publisher=General Register Office for Scotland}}</ref> The number of children being taught either Welsh or Scottish Gaelic is increasing.<ref>{{Cite news |date=12 February 2009 |title=Local UK languages 'taking off' |url=http://news.bbc.co.uk/1/hi/education/7885493.stm |work=BBC News}}</ref> [[Scots language|Scots]], a language descended from early northern [[Middle English]], has limited [[European Charter for Regional or Minority Languages|recognition]] alongside its regional variant, [[Ulster Scots dialects|Ulster Scots]] in Northern Ireland, without specific commitments to protection and promotion.<ref name="reglang" /><ref>{{Cite web |title=Language Data – Scots |url=http://www.eurolang.net/index.php?option=com_content&task=view&id=2449&Itemid=52&lang=en |archive-url=https://web.archive.org/web/20070623185445/http://eurolang.net/index.php?option=com_content&task=view&id=2449&Itemid=52&lang=en |archive-date=23 June 2007 |access-date=2 November 2008 |publisher=European Bureau for Lesser-Used Languages}}</ref> As of April 2020 there are around 151,000 users of [[British Sign Language]] (BSL), a [[sign language]] used by deaf people, in the UK.<ref>{{Cite news |last=Brown |first=Hannah |date=23 April 2020 |title='People are dying because of this': Calls for UK Gov to follow Scotland with sign language interpreter at Covid-19 briefing |url=https://www.scotsman.com/news/politics/people-are-dying-because-calls-uk-gov-follow-scotland-sign-language-interpreter-covid-19-briefing-2547989 |access-date=19 December 2021 |work=The Scotsman}}</ref>
In 2013, it was estimated that 95 per cent of the UK's population were [[monolingual]] English speakers.<ref name="BBC languages">{{Cite web |title=Languages across Europe: United Kingdom |url=https://www.bbc.co.uk/languages/european_languages/countries/uk.shtml |access-date=4 February 2013 |website=BBC}}</ref> In 2013, over 5 per cent of the population were estimated to speak languages brought to the UK as a result of immigration.<ref name="BBC languages" /> [[South Asian languages]] are the largest group, which includes [[Punjabi language|Punjabi]], [[Urdu]], [[Bengali language|Bengali]], [[Sylheti language|Sylheti]], [[Hindi]], [[Pahari-Pothwari]], [[Tamil language|Tamil]] and [[Gujarati language|Gujarati]].<ref>Carl Skutsch (2013). ''Encyclopedia of the World's Minorities''. pp.1261. Routledge. Retrieved 3 December 2020.</ref> In the 2011 census [[Polish language|Polish]] was the second-largest language spoken in England, with 546,000 speakers.<ref>{{Cite news |last=Booth |first=Robert |date=30 January 2013 |title=Polish becomes England's second language |url=https://www.theguardian.com/uk/2013/jan/30/polish-becomes-englands-second-language |access-date=4 February 2012 |work=The Guardian |location=London}}</ref> In 2019 some three-quarters of a million people spoke little or no English.<ref>{{Cite news |date=23 April 2019 |title=The teenagers who translate for their parents |url=https://www.bbc.co.uk/news/av/uk-47982494 |access-date=23 April 2019 |work=BBC News}}</ref>
=== Religion ===
{{Main|Religion in the United Kingdom|Freedom of religion in the United Kingdom}}
[[File:Westminster_Abbey_St_Peter.jpg|thumb|The [[Westminster Abbey]] in [[London]]. This was the [[Coronation of the British monarch|coronation]] site of 40 monarchs, 18 royal burials, and at least 16 royal weddings since 1100.]]
[[Christianity]] has dominated religious life in the United Kingdom for [[History of Christianity in Britain|more than 1,400 years]].<ref>Cannon, John, ed. (2nd edn., 2009). [https://books.google.com/books?id=TYnfhTq2M7EC&pg=PA144 ''A Dictionary of British History'']. Oxford University Press. p. 144. {{ISBN|978-0-19-955037-1}}.</ref> Although a majority of citizens still identify with Christianity in surveys, regular church attendance has fallen dramatically since the middle of the 20th century,<ref>Field, Clive D. (November 2009). [http://www.brin.ac.uk/wp-content/uploads/2011/12/development-of-religious-statistics.pdf "British religion in numbers"]. BRIN Discussion Series on Religious Statistics, Discussion Paper 001. Retrieved 7 March 2015.</ref> while immigration and demographic change have contributed to the growth of Islam and other faiths.<ref>Yilmaz, Ihsan (2005). [https://books.google.com/books?id=ryrD2YODzxUC&pg=PA291 ''Muslim Laws, Politics and Society in Modern Nation States: Dynamic Legal Pluralisms in England, Turkey, and Pakistan'']. Aldershot: Ashgate Publishing. pp. 55–56. {{ISBN|978-0-7546-4389-0}}.</ref> This has led some commentators to describe the UK as a multi-faith,<ref>Brown, Callum G. (2006). [https://books.google.com/books?id=ryrD2YODzxUC&pg=PA291 ''Religion and Society in Twentieth-Century Britain'']. Harlow: Pearson Education. p. 291. {{ISBN|978-0-582-47289-1}}.</ref> [[secularised]],<ref>Norris, Pippa; Inglehart, Ronald (2004). [https://books.google.com/books?id=dto-P2YfWJIC&pg=PA84 ''Sacred and Secular: Religion and Politics Worldwide'']. Cambridge University Press. p. 84. {{ISBN|978-0-521-83984-6}}.</ref> or [[post-Christian]] society.<ref>Fergusson, David (2004). [https://books.google.com/books?id=Owz4aBSEINgC&pg=PA94 ''Church, State and Civil Society'']. Cambridge University Press. p. 94. {{ISBN|978-0-521-52959-4}}.</ref>
In the 2021 census of England and Wales, 46.2 per cent of respondents reported that they were Christians, with the next largest faiths being [[Islam in the United Kingdom|Islam]] (6.5 per cent), [[Hinduism in the United Kingdom|Hinduism]] (1.7 per cent), [[Sikhism in the United Kingdom|Sikhism]] (0.9 per cent), [[Buddhism in the United Kingdom|Buddhism]] (0.5 per cent), [[Judaism in the United Kingdom|Judaism]] (0.5 per cent), and all other religions (0.6 per cent). Of the respondents, 37.2 per cent stated that they had [[Irreligion in the United Kingdom|no religion]] and a further 6.0 per cent did not answer the optional question.<ref>{{cite news|url=https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/religion/bulletins/religionenglandandwales/census2021|title=Religion, England and Wales: Census 2021|publisher=Office for National Statistics|first=Michael|last=Roskams|date=29 November 2022|access-date=28 March 2026}}</ref> In the census of Northern Ireland, 42.3 per cent of the population was recorded as Catholic, 37.7% as Protestant or other Christian, 1.3 per cent as belonging to other religions, 17.4 per cent as having no religion and 1.6 per cent did not state a religion.<ref>{{cite web|url=https://www.nisra.gov.uk/system/files/statistics/census-2021-ms-b19.xlsx|title=MS-B19: Religion|publisher=Northern Ireland Statistics and Research Agency|date=30 November 2023}}</ref> In Scotland's 2022 census, 51.1 per cent of the population stated that they had no religion, 20.4 per cent were recorded as Church of Scotland, 13.3 per cent as Catholic, 5.1 per cent as other Christian, 2.2 per cent as Muslim and 0.6 per cent as Hindu, with 1.2 per cent belonging to other religions and 6.2 per cent not stating a religion.<ref>{{cite web|url=https://www.scotlandscensus.gov.uk/2022-reports/scotland-s-census-2022-ethnic-group-national-identity-language-and-religion/|title=Scotland's Census 2022 - Ethnic group, national identity, language and religion|publisher=National Records of Scotland|date=21 May 2024|access-date=28 March 2026}}</ref>
A [[Tearfund]] survey in 2007 showed that one Briton in ten attends church weekly.<ref>{{Cite web |date=4 April 2007 |title=United Kingdom: New Report Finds Only One in 10 Attend Church |url=http://news.adventist.org/2007/04/uite-kigom-ew-report-fis-oly-oe-i-10-atte-church.html |archive-url=https://web.archive.org/web/20111213155625/http://news.adventist.org/2007/04/uite-kigom-ew-report-fis-oly-oe-i-10-atte-church.html |archive-date=13 December 2011 |access-date=9 March 2015 |website=News.adventist.org}}</ref> Between the 2001 and 2011 censuses there was a 12 per cent decrease in those who identified as Christian, while the percentage reporting no religious affiliation doubled. This contrasted with growth in the other main religious group categories, with the number of [[Muslims]] increasing the most to about 5 per cent.<ref>{{Cite news |last=Philby |first=Charlotte |date=12 December 2012 |title=Less religious and more ethnically diverse: Census reveals a picture of Britain today |url=https://www.independent.co.uk/news/uk/home-news/less-religious-and-more-ethnically-diverse-census-reveals-a-picture-of-britain-today-8406506.html |work=[[The Independent|Independent]] |location=London}}</ref>
The [[Church of England]] is the [[State religion|established church]] in England.<ref>{{Cite web |date=2004 |title=The History of the Church of England |url=http://www.cofe.anglican.org/about/history/ |url-status=dead |archive-url=https://web.archive.org/web/20100221212004/http://www.cofe.anglican.org/about/history |archive-date=21 February 2010 |access-date=23 November 2008 |website=The Church of England}}</ref> It retains [[Lords Spiritual|representation]] in the UK Parliament, and the British monarch is its [[Supreme Governor of the Church of England|Supreme Governor]].<ref>{{Cite web |title=Queen and Church of England |url=http://www.royalinsight.gov.uk/output/Page4708.asp |archive-url=https://web.archive.org/web/20061008203611/http://www.royalinsight.gov.uk/output/Page4708.asp |archive-date=8 October 2006 |access-date=5 June 2010 |publisher=British Monarchy Media Centre}}</ref> In [[religion in Scotland|Scotland]] the [[Church of Scotland]] is the [[national church]]. It is not subject to state control, and the British monarch is an ordinary member, required to swear an oath to "maintain and preserve the Protestant Religion and [[Presbyterian polity|Presbyterian Church Government]]" upon his or her accession.<ref>{{Cite web |title=Queen and the Church |url=http://www.royal.gov.uk/MonarchUK/QueenandChurch/History.aspx |url-status=live |archive-url=https://web.archive.org/web/20110605025533/http://www.royal.gov.uk/MonarchUK/QueenandChurch/History.aspx |archive-date=5 June 2011 |publisher=The British Monarchy (Official Website)}}</ref><ref name="reglang" /><ref>{{Cite web |date=22 February 2010 |title=Our structure |url=https://www.churchofscotland.org.uk/about-us/our-structure |url-status=live |archive-url=https://web.archive.org/web/20200125192732/https://www.churchofscotland.org.uk/about-us/our-structure |archive-date=25 January 2020 |website=churchofscotland.org.uk}}</ref> The [[Church in Wales]] was disestablished in 1920 and, because the [[Church of Ireland]] was disestablished in 1870 before the [[partition of Ireland]], there is no established church in Northern Ireland.<ref>Weller, Paul (2005). [https://books.google.com/books?id=tHc88PzAPLMC&pg=PA80 ''Time for a Change: Reconfiguring Religion, State, and Society'']. London: Continuum. pp. 79–80. {{ISBN|978-0-567-08487-3}}.</ref> Although there are no UK-wide data in the 2001 census on adherence to individual Christian denominations, it has been estimated that 62 per cent of Christians are Anglican, 13.5 per cent Catholic, 6 per cent Presbyterian, and 3.4 per cent Methodist, with smaller numbers of other denominations.<ref>Peach, Ceri, [https://books.google.com/books?id=i6ER_z8gcD4C "United Kingdom, a major transformation of the religious landscape"], in H. Knippenberg. ed. (2005). ''The Changing Religious Landscape of Europe''. Amsterdam: Het Spinhuis. pp. 44–58. {{ISBN|978-90-5589-248-8}}.</ref>
=== Migration ===
{{Main|Historical immigration to Great Britain|Modern immigration to the United Kingdom}}
{{See also|Foreign-born population of the United Kingdom}}
[[File:United Kingdom foreign born population by country of birth.png|thumb|upright=1.35|Estimated foreign-born population by country of birth from April 2007 to March 2008]]
[[File:British expats countrymap.svg|thumb|upright=1.35|Estimated number of British citizens living overseas by country in 2006:
{{legend|#002255|Greater than or equal to 1,000,000}}
{{legend|#003380|500,000 - 999,999}}
{{legend|#0044aa|100,000 - 499,999}}
{{legend|#0055d4|50,000 - 99,999}}
{{legend|#0066ff|10,000 - 49,999}}
{{legend|#2a7fff|5,000 - 9,999}}
{{legend|#5599ff|1,000 - 4,999}}
{{legend|#80b3ff|100 - 999}}
{{legend|#afc6e9|Less than 100 or no data}}
{{legend|#000000|UK}}
]]
Immigration is contributing to a rising population in the United Kingdom,<ref>{{Cite news |date=21 August 2008 |title=Immigration and births to non-British mothers pushes British population to record high |url=https://www.standard.co.uk/news/immigration-and-births-to-nonbritish-mothers-pushes-british-population-to-record-high-6816318.html |work=London Evening Standard}}</ref><ref name="bbc-23-05-2024">{{cite news |title=Migration: How many people come to the UK and how are the salary rules changing? |url=https://www.bbc.com/news/uk-48785695 |work=BBC News |date=23 May 2024}}</ref> with arrivals and UK-born children of migrants accounting for about half of the population increase between 1991 and 2001. According to statistics released in 2015, 27 per cent of UK live births in 2014 were to mothers born outside the UK.<ref>{{Cite web |date=15 July 2015 |title=Births in England and Wales: 2014 |url=http://www.ons.gov.uk/ons/rel/vsob1/birth-summary-tables--england-and-wales/2014/index.html |website=Office for National Statistics }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref>
In 2013 approximately 208,000 foreign nationals were naturalised as British citizens, the highest number since 1962. This figure fell to around 125,800 in 2014. Between 2009 and 2013 the average number of British citizenships granted annually was 195,800. The most common origins of those naturalised in 2024 were Pakistani, Indian, [[Nigeria]]n, [[Philippines|Filipino]], [[Bangladesh]]i, Italian, Turkish, Romanian and Iranian. The number of grants of settlement, which confer [[Permanent residency|permanent residence]] in the UK but not [[British citizenship|citizenship]],<ref>{{Cite web |last=Blinder |first=Scott |date=11 June 2014 |title=Settlement in the UK |url=http://www.migrationobservatory.ox.ac.uk/briefings/settlement-uk |archive-url=https://web.archive.org/web/20150906232123/http://migrationobservatory.ox.ac.uk/briefings/settlement-uk |archive-date=6 September 2015 |access-date=1 August 2015 |publisher=The Migration Observatory, University of Oxford}}</ref> was approximately 154,700 in 2013, higher than the previous two years.<ref name="Blinder2015">{{Cite web |last=Blinder |first=Scott |date=27 March 2015 |title=Naturalisation as a British Citizen: Concepts and Trends |url=http://www.migrationobservatory.ox.ac.uk/sites/files/migobs/Briefing%20-%20Naturalisation%20as%20a%20British%20Citizen%20-%20Concepts%20and%20Trends_0.pdf |archive-url=https://web.archive.org/web/20150916052200/http://www.migrationobservatory.ox.ac.uk/sites/files/migobs/Briefing%20-%20Naturalisation%20as%20a%20British%20Citizen%20-%20Concepts%20and%20Trends_0.pdf |archive-date=16 September 2015 |access-date=1 August 2015 |publisher=The Migration Observatory, University of Oxford}}</ref> Long-term net migration (the number of people immigrating minus the number emigrating) reached a record of 860,000 in 2023, with immigration at 1.326 million and emigration at 466,000. In comparison, in 2024 net migration was estimated to be 431,000 with immigration at 948,000 and emigration at 517,000.<ref>{{Cite web |title=Long-term international migration, provisional: year ending December 2024 |date=22 May 2025 |url=https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/internationalmigration/bulletins/longterminternationalmigrationprovisional/yearendingdecember2024 |website=gov.uk |access-date=22 May 2025}}</ref>
[[British diaspora|Emigration]] was an important feature of British society in the 19th century. Between 1815 and 1930, around 11.4 million people emigrated from Britain and 7.3 million from Ireland.<ref>{{Cite book |last=Hammar |first=Tomas |url=https://www.cambridge.org/core/books/european-immigration-policy/10B639425685B0C101619FA11522C409 |title=European Immigration Policy: A Comparative Study |date=1985 |publisher=Cambridge University Press |isbn=978-0-521-12437-9 |series=Comparative Ethnic and Race Relations |location=Cambridge}}</ref><ref name="richards-2018">{{Cite book |last=Richards |first=Eric |url=https://www.jstor.org/stable/j.ctvnb7rj2 |title=The genesis of international mass migration: The British case, 1750-1900 |date=2018 |publisher=Manchester University Press |edition=1 |jstor=j.ctvnb7rj2}}</ref> Estimates show that by the end of the 20th century, some 300 million people of British and Irish descent were permanently settled around the globe.<ref name="richards-2018" /> In 2006 at least 5.5 million UK-born people lived abroad,<ref name="BritsAbroad">{{Cite web |last1=Sriskandarajah |first1=Dhananjayan |last2=Drew |first2=Catherine |date=11 December 2006 |title=Brits Abroad: Mapping the scale and nature of British emigration |url=http://www.ippr.org/publicationsandreports/publication.asp?id=509 |archive-url=https://web.archive.org/web/20070828011816/http://www.ippr.org/publicationsandreports/publication.asp?id=509 |archive-date=28 August 2007 |access-date=9 March 2015 |publisher=Institute for Public Policy Research}}</ref><ref>{{Cite news |title=Brits Abroad: world overview |url=http://news.bbc.co.uk/1/shared/spl/hi/in_depth/brits_abroad/html/default.stm |access-date=20 April 2007 |publisher=BBC}}; {{Cite news |last=Casciani |first=Dominic |date=11 December 2006 |title=5.5 m Britons 'opt to live abroad' |work=BBC News |url=http://news.bbc.co.uk/2/hi/uk_news/6210358.stm |access-date=20 April 2007}}</ref> mainly in Australia, Spain, the United States and Canada.<ref name="BritsAbroad" /><ref>{{Cite news |date=11 December 2006 |title=Brits Abroad: Country-by-country |url=http://news.bbc.co.uk/2/hi/uk_news/6161705.stm |work=BBC News}}</ref>
=== Education ===
{{Main|Education in the United Kingdom|Universities in the United Kingdom}}
{{Further|Education in England|Education in Scotland|Education in Wales|Education in Northern Ireland}}
Education in the United Kingdom is a [[Devolution|devolved]] matter, with each country having a separate education system. About 38 per cent of the United Kingdom population has a university or [[college degree]], the highest percentage in Europe and one of the highest in the world.<ref>{{Cite web |date=24 September 2012 |title=The Most Educated Countries in the World |url=https://finance.yahoo.com/news/the-most-educated-countries-in-the-world.html;_ylt=AlaWy8IcyeBaviKi7_.WJyhE6odG;_ylu=X3oDMTJrY2d2NGZyBG1pdANDeFMgRmluYW5jaWFsbHkgRml0IEFydGljbGUgQXJ0aWNsZSBCb2R5IFByb2QEcG9zAzMEc2VjA01lZGlhQXJ0aWNsZUJvZHlBc3NlbWJseQ--;_ylg=X3oDMTNjdGVoaXJqBGludGwDdXMEbGFuZwNlbi11cwRwc3RhaWQDY2IyOTRhMGEtYmY2OS0zYTdlLThlYTUtZWFlNTU3YWI1ZTc3BHBzdGNhdANleGNsdXNpdmVzfGZpbmFuY2lhbGx5Zml0BHB0A3N0b3J5cGFnZQ--;_ylv=3?page=1 |archive-url=https://web.archive.org/web/20160204213400/http://finance.yahoo.com/news/the-most-educated-countries-in-the-world.html%3B_ylt%3DAlaWy8IcyeBaviKi7_.WJyhE6odG%3B_ylu%3DX3oDMTJrY2d2NGZyBG1pdANDeFMgRmluYW5jaWFsbHkgRml0IEFydGljbGUgQXJ0aWNsZSBCb2R5IFByb2QEcG9zAzMEc2VjA01lZGlhQXJ0aWNsZUJvZHlBc3NlbWJseQ--%3B_ylg%3DX3oDMTNjdGVoaXJqBGludGwDdXMEbGFuZwNlbi11cwRwc3RhaWQDY2IyOTRhMGEtYmY2OS0zYTdlLThlYTUtZWFlNTU3YWI1ZTc3BHBzdGNhdANleGNsdXNpdmVzfGZpbmFuY2lhbGx5Zml0BHB0A3N0b3J5cGFnZQ--%3B_ylv%3D3?page=1 |archive-date=4 February 2016 |access-date=20 April 2016 |website=Yahoo Finance }}; {{Cite magazine |date=27 September 2012 |title=And the World's Most Educated Country Is... |url=https://newsfeed.time.com/2012/09/27/and-the-worlds-most-educated-country-is/ |magazine=Time |location=New York |access-date=20 April 2016 |archive-date=30 April 2018 |archive-url=https://web.archive.org/web/20180430040213/http://newsfeed.time.com/2012/09/27/and-the-worlds-most-educated-country-is/ |url-status=dead }}</ref> The UK is home to [[List of universities in the United Kingdom|many universities]], including the [[University of Oxford]] and [[University of Cambridge]], which often achieve first place on global rankings.<ref>{{Cite web |title=The Times Higher Education World University Rankings 2024 |date=25 September 2023 |url=https://www.timeshighereducation.com/world-university-rankings/2024/world-ranking |access-date=17 April 2024}}</ref><ref>{{Cite web |title=QS World University Rankings 2024 |url=https://www.topuniversities.com/university-rankings/world-university-rankings/2024 |access-date=17 April 2024}}</ref>
University education has varied [[Student loans and grants in the United Kingdom|tuition fees]] in different regions of the UK. England and Wales have a fixed maximum annual fee for all UK citizens, contingent on attaining a certain level of income. Only those who reach a certain salary threshold pay this fee through [[Taxation in the United Kingdom|general taxation]].<ref>{{Cite web |title=Repaying your student loan |url=https://www.gov.uk/repaying-your-student-loan/what-you-pay |website=gov.uk |access-date=21 June 2025}}</ref> Northern Ireland and Scotland have a reduced maximum fee or no fee for citizens where it is their home region. Some NHS courses have bursaries which pay the fee and in 2017 it was stated that each doctor gets subsidised by £230,000 during their training.<ref>{{Cite web |date=20 October 2014 |title=Undergraduate Tuition Fess and Student Loans |url=https://www.ucas.com/money-and-student-life/money/student-finance/undergraduate-tuition-fees-and-student-loans |access-date=24 February 2024 |website=UCAS}}</ref><ref>{{Cite web |title=More undergraduate medical education places |url=https://www.gov.uk/government/news/more-undergraduate-medical-education-places |access-date=24 February 2024 |website=gov.uk}}</ref>
In 2022 the [[Programme for International Student Assessment]] (PISA), coordinated by the [[OECD]], ranked the overall knowledge and skills of British 15-year-olds as 14th in the world in reading, mathematics and science. The average British student scored 494, above the OECD average of 478.<ref>{{Cite web |title=PISA 2022 UK Results |url=https://www.oecd.org/publication/pisa-2022-results/country-notes/united-kingdom-9c15db47#chapter-d1e11 |access-date=24 February 2024 |website=OECD |date=4 December 2023}}</ref>
=== Health ===
{{Main|Health in the United Kingdom|Healthcare in the United Kingdom}}
{{Further|Healthcare in England|Healthcare in Scotland|Healthcare in Wales|Healthcare in Northern Ireland}}
[[File:QEUH.jpg|thumb|[[NHS Scotland]]'s [[Queen Elizabeth University Hospital]] in Glasgow, the largest hospital campus in Europe]]
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the establishment of the [[National Health Service]] (NHS), which began operating in 1948 as the primary healthcare provider in the United Kingdom.<ref>{{cite web |title=The foundation of the NHS |url=https://www.nationalarchives.gov.uk/explore-the-collection/stories/the-foundation-of-the-nhs/ |access-date=6 July 2026 |publisher=The National Archives}}</ref> The widespread popularity of the NHS has led to it being described as a "national religion".<ref>{{Cite news |last=Gill |first=Martha |date=9 July 2023 |title=To those who claim the NHS has turned into a British religion, I say: keep the faith |url=https://www.theguardian.com/commentisfree/2023/jul/09/nhs-british-religion-keep-faith-nhs-at-75 |access-date=16 July 2023 |work=The Observer}}</ref><ref>{{Cite web |date=14 April 2020 |title=Is the NHS our new national religion? – Religion Media Centre |url=https://religionmediacentre.org.uk/news/is-the-nhs-our-new-national-religion/ |access-date=16 July 2023 |website=religionmediacentre.org.uk}}</ref> Healthcare in the United Kingdom is a [[Devolution|devolved matter]] and each country has its own system of universal publicly funded healthcare ([[NHS England]], [[NHS Scotland]], [[Health and Social Care (Northern Ireland)]] and [[NHS Wales]]), although private healthcare is also available. Public healthcare is provided to all [[British nationality law|UK permanent residents]] and is mostly free at the point of need, being paid for from [[Taxation in the United Kingdom|general taxation]]. The [[World Health Organization]], in 2000, ranked the provision of healthcare in the United Kingdom as fifteenth-best in Europe and eighteenth in the world.<ref>{{Cite book |url=https://archive.org/details/worldhealthrepor00worl |title=The world health report 2000 – Health systems: improving performance |publisher=World Health Organization |date=2000 |isbn=978-92-4-156198-3 |editor-last=Haden |editor-first=Angela |location=Geneva |access-date=5 July 2011 |editor-last2=Campanini |editor-first2=Barbara}}; {{Cite web |last=World Health Organization |author-link=World Health Organization |title=Measuring overall health system performance for 191 countries |url=http://pages.stern.nyu.edu/~wgreene/Statistics/WHO-COMP-Study-30.pdf |access-date=5 July 2011 |publisher=New York University}}</ref>
Since 1979 expenditure on healthcare has increased significantly.<ref>{{Cite journal |last=Fisher |first=Peter |title=The NHS from Thatcher to Blair |url=http://www.healthp.org/node/71 |journal=NHS Consultants Association |archive-url=https://web.archive.org/web/20181120124807/http://www.healthp.org/node/71 |archive-date=20 November 2018 |access-date=19 December 2018 |quote=The Budget ... was even more generous to the NHS than had been expected amounting to an annual rise of 7.4 per cent above the rate of inflation for the next five years. This would take us to 9.4 per cent of GDP spent on health ie around EU average.}}</ref> The 2018 [[OECD]] data, which incorporates in health a chunk of what in the UK is classified as social care, has the UK spending £3,121 per person.<ref>{{Cite news |date=24 September 2019 |title=Swindells: They aren't 'your' patients |url=https://www.hsj.co.uk/policy-and-regulation/swindells-they-arent-your-patients/7025988.article? |access-date=19 November 2019 |publisher=Health Service Journal}}</ref> In 2017 the UK spent £2,989 per person on healthcare, near the median for members of the Organisation for Economic Co-operation and Development.<ref>{{Cite news |date=29 August 2019 |title=How does UK healthcare spending compare with other countries? |url=https://www.ons.gov.uk/peoplepopulationandcommunity/healthandsocialcare/healthcaresystem/articles/howdoesukhealthcarespendingcomparewithothercountries/2019-08-29 |access-date=5 October 2019 |publisher=Office of National Statistics}}</ref>
Regulatory bodies are organised on a UK-wide basis such as the [[General Medical Council]], the [[Nursing and Midwifery Council]] and non-governmental-based, such as the [[Medical royal college|Royal College]]s. Political and operational responsibility for healthcare lies with four national [[governments]]; healthcare in England is the responsibility of the UK Government; healthcare in Northern Ireland is the responsibility of the Northern Ireland Executive; healthcare in Scotland is the responsibility of the Scottish Government; and healthcare in Wales is the responsibility of the Welsh Government. Each National Health Service has different policies and priorities.<ref>{{Cite news |date=28 August 2008 |title='Huge contrasts' in devolved NHS |url=http://news.bbc.co.uk/1/hi/health/7586147.stm |work=BBC News}}; {{Cite news |last=Triggle |first=Nick |date=2 January 2008 |title=NHS now four different systems |work=BBC News |url=http://news.bbc.co.uk/1/hi/health/7149423.stm}}</ref>
== Culture ==
{{Main|Culture of the United Kingdom}}
{{Further|Culture of England|Culture of Scotland|Culture of Wales|Culture of Northern Ireland}}
The culture of the United Kingdom is influenced by the nation's island status, its history, and being a [[political union]] of four countries with each preserving distinctive traditions, customs and symbolism. British influence can be observed in the language, culture and [[Common law|legal systems]] of many of [[List of countries that have gained independence from the United Kingdom|its former colonies]], in particular the United States, Australia, Canada, New Zealand and Ireland, a common culture known as the Anglosphere.<ref>{{Cite book |last=Julian Go |title=Constitutionalism and political reconstruction |date=2007 |publisher=Brill |isbn=978-90-04-15174-1 |editor-last=Arjomand |editor-first=Saïd Amir |pages=92–94 |chapter=A Globalizing Constitutionalism?, Views from the Postcolony, 1945–2000 |chapter-url=https://books.google.com/books?id=kYmmnYKEvE0C&pg=PA94}}</ref>{{Sfn|Ferguson|2004|p=307}} Most of its former colonies are Commonwealth countries, bonded by a shared British inheritance.<ref>{{Cite web |title=The Commonwealth |url=https://www.mfat.govt.nz/en/peace-rights-and-security/the-commonwealth/ |access-date=8 January 2024 |website=[[New Zealand Ministry of Foreign Affairs and Trade]] |language=en-NZ}}</ref><ref>{{Cite web |title=Commonwealth of Nations |url=https://www.parliament.uk/about/living-heritage/evolutionofparliament/legislativescrutiny/parliament-and-empire/contemporary-context/ |access-date=2026-02-22 |publisher=UK Parliament |language=en}}</ref><ref>{{Cite book |last1=Mazrui |first1=Ali Al Amin |title=Anglo-African Commonwealth |last2=Taylor |first2=D. |last3=Bradley |first3=Kenneth |date=1967 |publisher=Pergamon |isbn=978-0-08-012253-3 |pages=40–41 |quote=...in the ultimate analysis, what could a New Zealander have in common with a Jamaican or a Zambian, if not the bonds of a shared British-ness?}}</ref> A global survey in 2024 ranked the UK third in the 'Most Influential Countries' rankings, behind the US and China.<ref>{{Cite web |title=Most Influential Countries |url=https://www.usnews.com/news/best-countries/most-influential-countries |access-date=22 September 2025 |website=[[U.S. News & World Report]]}}</ref>
=== Literature and drama ===
{{Main|British literature|Theatre of the United Kingdom}}
{{Further|Literature of England|Scottish literature|Welsh literature|Literature of Northern Ireland}}
{{multiple image
| align = right
| total_width = 320
| image1 = PG 1063Burns Naysmith.jpg
| alt1 = Robert Burns
| caption1 = [[Robert Burns]] (1759–1796)
| image2 = William Shakespeare by John Taylor, edited.jpg
| alt2 = William Shakespeare
| caption2 = [[William Shakespeare]] (1564–1616)
| footer = Burns and Shakespeare are considered the [[national poet]]s of Scotland and England respectively.
}}
British literature includes that associated with the United Kingdom, the [[Isle of Man]] and the [[Channel Islands]]. Most British literature is in English. In 2022, 669 million physical books were sold in the UK, the most ever.<ref>{{Cite web |title=UK publishing industry reports record-breaking year in 2022 |url=https://www.theguardian.com/books/2023/apr/17/uk-publishing-industry-reports-record-breaking-year-in-2022 |access-date=9 May 2024 |work=[[The Guardian]] |date=17 April 2023}}</ref> Britain is renowned for [[Literature for children|children's literature]]; writers include [[Daniel Defoe]], [[Rudyard Kipling]], [[Lewis Carroll]] and [[Beatrix Potter]], who also illustrated her own books. Other writers include [[A. A. Milne]], [[Enid Blyton]], [[J. R. R. Tolkien]], [[Roald Dahl]], [[Terry Pratchett]] and [[J. K. Rowling]], who wrote ''[[Harry Potter]]'', the [[List of best-selling book series|best-selling book series]] of all time.<ref>{{Cite web |title=Best-selling Book Series Of All Time |url=https://wordsrated.com/best-selling-book-series-of-all-time-statistics/ |access-date=18 May 2024 |publisher=Wordsrated |date=20 July 2023}}</ref>
The playwright and poet [[William Shakespeare]] is generally regarded as the greatest dramatist ever and the [[national poet]] of England.<ref>{{Cite web |title=William Shakespeare (English author) |url=https://www.britannica.com/EBchecked/topic/537853/William-Shakespeare |access-date=26 February 2006 |publisher=[[Encyclopædia Britannica]]}}; {{Cite encyclopedia |title=MSN Encarta Encyclopedia article on Shakespeare |url=http://encarta.msn.com/encyclopedia_761562101/Shakespeare.html |access-date=26 February 2006 |archive-url=https://web.archive.org/web/20060209154055/http://encarta.msn.com/encyclopedia_761562101/Shakespeare.html |archive-date=9 February 2006}}; {{Cite web |title=William Shakespeare |work=TheFreeDictionary.com |publisher=Columbia Electronic Encyclopedia |url=http://encyclopedia2.thefreedictionary.com/Shakespeare%2c+William |access-date=26 February 2006}}</ref> Theatre of United Kingdom plays an important part in British culture and has had a vibrant tradition of [[theatre]] since the Renaissance with roots going back to the Roman occupation. Other important figures in the literature of England are [[Geoffrey Chaucer]], known for ''[[The Canterbury Tales]]'', the poet [[William Wordsworth]], and other [[Romantic Poetry|Romantic poets]], also the novelists [[Charles Dickens]], [[H. G. Wells]], [[George Orwell]], [[Aldous Huxley]] and [[Ian Fleming]]. The 20th-century English crime writer [[Agatha Christie]] is the [[List of best-selling fiction authors|best-selling novelist]] in history.<ref>{{Cite news |date=19 December 2005 |title=Mystery of Christie's success is solved |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/uknews/1505799/Mystery-of-Christies-success-is-solved.html |url-status=live |url-access=subscription |access-date=14 November 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/news/uknews/1505799/Mystery-of-Christies-success-is-solved.html |archive-date=10 January 2022}}{{Cbignore}}</ref> Twelve of the top 25 of 100 novels by British writers chosen by a BBC poll of global critics were written by women; these included works by [[George Eliot]], [[Virginia Woolf]], [[Charlotte Brontë]], [[Emily Brontë]], [[Mary Shelley]], [[Jane Austen]], [[Doris Lessing]] and [[Zadie Smith]].<ref>{{Cite news |last=Ciabattari |first=Jane |date=December 2015 |title=The 25 greatest British novels |work=BBC Culture |url=https://www.bbc.com/culture/article/20151204-the-25-greatest-british-novels |access-date=29 December 2021}}</ref>
Scottish literature includes [[Arthur Conan Doyle]] (the creator of [[Sherlock Holmes]]), [[Walter Scott|Sir Walter Scott]], [[J. M. Barrie]], [[Robert Louis Stevenson]] (whose novel ''[[Treasure Island]]'' strongly influenced the portrayal of [[pirates in the arts and popular culture]]), and the poet [[Robert Burns]], who is considered the national poet of Scotland. More recently [[Hugh MacDiarmid]] and [[Neil M. Gunn]] contributed to the [[Scottish Renaissance]], with grimmer works from [[Ian Rankin]] and [[Iain Banks]]. Edinburgh was UNESCO's first worldwide [[City of Literature]].<ref>{{Cite web |year=2004 |title=Edinburgh, United Kingdom, UNESCO City of Literature |url=http://www.unesco.org/new/en/culture/themes/creativity/creative-industries/creative-cities-network/literature/edinburgh |archive-url=https://web.archive.org/web/20130528152834/http://www.unesco.org/new/en/culture/themes/creativity/creative-industries/creative-cities-network/literature/edinburgh |archive-date=28 May 2013 |url-status=dead |access-date=9 March 2015 |work=Unesco}}</ref>
Welsh literature includes Britain's oldest known poem, ''[[Y Gododdin]]'', most likely composed in the late 6th century. It was written in [[Cumbric language|Cumbric]] or [[Old Welsh]] and contains the earliest known reference to [[King Arthur]].<ref>{{Cite web |title=Early Welsh poetry |url=https://www.bbc.co.uk/wales/history/sites/themes/society/language_poetry.shtml |access-date=29 December 2010 |work=BBC Wales}}</ref> The [[Arthurian legend]] was further developed by [[Geoffrey of Monmouth]].<ref>{{Cite book |last=Lang, Andrew |url=https://books.google.com/books?id=dKJiPyyTevgC |title=History of English Literature from Beowulf to Swinburne |publisher=Wildside Press |year=2003 |isbn=978-0-8095-3229-2 |location=Holicong, PA |page=42 |orig-date=1913}}</ref> [[Dafydd ap Gwilym]] (''fl.'' 1320–1370) is widely regarded as one of the greatest European poets of his age.<ref>{{Cite web |year=2011 |title=Dafydd ap Gwilym |url=http://www.academi.org/dafydd-ap-gwilym-eng |archive-url=https://web.archive.org/web/20120324034938/http://www.literaturewales.org/dafydd-ap-gwilym-eng |archive-date=24 March 2012 |url-status=dead |access-date=3 January 2011 |website=[[Literature Wales|Academi.org]] |quote=Dafydd ap Gwilym is widely regarded as one of the greatest Welsh poets of all time, and amongst the leading European poets of the Middle Ages.}}</ref> [[Daniel Owen]] is credited as the first Welsh-language novelist, publishing ''[[Rhys Lewis (novel)|Rhys Lewis]]'' in 1885. The best-known of the [[Anglo-Welsh poetry|Anglo-Welsh poets]] are [[Dylan Thomas]] and [[R. S. Thomas]], the latter nominated for the [[Nobel Prize in Literature]] in 1996. Leading Welsh novelists of the twentieth century include [[Richard Llewellyn]] and [[Kate Roberts (author)|Kate Roberts]].<ref>{{Cite web |url=http://newsalerts.bbc.co.uk/1/low/wales/551486.stm |title=True birthplace of Wales's literary hero |archive-url=https://web.archive.org/web/20200316173733/http://newscdn.bbc.net.uk/2/hi/uk_news/wales/551486.stm |archive-date=16 March 2020 |url-status=dead |website=BBC News |date=5 December 1999 |access-date=28 April 2012}}</ref><ref>{{Cite web |title=Kate Roberts: Biography |url=https://www.bbc.co.uk/wales/northwest/halloffame/arts/kateroberts.shtml |url-status=dead |access-date=19 February 2017 |website=BBC Wales |archive-url=https://web.archive.org/web/20130308000646/https://www.bbc.co.uk/wales/northwest/halloffame/arts/kateroberts.shtml |archive-date=8 March 2013}}</ref>
Northern Ireland's most popular writer is [[C. S. Lewis]], who was born in Belfast and wrote ''[[The Chronicles of Narnia]]''.<ref>{{Cite web |title=The Chronicles of Narnia Book Series Statistics |url=https://wordsrated.com/the-chronicles-of-narnia-book-series-statistics/ |access-date=18 May 2024 |publisher=Wordsrated |date=19 July 2023}}</ref> Irish writers, living at a time when all of Ireland was part of the United Kingdom, include [[Oscar Wilde]],<ref>{{Cite book |last=Varty |first=Anne |title=A Preface to Oscar Wilde |date=2014 |publisher=Routledge |isbn=978-1-317-89231-1 |pages=[https://books.google.com/books?id=A9YFBAAAQBAJ&pg=PA231 231–232]}}; {{Cite encyclopedia |title=Oscar Wilde |encyclopedia=[[Encyclopedia.com]] |publisher=[[Cengage]] |url=https://www.encyclopedia.com/people/literature-and-arts/english-literature-19th-cent-biographies/oscar-wilde |access-date=10 December 2019}}</ref> [[Bram Stoker]] (who wrote ''[[Dracula]]'')<ref>{{Cite book |last=Moss |first=Joyce |url=https://archive.org/details/isbn_9780787637286 |title=British and Irish Literature and Its Times: The Victorian Era to the Present (1837–) |publisher=Gale Group |year=2001 |isbn=978-0-7876-3729-3 |page=[https://archive.org/details/isbn_9780787637286/page/107 107] |url-access=registration}}</ref> and [[George Bernard Shaw]].<ref>{{Cite book |last=Holroyd |first=Michael |url=https://archive.org/details/bernardshaw00holr/page/384 |title=Bernard Shaw, Volume 2: 1898–1918: The Pursuit of Power |publisher=Chatto & Windus |year=1989 |isbn=978-0-7011-3350-4 |page=[https://archive.org/details/bernardshaw00holr/page/384 384]}}; {{Cite web |title=G B Shaw |url=https://www.bl.uk/people/g-b-shaw |access-date=10 December 2019 |website=Discovering Literature: 20th century |publisher=[[British Library]] |archive-date=9 August 2020 |archive-url=https://web.archive.org/web/20200809155152/https://www.bl.uk/people/g-b-shaw |url-status=dead}}</ref> There have been many authors whose origins were from outside the United Kingdom but who moved to the UK, including [[Joseph Conrad]],<ref>{{Cite book |last=Middleton |first=Tim |url=https://books.google.com/books?id=Azd1f8NBpUoC&pg=PA159 |title=Joseph Conrad |publisher=Routledge |year=2006 |isbn=978-0-415-26851-6 |page=159}}</ref> [[T. S. Eliot]],<ref>{{Cite book |last=Cooper |first=John Xiros |url=https://books.google.com/books?id=XqmNjQzhwV4C&pg=PA111 |title=The Cambridge Introduction to T. S. Eliot |date=2006 |publisher=Cambridge University Press |isbn=978-1-139-45790-3 |page=111}}</ref> [[Kazuo Ishiguro]],<ref>{{Cite book |last=Sim |first=Wai-chew |url=https://books.google.com/books?id=WcKLAgAAQBAJ&pg=PT201 |title=Kazuo Ishiguro |date=2009 |publisher=Routledge |isbn=978-1-135-19867-1 |page=201}}</ref> Sir [[Salman Rushdie]]<ref>{{Cite web |title=Salman Rushdie |url=https://www.oxfordreference.com/view/10.1093/oi/authority.20110803100433765 |access-date=10 December 2019 |website=Oxford Reference |publisher=[[Oxford University Press]]}}</ref> and [[Ezra Pound]].<ref>{{Cite news |last=Campbell |first=James |date=17 May 2008 |title=Home from home |work=The Guardian |url=https://www.theguardian.com/books/2008/may/17/poetry3 |access-date=10 December 2019}}; {{Cite book |last=Nadel |first=Ira |url=https://books.google.com/books?id=ECiGDAAAQBAJ&pg=PA90 |title=Ezra Pound: A Literary Life |date=2004 |publisher=Palgrave Macmillan |isbn=978-0-230-37881-0 |page=90}}</ref>
=== Philosophy ===
{{Main|British philosophy}}
The United Kingdom is famous for "[[British Empiricism]]", a branch of the philosophy that states that only knowledge verified by experience is valid, and 'Scottish Philosophy', sometimes referred to as the '[[Scottish School of Common Sense]]'.<ref>{{Cite book |url=http://www.rrbltd.co.uk/bibliographies/scottish_v5_bibliog.pdf |title=A bibliography of Scottish common sense philosophy: Sources and origins |publisher=Thoemmes Press |year=2000 |editor-last=Fieser, James |location=Bristol |access-date=17 December 2010 |archive-date=9 April 2023 |archive-url=https://web.archive.org/web/20230409171906/https://www.rrbltd.co.uk/bibliographies/scottish_v5_bibliog.pdf |url-status=dead}}</ref> The most famous philosophers of British Empiricism are [[John Locke]], [[George Berkeley]]{{Efn|Berkeley is in fact Irish but was called a 'British empiricist' due to the territory of what is now known as the [[Republic of Ireland]] being in the UK at the time.}} and [[David Hume]]; while [[Dugald Stewart]], [[Thomas Reid]] and [[Sir William Hamilton, 9th Baronet|William Hamilton]] were major exponents of the Scottish "common sense" school. Two Britons are also notable for the ethical theory of [[utilitarianism]], a moral philosophy first used by [[Jeremy Bentham]] and later by [[John Stuart Mill]] in his short work ''[[Utilitarianism (book)|Utilitarianism]]''.<ref>{{Cite book |last=Palmer, Michael |url=https://books.google.com/books?id=s7y5MJOuN30C&pg=PA66 |title=Moral Problems in Medicine: A Practical Coursebook |publisher=Lutterworth Press |year=1999 |isbn=978-0-7188-2978-0 |location=Cambridge |page=66}}; {{Cite book |last=Scarre, Geoffrey |url=https://books.google.com/books?id=8A4xLnzfqYwC&pg=PA82 |title=Utilitarianism |publisher=Routledge |year=1995 |isbn=978-0-415-12197-2 |location=London |page=82}}</ref>
=== Media ===
{{Main|Media of the United Kingdom|Censorship in the United Kingdom}}
{{Further|Media of England|Media of Scotland|Media of Wales|Media of Northern Ireland}}
The [[BBC]], founded in 1922, is the United Kingdom's publicly funded radio, television and Internet broadcasting corporation, and is the oldest and largest broadcaster in the world.<ref name="MediaNewsline">{{Cite web |title=BBC: World's largest broadcaster & Most trusted media brand |url=http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-url=https://web.archive.org/web/20101005004930/http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-date=5 October 2010 |access-date=23 September 2010 |publisher=Media Newsline}}</ref><ref name="ProspectMag">{{Cite web |title=Digital license |url=http://www.prospectmagazine.co.uk/?p=64654 |archive-url=https://web.archive.org/web/20111107024637/http://www.prospectmagazine.co.uk/2009/07/digitallicense |archive-date=7 November 2011 |access-date=9 March 2015 |publisher=Prospect}}</ref><ref name="AboutBBC">{{Cite news |title=About the BBC – What is the BBC |work=BBC Online |url=https://www.bbc.co.uk/info/purpose/what.shtml |access-date=9 March 2015 |archive-url=https://web.archive.org/web/20100116202334/http://www.bbc.co.uk/info/purpose/what.shtml |archive-date=16 January 2010}}</ref> It operates television and radio stations across the UK and abroad and its domestic services are funded by the [[Television licensing in the United Kingdom|television licence]].<ref>{{Cite journal |date=13 August 2009 |title=BBC: World's largest broadcaster & Most trusted media brand |url=http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |journal=Media Newsline |archive-url=https://web.archive.org/web/20110510090842/http://www.medianewsline.com/news/151/ARTICLE/4930/2009-08-13.html |archive-date=10 May 2011 |access-date=19 June 2011}}; {{Cite web |date=April 2010 |title=TV Licence Fee: facts & figures |url=https://www.bbc.co.uk/pressoffice/keyfacts/stories/licencefee.shtml |url-status=live |archive-url=https://web.archive.org/web/20110427080539/http://www.bbc.co.uk/pressoffice/keyfacts/stories/licencefee.shtml |archive-date=27 April 2011 |publisher=BBC Press Office}}</ref> The [[BBC World Service]] is an [[International broadcasting|international broadcaster]] owned and operated by the BBC, and the world's largest.<ref>{{Cite web |title=Microsoft Word – The Work of the BBC World Service 2008–09 HC 334 FINAL.doc |url=https://publications.parliament.uk/pa/cm200910/cmselect/cmfaff/334/334.pdf |archive-url=https://web.archive.org/web/20201021001645/https://publications.parliament.uk/pa/cm200910/cmselect/cmfaff/334/334.pdf |archive-date=21 October 2020 |access-date=16 February 2011}}</ref> It broadcasts radio news, speech and discussions in more than 40 languages.<ref>{{Cite web |title=News in your language – BBC News |url=https://www.bbc.co.uk/ws/languages |website=BBC}}; {{Cite web |title=BBC World Service |url=https://www.facebook.com/pages/category/Media-News-Company/bbcworldservice/about |website=Facebook.com}}</ref>
Other major players in the UK media include [[ITV plc|ITV]], which operates 11 of the 15 regional television broadcasters that make up the [[ITV (TV network)|ITV Network]],<ref>{{Cite web |title=Publications & Policies: The History of ITV |url=http://www.itv.com/aboutitv/publications-policies |archive-url=https://web.archive.org/web/20110411224117/http://www.itv.com/aboutitv/publications-policies |archive-date=11 April 2011 |website=ITV.com}}</ref> and [[Sky UK|Sky]].<ref>{{Cite journal |title=Direct Broadcast Satellite Television |url=http://www.newscorp.com/operations/dbst.html |journal=News Corporation |archive-url=https://web.archive.org/web/20110604095622/http://www.newscorp.com/operations/dbst.html |archive-date=4 June 2011}}</ref> Newspapers produced in the United Kingdom include the ''[[Daily Mail]]'', ''[[The Guardian]]'', ''[[The Daily Telegraph|The Telegraph]]'', ''[[The Times]]'', and the ''[[Financial Times]]''.<ref>{{Cite news |date=10 October 2008 |title=ABCs: National daily newspaper circulation September 2008 |work=The Guardian |location=London |url=https://www.theguardian.com/media/table/2008/oct/10/abcs-pressandpublishing |access-date=17 October 2008}}</ref> Magazines and journals published in the United Kingdom that have achieved worldwide circulation include ''[[The Spectator]]'', ''[[The Economist]]'', ''[[New Statesman]]'' and ''[[Radio Times]]''.
[[File:Media City Footbridge and BBC Offices (geograph 2685261).jpg|thumb|[[MediaCityUK]] in [[Salford]], [[Greater Manchester]], is one of the largest media production facilities in Europe.]]London dominates the media sector in the UK: national newspapers and television and radio are largely based there, although [[MediaCityUK]] in Manchester is also a significant national media centre. Edinburgh and Glasgow, and Cardiff, are important centres of newspaper and broadcasting production in Scotland and Wales, respectively.<ref>William, D. (2010). [https://books.google.com/books?id=7yg45P35KDMC ''UK Cities: A Look at Life and Major Cities in England, Scotland, Wales and Northern Ireland'']. Eastbourne: Gardners Books. {{ISBN|978-9987-16-021-1}}, pp. 22, 46, 109 and 145.</ref> The UK publishing sector, including books, directories and databases, journals, magazines and business media, newspapers and news agencies, has a combined turnover of around £20 billion and employs 167,000 people.<ref>{{Cite web |title=Publishing |url=http://www.culture.gov.uk/what_we_do/creative_industries/3280.aspx |url-status=live |archive-url=https://web.archive.org/web/20110505104322/http://www.culture.gov.uk/what_we_do/creative_industries/3280.aspx |archive-date=5 May 2011 |publisher=Department of Culture, Media and Sport}}</ref> In 2015 the UK published 2,710 book titles per million inhabitants, more than any other country, with much of this exported to other [[Anglophone]] countries.<ref>{{Cite web |last=<!--Not stated--> |date=2016 |title=Annual Report 2015–2016 |url=https://www.internationalpublishers.org/images/reports/Annual_Report_2016/IPA_Annual_Report_2015-2016_interactive.pdf |access-date=14 January 2021 |website=internationalpublishers.org |publisher=International Publishers Association |page=16 |archive-date=31 August 2023 |archive-url=https://web.archive.org/web/20230831205753/https://www.internationalpublishers.org/images/reports/Annual_Report_2016/IPA_Annual_Report_2015-2016_interactive.pdf |url-status=dead}}</ref>
In 2010, 82.5 per cent of the UK population were Internet users, the [[List of countries by number of Internet users|highest proportion]] amongst the 20 countries with the largest total number of users in that year.<ref>{{Cite journal |title=Top 20 countries with the highest number of Internet users |url=http://www.internetworldstats.com/top20.htm |journal=Internet World Stats |archive-url=https://web.archive.org/web/20110610104435/http://www.internetworldstats.com/top20.htm |archive-date=10 June 2011 |access-date=19 June 2011}}</ref> The [[Video games in the United Kingdom|British video game industry]] is the largest in Europe, and since 2022 the UK has the [[List of video games markets by country|largest video game market]] in Europe by sales, surpassing [[Video games in Germany|Germany]].<ref>{{Cite web |last=Dring |first=Christopher |date=12 January 2023 |title=European console and PC game sales fall 7.1% in 2022 |url=https://www.gamesindustry.biz/european-console-and-pc-game-sales-fall-71-over-2021 |access-date=30 September 2023 |website=GamesIndustry.biz}}</ref> It is the world's third-largest producer of video games after [[Video games in Japan|Japan]] and the [[Video games in the United States|United States]].<ref>{{Cite web |title=About UK Video Games Industry |url=https://tiga.org/about-tiga-and-our-industry/about-uk-video-games-industry |access-date=6 June 2023 |website=TIGA}}</ref>
=== Visual art ===
{{Main|Art of the United Kingdom|Architecture of the United Kingdom}}
[[File:Angel of the North - 6150534524.jpg|thumb|The [[Angel of the North]] sculpture by [[Antony Gormley]] has become a symbol of [[Northern England]].]]
Major British artists include the [[Romanticism|Romantic]] artists [[William Blake]], [[John Constable]], [[Samuel Palmer]], and [[J. M. W. Turner]]; the [[portrait]] painters [[Joshua Reynolds|Sir Joshua Reynolds]] and [[Lucian Freud]]; the landscape artists [[Thomas Gainsborough]] and [[L. S. Lowry]]; the pioneer of the [[Arts and Crafts movement]] [[William Morris]]; the figurative painter [[Francis Bacon (artist)|Francis Bacon]]; the [[Pop artist]]s [[Peter Blake (artist)|Peter Blake]], [[Richard Hamilton (artist)|Richard Hamilton]] and [[David Hockney]]; the pioneers of [[conceptual art]] movement [[Art & Language]];<ref>{{Cite news |last=Tate |title=Art & Language – Art Term {{!}} Tate |work=Tate |url=https://www.tate.org.uk/art/art-terms/a/art-language |access-date=8 September 2018}}</ref> the collaborative duo [[Gilbert and George]]; the [[Abstract art|abstract]] artist [[Howard Hodgkin]]; and the sculptors [[Antony Gormley]], [[Anish Kapoor]] and [[Henry Moore]]. During the late 1980s and 1990s the [[Saatchi Gallery]] in London helped to bring to public attention a group of multi-genre artists who would become known as the "[[Young British Artists]]": [[Damien Hirst]], [[Chris Ofili]], [[Rachel Whiteread]], [[Tracey Emin]], [[Mark Wallinger]], [[Steve McQueen (director)|Steve McQueen]], [[Sam Taylor-Wood]] and the [[Jake and Dinos Chapman|Chapman Brothers]] are amongst the better-known members of this loosely affiliated movement.
The [[Royal Academy]] in London is a key organisation for the promotion of the visual arts in the United Kingdom. Major schools of art in the UK include: the six-school [[University of the Arts London]], which includes the [[Central Saint Martins College of Art and Design]] and [[Chelsea College of Art and Design]]; [[Goldsmiths, University of London]]; the [[Slade School of Fine Art]] (part of [[University College London]]); the [[Glasgow School of Art]]; the [[Royal College of Art]]; and [[The Ruskin School of Drawing and Fine Art]] (part of the University of Oxford). The [[Courtauld Institute of Art]] is a leading centre for the teaching of the [[history of art]]. Important art galleries in the United Kingdom include the [[National Gallery]], [[National Portrait Gallery (London)|National Portrait Gallery]], [[Tate Britain]], and [[Tate Modern]] (the most-visited modern art gallery in the world, with around 4.7 million visitors per year).<ref>{{Cite news |last=Bayley |first=Stephen |date=24 April 2010 |title=The startling success of Tate Modern |work=[[The Times]] |location=London |url=http://entertainment.timesonline.co.uk/tol/arts_and_entertainment/visual_arts/article7105032.ece |archive-url=https://web.archive.org/web/20110429173928/http://entertainment.timesonline.co.uk/tol/arts_and_entertainment/visual_arts/article7105032.ece |url-status=dead |archive-date=29 April 2011 |access-date=19 January 2011}} {{Subscription required}}</ref>
=== Music ===
{{Main|Music of the United Kingdom}}
{{Further|Music of England (disambiguation){{!}}Music of England|Music of Scotland|Music of Wales|Music of Northern Ireland}}
<!----Caution should be taken to ensure that the sections are not simply a listing of names or mini biographies of individuals accomplishments.---->
[[File:Royal Albert Hall, BBC Proms 2017.jpg|thumb|[[The Proms]] is a classical music festival, most closely associated with [[Henry Wood]] and held at the [[Royal Albert Hall]] in London, which regularly plays music by [[Edward Elgar]] and other British composers.]]
Various styles of music have become popular in the UK, including the [[folk music]] of [[Folk music of England|England]], [[Folk music of Scotland|Scotland]], [[Music of Wales#Folk music|Wales]] and [[Folk music of Northern Ireland|Northern Ireland]]. English folk features melodic ballads with strong lyrics and music for country dancing often using accordion and fiddles.<ref>{{Cite web |access-date=15 September 2025 |title=Songs of England |url=https://www.english-heritage.org.uk/visit/inspire-me/songs-of-england}}</ref> Scottish folk features bagpipes and fiddles playing traditional dance tunes with bouncy tempos.<ref>{{Cite web |access-date=15 September 2025 |title=The influence of traditional Scottish Music |url=https://www.visitscotland.com/things-to-do/events/music-festivals/traditional-folk}}</ref> Welsh folk has harps and vocal harmonies often sung in Welsh.<ref>{{Cite web |access-date=15 September 2025 |title=Celtic connections: the story of folk music in Wales |date=17 February 2020 |url=https://www.wales.com/culture-and-sport/music-and-performance/roots-and-shoots-welsh-folk-music}}</ref> Northern Irish folk blends fiddles with flutes merging Scottish and Irish influences.<ref>{{Cite web |access-date=15 September 2025 |title=Why you should experience traditional music in Ireland |url=https://www.ireland.com/en-us/magazine/music/traditional-music/}}</ref>
Historically, there has been [[Renaissance music]] from the [[Tudor period]], with [[Mass (music)|masses]], [[madrigal]]s and [[lute]] music by [[Thomas Tallis]], [[John Taverner]], [[William Byrd]], [[Orlando Gibbons]] and [[John Dowland]]. After the [[Stuart Restoration]], an English tradition of dramatic [[masque]]s, anthems and airs became established, led by [[Henry Purcell]], followed by [[Thomas Arne]] and others. [[George Frideric Handel]] composed the anthem ''[[Zadok the Priest]]'' for the [[coronation of George II]]; it became the traditional ceremonial music for anointing all future monarchs. Handel's many oratorios, such as his famous ''[[Messiah (Handel)|Messiah]]'', were written in English.<ref>{{Cite web |date=20 July 2009 |title=British Citizen by Act of Parliament: George Frideric Handel |url=http://www.parliament.uk/parliamentary_publications_and_archives/parliamentary_archives/handel_and_naturalisation.cfm |archive-url=https://web.archive.org/web/20100326164147/http://www.parliament.uk/parliamentary_publications_and_archives/parliamentary_archives/handel_and_naturalisation.cfm |archive-date=26 March 2010 |access-date=9 March 2015 |publisher=UK Parliament}}; {{Cite news |last=Andrews |first=John |date=14 April 2006 |title=Handel all'inglese |work=Playbill |location=New York |url=http://www.playbillarts.com/features/article/4236.html |access-date=11 September 2009 |archive-url=https://web.archive.org/web/20080516210558/http://www.playbillarts.com/features/article/4236.html |archive-date=16 May 2008}}</ref>
In the second half of the 19th century, [[Arthur Sullivan]] and his librettist [[W. S. Gilbert]] wrote their popular [[Savoy opera]]s, and [[Edward Elgar]] composed a wide range of music. Increasingly, composers became inspired by the English countryside and its [[folk music]], notably [[Gustav Holst]], [[Ralph Vaughan Williams]] and [[Benjamin Britten]], a pioneer of modern British opera. Amongst the many post-war composers, some of the most notable have made their own personal choice of musical identity: [[Peter Maxwell Davies]] (Orkney), [[Harrison Birtwistle]] (mythological), and [[John Tavener]] (religious).<ref>{{Cite Grove |title=Great Britain |first1=Nicholas |last1=Iemperley |date=2002 |url=https://doi.org/10.1093/gmo/9781561592630.article.O006236 |url-access=subscription}}; {{Cite Grove |title=England (i) |date=2001 |url=https://doi.org/10.1093/gmo/9781561592630.article.40044 |url-access=subscription |first1=Stephen |last1=Banfield |first2=Ian |last2=Russell}}; {{Cite Grove |title=Wales |date=2001 |first1=Geraint |last1=Lewis |first2=Lyn |last2=Davies |first3=Phyllis |last3=Kinney |url=https://doi.org/10.1093/gmo/9781561592630.article.41108 |url-access=subscription}}; {{Cite Grove |title=Scotland |first1=Kenneth |last1=Elliott |first2=Francis |last2=Collinson |first3=Peggy |last3=Duesenberry |url=https://doi.org/10.1093/gmo/9781561592630.article.40113 |url-access=subscription |date=2001}}; {{Cite Grove |title=Ireland |first1=Harry |last1=White |first2=Nicholas |last2=Carolan |url=https://doi.org/10.1093/gmo/9781561592630.article.13901 |url-access=subscription |date=2011}}; {{Cite web |title=British 20th century composers |url=https://www.bbc.co.uk/bitesize/guides/zdjw7p3/revision/1 |access-date=21 April 2022 |website=[[BBC]]}}</ref> Recent classical singers include [[Alfie Boe]], [[Bryn Terfel]], [[Katherine Jenkins]], [[Michael Ball]], [[Roderick Williams]], [[Russell Watson]] and [[Sarah Brightman]], while [[Nicola Benedetti]] and [[Nigel Kennedy]] are renowned for their violin ability.<ref>{{Cite web |date=21 June 2022 |title=30 of the greatest violinists on record |url=https://www.gramophone.co.uk/features/article/30-of-the-greatest-violinists-on-record |access-date=4 March 2024 |website=Gramophone}};{{Cite web |date=1 January 2020 |title=Katherine Jenkins has officially sold the most classical albums this century |url=https://www.classicfm.com/radio/shows-presenters/classic-fm-chart/katherine-jenkins-most-classical-albums/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=6 May 2023 |title=Who is Roderick Williams, the British baritone and composer at the King's coronation? |url=https://www.classicfm.com/discover-music/roderick-williams-composer-baritone-singing-roles/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=23 February 2024 |title=Michael Ball |url=https://www.eno.org/artists/michael-ball-2/ |access-date=4 March 2024 |website=English National Opera}};{{Cite web |title=Alfie Bow |url=https://www.classicfm.com/artists/alfie-boe/ |access-date=4 March 2024 |website=Classic FM}};{{Cite web |date=11 July 2023 |title=Sarah Brightman facts |url=https://www.smoothradio.com/news/music/sarah-brightman-age-husband-songs/ |access-date=4 March 2024 |website=Smooth Radio}}</ref>
According to ''[[The New Grove Dictionary of Music and Musicians]]'' the term "[[pop music]]" originated in Britain in the mid-1950s to describe [[rock and roll]]'s fusion with the "new youth music".<ref>R. Middleton, et al., [http://www.oxfordmusiconline.com/public/book/omo_gmo "Pop"], ''Grove music online'', retrieved 14 March 2010. {{Subscription required}} {{Webarchive|url=https://web.archive.org/web/20110113160329/http://www.oxfordmusiconline.com/public/book/omo_gmo|date=13 January 2011}}</ref> ''The Oxford Dictionary of Music'' states that artists such as [[the Beatles]] and [[the Rolling Stones]] drove pop music to the forefront of popular music in the early 1960s.<ref>"Pop", [http://www.oxfordmusiconline.com/public/book/omo_t237 ''The Oxford Dictionary of Music''], retrieved 9 March 2010.{{Subscription required}} {{Webarchive|url=https://web.archive.org/web/20171112170116/http://www.oxfordmusiconline.com/public/book/omo_t237|date=12 November 2017}}</ref> Birmingham became known as the birthplace of [[heavy metal music|heavy metal]], with the band [[Black Sabbath]] starting there in the 1960s.<ref>{{Cite news |title=Birmingham, England ... the unlikely birthplace of heavy metal |work=CNN |date=1 July 2011 |first1=Laura |last1=Allsop |url=http://www.cnn.com/2011/WORLD/europe/07/01/birmingham.home.of.metal/index.html |access-date=28 February 2022 |postscript=;}} {{Cite web |last=Bentley |first=David |date=4 June 2013 |title=Midlands rocks! How Birmingham's industrial heritage made it the birthplace of heavy metal |url=http://www.birminghampost.co.uk/whats-on/music/birmingham-birthplace-of-heavy-metal-4031445 |access-date=28 February 2022 |website=[[Birmingham Post]]}}</ref> In the following years, Britain took part in the development of [[rock music]], with British acts pioneering [[hard rock]],<ref>{{Cite web |title=The Rolling Stones {{!}} Biography & History |url=https://www.allmusic.com/artist/the-rolling-stones-mn0000894465/biography |access-date=22 July 2020 |website=AllMusic}}</ref> [[raga rock]], heavy metal,<ref>{{Cite book |last=Tom Larson |url=https://books.google.com/books?id=vGJ7XmA8rjIC&pg=PA183 |title=History of Rock and Roll |publisher=Kendall/Hunt Pub. |year=2004 |isbn=978-0-7872-9969-9 |pages=183–187}}</ref> [[space rock]], [[glam rock]],<ref>{{Cite encyclopedia |title=Glam Rock |url=http://encarta.msn.com/dictionary_561509274/glam_rock.html |access-date=21 December 2008 |archive-url=https://web.archive.org/web/20090828224412/http://encarta.msn.com/dictionary_561509274/glam_rock.html |archive-date=28 August 2009 |encyclopedia=[[Encarta]]}}</ref> [[Gothic rock]],<ref>{{Cite web |year=2004 |title=NME Originals: Goth |url=https://www.nme.com/originals/4 |archive-url=https://web.archive.org/web/20080126150121/http://www.nme.com/originals/4 |archive-date=26 January 2008 |access-date=30 September 2013 |website=[[NME]]}}</ref> [[psychedelic rock]]<ref>{{Cite web |title=Pop/Rock » Psychedelic/Garage |url=https://www.allmusic.com/subgenre/psychedelic-garage-ma0000002800 |access-date=6 August 2020 |publisher=[[AllMusic]]}}</ref> and [[punk rock]].<ref>{{cite magazine |author1=Charles M. Young |title=Rock is Sick and Living in London |url=https://www.rollingstone.com/feature/a-report-on-the-sex-pistols-119989/ |magazine=Rolling Stone |access-date=23 February 2026 |date=20 October 1977 |archive-url=https://web.archive.org/web/20250328094721/https://www.rollingstone.com/feature/a-report-on-the-sex-pistols-119989/ |archive-date=28 March 2025}}</ref> British acts also developed [[neo soul]] and created [[dubstep]].<ref>Henderson, Alex (1 August 2003). [https://web.archive.org/web/20101104165122/http://allmusic.com/explore/essay/british-soul-t2160 British Soul]. Allmusic. Retrieved 6 March 2011.; [http://www.allmusic.com/style/dubstep-ma0000004465 AllMusic – Dubstep] {{Webarchive|url=https://web.archive.org/web/20170923151236/http://www.allmusic.com/style/dubstep-ma0000004465|date=23 September 2017}} "Absorbed and transfigured elements of techno, drum'n' bass and dub"; {{Cite news |last=Goldman |first=Vivien |date=31 January 2012 |title=Local Groove Does Good: The Story Of Trip-Hop's Rise From Bristol |work=NPR |url=https://www.npr.org/sections/therecord/2012/01/31/142607358/local-groove-does-good-the-story-of-trip-hops-rise-from-bristol}}</ref> The UK has produced some of the most prominent English-speaking [[rappers]] along with the United States, including [[Stormzy]], [[Kano (rapper)|Kano]], [[Yxng Bane]], [[Ramz (rapper)|Ramz]], [[Little Simz]] and [[Skepta]].<ref>{{Cite magazine |title=5 U.K. Rappers Primed to Take Over America in 2018 |url=https://www.billboard.com/music/rb-hip-hop/uk-rappers-to-watch-2018-8097878/ |magazine=Billboard |access-date=18 June 2018}}</ref>
[[File:The SSE Hydro arena - geograph.org.uk - 6725739.jpg|thumb|right|The [[OVO Hydro]] in [[Glasgow]], Scotland, a 14,500-capacity arena consistently ranked within the top ten busiest venues worldwide<ref>{{cite web |title=OVO Hydro {{!}} SEC |url=https://www.sec.co.uk/organise-an-event/event-spaces/the-ovo-hydro |website=www.sec.co.uk |access-date=9 February 2026 |language=en}}</ref>]]
The Beatles have international sales of over 1 billion units and are the [[List of best-selling music artists|biggest-selling band]], in addition to being [[Cultural impact of the Beatles|widely regarded as the most influential band]] in the history of popular music.<ref name="Beatles sales">{{Cite web |title=1960–1969 |url=http://www.emimusic.com/about/history/1960-1969/# |archive-url=https://web.archive.org/web/20140425011032/http://www.emimusic.com/about/history/1960-1969 |archive-date=25 April 2014 |access-date=9 March 2015 |publisher=EMI Group}}</ref><ref name="McCartney">{{Cite magazine |date=8 June 1992 |title=Paul At Fifty |url=http://www.time.com/time/magazine/article/0,9171,975715-2,00.html |magazine=Time |location=New York |archive-url=https://web.archive.org/web/20090206120350/http://www.time.com/time/magazine/article/0,9171,975715-2,00.html |archive-date=6 February 2009}}</ref><ref name="Guinness">[https://books.google.com/books?id=rdU1xtIWJz0C Most Successful Group] ''[[The Guinness Book of Records]]'' 1999, p. 230. Retrieved 19 March 2011.</ref><ref>{{Cite news |date=25 November 2010 |title=Beatles a big hit with downloads |work=Belfast Telegraph |url=http://www.belfasttelegraph.co.uk/entertainment/music/news/beatles-a-big-hit-with-downloads-15013117.html |access-date=16 May 2011}}</ref> Other prominent British contributors to popular music over the last 50 years include the Rolling Stones, [[Pink Floyd]], [[Queen (band)|Queen]], [[Led Zeppelin]], the [[Bee Gees]] and [[Elton John]], all of whom have worldwide record sales of 200 million or more.<ref>{{Cite press release |title=British rock legends get their own music title for PlayStation3 and PlayStation2 |date=2 February 2009 |publisher=[[EMI]] |url=http://www.emimusic.com/news/2009/singstar®-queen-to-be-launched-by-sony-computer-entertainment-europe |access-date=9 March 2015 |archive-url=https://web.archive.org/web/20140423012539/http://www.emimusic.com/news/2009/singstar%C2%AE-queen-to-be-launched-by-sony-computer-entertainment-europe |archive-date=23 April 2014}}; {{Cite news |last=Khan |first=Urmee |date=17 July 2008 |title=Sir Elton John honoured in Ben and Jerry ice cream |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/newstopics/celebritynews/2305273/Sir-Elton-John-honoured-in-Ben-and-Jerry-ice-cream.html |archive-url=https://web.archive.org/web/20080730164432/http://www.telegraph.co.uk/news/newstopics/celebritynews/2305273/Sir-Elton-John-honoured-in-Ben-and-Jerry-ice-cream.html |archive-date=30 July 2008}}; {{Cite news |last=Alleyne |first=Richard |date=19 April 2008 |title=Rock group Led Zeppelin to reunite |work=The Telegraph |location=London |url=https://www.telegraph.co.uk/news/uknews/1562875/Rock-group-Led-Zeppelin-to-reunite.html |url-status=live |url-access=subscription |access-date=31 March 2010 |archive-url=https://ghostarchive.org/archive/20220110/https://www.telegraph.co.uk/news/uknews/1562875/Rock-group-Led-Zeppelin-to-reunite.html |archive-date=10 January 2022}}{{Cbignore}}; {{Cite news |date=11 July 2006 |title=Floyd 'true to Barrett's legacy' |work=BBC News |url=http://news.bbc.co.uk/1/hi/entertainment/5170644.stm}}; {{Cite news |last=Holton |first=Kate |date=17 January 2008 |title=Rolling Stones sign Universal album deal |work=Reuters |url=https://www.reuters.com/article/entertainmentNews/idUSL1767761020080117 |access-date=26 October 2008}}; {{Cite news |last=Walker |first=Tim |date=12 May 2008 |title=Jive talkin': Why Robin Gibb wants more respect for the Bee Gees |work=Independent |location=London |url=https://www.independent.co.uk/arts-entertainment/music/features/jive-talkin-why-robin-gibb-wants-more-respect-for-the-bee-gees-826116.html |access-date=26 October 2008 |archive-url=https://web.archive.org/web/20111013215157/http://www.independent.co.uk/arts-entertainment/music/features/jive-talkin-why-robin-gibb-wants-more-respect-for-the-bee-gees-826116.html |archive-date=13 October 2011}}</ref> The [[Brit Awards]] are the [[British Phonographic Industry|BPI]]'s annual music awards, and some of the British recipients of the [[Brit Award for Outstanding Contribution to Music|Outstanding Contribution to Music]] award include [[the Who]], [[David Bowie]], [[Eric Clapton]], [[Rod Stewart]], [[the Police]] and [[Fleetwood Mac]] (who are a British-American band).<ref>[https://www.theguardian.com/news/datablog/2012/feb/22/brit-awards-winners-list-2012 "Brit awards winners list 2012: every winner since 1977"]. ''The Guardian'' (London). Retrieved 28 February 2012.</ref> <!-- Please note that the following list of recent musicians and groups includes only those selling more than 30 million records. -->More recent UK music acts that have had international success include [[George Michael]], [[Oasis (band)|Oasis]], [[Spice Girls]], [[Radiohead]], [[Coldplay]], [[Arctic Monkeys]], [[Robbie Williams]], [[Amy Winehouse]], [[Susan Boyle]], [[Adele]], [[Ed Sheeran]], [[Lewis Capaldi]], [[One Direction]], [[Harry Styles]] and [[Dua Lipa]].<ref>{{Cite web |date=12 January 2020 |title=Harry Styles Has Weathered the Post-Boy Band Storm Better Than Most |url=https://consequence.net/2020/01/harry-styles-solo-career/ |access-date=15 September 2020 |website=Consequence of Sound}}; {{Cite magazine |date=16 July 2020 |title=10 Years of One Direction: The Story of the World's Biggest Boy Band, Told With the Fans Who Made It Happen |magazine=Billboard |url=https://www.billboard.com/music/pop/one-direction-ten-year-anniversary-fan-interviews-9419436/ |access-date=15 September 2020}}; {{Cite news |last=Corner, Lewis |date=16 February 2012 |title=Adele, Coldplay biggest-selling UK artists worldwide in 2011 |work=Digital Spy |url=http://www.digitalspy.co.uk/music/news/a366130/adele-coldplay-biggest-selling-uk-artists-worldwide-in-2011.html |access-date=22 March 2012}}; {{Cite web |title=Ed Sheeran's career journey: From street busker to global superstar |url=https://planetradio.co.uk/hits-radio/entertainment/celebrity/ed-sheeran-career-timeline/ |access-date=7 January 2023 |website=PlanetRadio.co.uk |last=Magliola |first=Anna Sky |date=30 November 2022}}; {{Cite web |url=https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we |title=Dua Lipa, 77.5M Monthly listeners |date=6 May 2024 |publisher=Spotify}}</ref> As of 2024 the UK is the world's [[List of largest music markets|third-largest music market]] behind the US and Japan,<ref>{{Cite web |last=Paine |first=Andre |date=10 September 2024 |title=IFPI report reveals EU risks falling behind in global market - UK still among top music exporters |url=https://www.musicweek.com/labels/read/ifpi-report-reveals-eu-risks-falling-behind-in-global-market-uk-still-among-top-music-exporters/090424 |access-date=17 November 2025 |website=[[Music Week]] |language=en}}</ref> and in 2021 was the second-largest exporter of music behind the US.<ref>{{Cite news |last=Savage |first=Mark |date=16 June 2021 |title=British music exports reach a record high |url=https://www.bbc.com/news/entertainment-arts-57486272 |access-date=17 November 2025 |work=[[BBC]] |language=en-GB}}</ref>
Many British cities are known for their music. Acts from Liverpool have had 54 UK chart number 1 hit singles, more per capita than any other city worldwide.<ref>{{Cite news |last=Hughes |first=Mark |date=14 January 2008 |title=A tale of two cities of culture: Liverpool vs Stavanger |work=Independent |location=London |url=https://www.independent.co.uk/news/uk/this-britain/a-tale-of-two-cities-of-culture-liverpool-vs-stavanger-770076.html?r=RSS |access-date=2 August 2009 |archive-url=https://web.archive.org/web/20180618175425/https://www.independent.co.uk/news/uk/this-britain/a-tale-of-two-cities-of-culture-liverpool-vs-stavanger-770076.html?r=RSS |archive-date=18 June 2018}}</ref> Glasgow's contribution was recognised in 2008 when it was named a [[City of Music (UNESCO)|City of Music]] by [[UNESCO]].<ref>{{Cite news |date=20 August 2008 |title=Glasgow gets city of music honour |work=BBC News |url=http://news.bbc.co.uk/1/hi/scotland/glasgow_and_west/7570915.stm |access-date=2 August 2009}}</ref> Manchester played a role in the spread of dance music such as [[acid house]], and from the mid-1990s, [[Britpop]]. London and Bristol are closely associated with the origins of [[electronic music]] sub-genres such as [[drum and bass]] and [[trip hop]].<ref>{{Cite web |title=Out of the melting pot: The origins and evolution of drum'n'bass |url=https://www.redbull.com/gb-en/history-of-drum-and-bass-music |access-date=1 August 2021 |website=Red Bull |date=25 June 2020}}</ref>
UK dance music traces its roots back to the black British [[Sound system (Jamaican)|Sound System Culture]] and the [[New Age travellers|New Age Traveller]] movement of the 60s and 70s,<ref>{{Cite web |date=3 August 2023 |title=Parties, protest and police: the neglected histories of UK dance music |url=https://www.dazeddigital.com/music/article/60511/1/ed-gillet-new-book-party-lines-politics-history-uk-dance-music-clubbing |access-date=27 February 2024 |website=Dazed}}</ref> it also has influences from the [[House music|Chicago House]] and [[Detroit techno|Detroit Techno]] scenes. In the late 80's, dance music exploded with [[Rave]] culture mainly [[Acid House]] tracks which were made mainstream with novelty records (such as Smart E's [[Sesame's Treet]] and the Prodigy's [[Charly (song)|Charly]])<ref>{{Cite web |date=20 January 2001 |title=Rave |url=https://www.oxfordmusiconline.com/search?q=rave |access-date=27 February 2024 |website=Oxford Music Online}}</ref> and the [[Balearic beat|Balearic sound]] brought back from the Ibiza club scene. This led on to genres such as [[UK Garage]], [[Speed Garage]], [[Drum and bass]], [[Jungle music|Jungle]], [[Trance music|Trance]], and [[Dubstep]]. Influential UK dance acts past and present include [[808 State]], [[Orbital (band)|Orbital]], [[the Prodigy]], [[Underworld (band)|Underworld]], [[Roni Size]], [[Leftfield]], [[Massive Attack]], [[Groove Armada]], [[Fatboy Slim]], [[Faithless]], [[Basement Jaxx]], [[Chemical Brothers]], [[Disclosure (band)|Disclosure]], [[Calvin Harris]], and [[Fred Again]].<ref>{{Cite web |title=Mixmag's Greatest Dance Act of all Time Revealed |date=19 January 2012 |url=http://www.mixmag.net/words/news/mixmags-greatest-dance-act-revealed |archive-date=14 April 2012 |archive-url=https://web.archive.org/web/20120414045620/http://www.mixmag.net/words/news/mixmags-greatest-dance-act-revealed}};{{Cite web |date=26 February 2024 |title=Fred Again: who is the DJ who has thousands queuing for a 'secret rave' at the Sydney Opera House? |url=https://www.theguardian.com/music/2024/feb/27/fred-again-dj-sydney-opera-house-secret-show-tickets-sell-out-profile-bio-details |access-date=27 February 2024 |website=The Guardian}}</ref> Other influential UK DJs include [[Judge Jules]], [[Pete Tong]], [[Carl Cox]], [[Paul Oakenfold]], [[John Digweed]] and [[Sasha (dj)|Sasha]].<ref>{{Cite web |title=Top 100 DJs Poll results 2003 |url=http://djmag.com/top100chart.asp |archive-date=7 December 2003 |archive-url=https://web.archive.org/web/20031207071739/http://djmag.com/top100chart.asp}}</ref>
=== Cinema ===
{{Main|Cinema of the United Kingdom|Independent cinema in the United Kingdom}}
The United Kingdom has had a considerable influence on the history of the cinema. The British directors [[Alfred Hitchcock]], whose film ''[[Vertigo (film)|Vertigo]]'' is considered by some critics as the [[List of films considered the best|best film of all time]],<ref>{{Cite news |date=2 August 2012 |title=Vertigo is named 'greatest film of all time' |work=BBC News |url=https://www.bbc.co.uk/news/entertainment-arts-19078948 |access-date=18 August 2012}}</ref> and [[David Lean]], who directed ''[[Lawrence of Arabia (film)|Lawrence of Arabia]]'', are amongst the most critically acclaimed directors ever.<ref>{{Cite web |title=The Directors' Top Ten Directors |url=http://www.bfi.org.uk/sightandsound/topten/poll/directors-directors.html |url-status=dead |archive-url=https://web.archive.org/web/20120517155218/http://www.bfi.org.uk/sightandsound/topten/poll/directors-directors.html |archive-date=17 May 2012 |publisher=British Film Institute}}</ref> Recent popular directors include [[Christopher Nolan]], [[Sam Mendes]], [[Steve McQueen (director)|Steve McQueen]], [[Richard Curtis]], [[Danny Boyle]], [[Tony Scott]] and [[Ridley Scott]].<ref>{{Cite web |title=The 24 Best British Directors of All Time |date=13 May 2023 |url=https://movieweb.com/best-british-directors-of-all-time/ |access-date=17 February 2024 |publisher=Movieweb}}</ref><ref>{{Cite web |title=Top 22 U.K. Film Directors |url=https://www.imdb.com/list/ls062383258/ |access-date=17 February 2024 |publisher=IMDb}}</ref><ref>{{Cite web |title=5 of the best ... Richard Curtis films |url=https://www.thetimes.com/culture/tv-radio/article/5-of-the-best-richard-curtis-films-tzxx9fv2h |work=The Times |access-date=4 June 2024 |date=17 April 2024}}</ref><ref>{{Cite web |title=The UK's top 50 film directors |date=23 May 2012 |url=https://www.televisual.com/news/the-uk-s-top-50-film-directors_bid-357/ |access-date=17 February 2024 |publisher=Televisual}}</ref> Many British actors have achieved international fame and critical success. Some of the most commercially successful films have been produced in the United Kingdom, including two of the [[List of highest-grossing film series|highest-grossing film franchises]] (''[[Harry Potter (film series)|Harry Potter]]'' and ''[[James Bond (film series)|James Bond]]'').<ref>{{Cite news |date=11 September 2007 |title=Harry Potter becomes highest-grossing film franchise |work=The Guardian |location=London |url=https://www.theguardian.com/film/2007/sep/11/jkjoannekathleenrowling |access-date=2 November 2010}}</ref>
2019 was a particularly good year for British films which grossed around £10.3 billion globally, accounting for 28.7 per cent of global box office revenue.<ref>{{Cite web |title=UK Film Industry Statistics 2023 |date=10 April 2023 |url=https://www.socialfilms.co.uk/blog/uk-film-industry-statistics |archive-url=https://web.archive.org/web/20240217211749/https://www.socialfilms.co.uk/blog/uk-film-industry-statistics |archive-date=17 February 2024 |access-date=17 February 2024}}</ref> UK box-office takings totalled £1.25 billion in 2019, with around 176 million admissions.<ref>{{Cite web |title=The UK box office in 2019 |url=https://www2.bfi.org.uk/sites/bfi.org.uk/files/downloads/bfi-uk-box-office-2019.pdf |archive-url=https://web.archive.org/web/20240217214846/https://www2.bfi.org.uk/sites/bfi.org.uk/files/downloads/bfi-uk-box-office-2019.pdf |archive-date=17 February 2024 |access-date=17 February 2024}}</ref> In 2023 UK film and television studio stage space stood at 6.9 million sq ft, with 1 million sq ft added in the past year with more in development.<ref>{{Cite web |title=UK Film and Television Studios Market Report |url=https://content.knightfrank.com/research/2439/documents/en/uk-film-and-television-studios-market-2023-10567.pdf |access-date=17 February 2024 |publisher=Knight Frank}}</ref> The annual [[British Academy Film Awards|BAFTA Film Awards]] are hosted by the [[British Academy of Film and Television Arts]].<ref>{{Cite news |date=26 February 2001 |title=Baftas fuel Oscars race |work=BBC News |url=http://news.bbc.co.uk/1/hi/entertainment/1190562.stm |access-date=14 February 2011}}</ref>
=== Cuisine ===
{{Main|British cuisine}}
{{Further|English cuisine|Scottish cuisine|Welsh cuisine|Northern Irish cuisine}}
[[File:Fish, chips and mushy peas.jpg|thumb|[[Fish and chips]], a traditional British dish, served with lemon, tartar sauce and mushy peas]]
British cuisine developed from influences reflective of its land, settlements, [[Immigration to the United Kingdom|arrivals of new settlers and immigrants]], trade and colonialism. The food of England has historically been characterised by simplicity of approach and a reliance on the high quality of natural produce.<ref>{{Cite book |last=Else |first=David |title=Inghilterra |publisher=EDT srl |date=2007 |isbn=978-88-6040-136-6 |page=76}}</ref> The traditional [[Sunday roast]] is one example, featuring a [[roasting|roast joint]] (usually of beef), lamb, chicken, or pork, often [[free range]] (and generally grass-fed, in the case of beef). Roasts are served with either roasted or boiled vegetables, [[Yorkshire pudding]] and [[gravy]]. Other traditional meals include [[meat pie]]s and [[stew]]s. A poll by [[YouGov]] in 2019 rated classic British food, with more than 80 per cent liking the Sunday roast, Yorkshire pudding, [[fish and chips]], [[crumpet]]s and the [[full English breakfast]].<ref>{{Cite web |url=https://yougov.co.uk/topics/consumer/articles-reports/2019/06/12/classic-british-cuisine-ranked-britons |date=11 June 2019 |title=Classic British cuisine ranked by Britons }}{{Dead link|date=May 2026 |bot=InternetArchiveBot }}</ref>
The UK is home to a large selection of [[fine dining]]. The nation hosts multiple restaurant guides such as ''[[The Good Food Guide]]'' and ''[[Harden's]]''. In 2025 there were 197 restaurants with a [[Michelin Star]]; [[List of Michelin 3-star restaurants in the United Kingdom|ten of which have received a three-star rating]].<ref>{{cite web |url=https://guide.michelin.com/en/gb/restaurants/all-starred |title=United Kingdom |publisher=Michelin Guide |access-date=12 May 2025}}</ref> Sweet foods are common within British cuisine, and there is a long list of [[List of British desserts|British desserts]]. Afternoon tea is a light afternoon meal served with tea in tea rooms and hotels around the United Kingdom, with the tradition dating back to around 1840.<ref>{{Cite web |title=The tea-rific history of Victorian afternoon tea |work=The British Museum |url=https://www.britishmuseum.org/blog/tea-rific-history-victorian-afternoon-tea |access-date=11 April 2023}}</ref> A poll from July 2024 revealed that 3 per cent of the UK population follow a [[vegan]] diet, 6 per cent are [[vegetarian]], and 13 per cent identify as [[flexitarian]] (following a mainly vegetarian diet).<ref>{{Cite web |title=Dietary choices of Brits (e.g. vegeterian, flexitarian, meat-eater etc) |url=https://yougov.co.uk/topics/society/trackers/dietery-choices-of-brits-eg-vegeterian-flexitarian-meat-eater-etc |access-date=26 November 2024 |date=8 July 2024 |website=YouGov.co.uk}}</ref> The British Empire facilitated knowledge of [[Indian cuisine]] with its "strong, penetrating spices and herbs". British cuisine has absorbed the cultural influence of those who have settled in Britain, producing hybrid dishes, such as [[chicken tikka masala]].<ref>{{Cite news |date=19 April 2001 |title=Robin Cook's chicken tikka masala speech |work=The Guardian |location=London |url=https://www.theguardian.com/world/2001/apr/19/race.britishidentity |access-date=7 September 2021}}; {{Cite news |last=BBC E-Cyclopedia |date=20 April 2001 |title=Chicken tikka masala: Spice and easy does it |publisher=BBC |url=http://news.bbc.co.uk/1/hi/special_report/1999/02/99/e-cyclopedia/1285804.stm |access-date=28 September 2007}}</ref> The British have embraced world cuisine and regularly eat recipes or fast food from other European countries, the Caribbean and Asia.
The UK has many [[gastropub]]s and is the birthplace of many alcoholic drinks including several beer styles such as [[pale ale]], [[India pale ale]], [[bitter (beer)|bitter]], [[brown ale]], [[porter (beer)|porter]], and [[stout]]. The number of [[craft beer]]s and microbreweries has expanded rapidly in the last two decades.<ref>{{Cite web |title=A guide to British Beer |url=https://www.expatica.com/uk/lifestyle/food-drink/british-beer-469903/ |access-date=25 November 2024 |website=Expatica}}</ref> Other popular alcoholic drinks produced in the UK include [[Scotch whisky]], [[Wine from the United Kingdom|English wine]], [[gin]], [[perry]] and [[cider]].
=== Sport ===
{{Main|Sport in the United Kingdom|Great Britain at the Olympics}}
{{Further|Sport in England|Sport in Scotland|Sport in Wales|Sport in Northern Ireland}}
[[File:City vs United FA Cup final 2023.jpg|thumb|right|The [[2023 FA Cup final]] at [[Wembley Stadium]] between [[Manchester City]] and [[Manchester United]]]]
[[File:Old 18th tee lr.jpg|thumb|right|Golf originated from the [[Old Course at St Andrews]] in Scotland.]]
[[Association football]], [[tennis]], [[table tennis]], [[badminton]], [[rugby union]], [[rugby league]], [[rugby sevens]], [[golf]], [[boxing]], [[netball]], [[water polo]], [[field hockey]], [[English billiards|billiards]], [[darts]], [[Rowing (sport)|rowing]], [[rounders]] and [[cricket]] originated or were substantially developed in the UK, with the rules and codes of many modern sports invented and codified in the Victorian era.{{efn|In 2012, the president of the IOC, [[Jacques Rogge]], stated, "This great, sports-loving country is widely recognised as the birthplace of modern sport. It was here that the concepts of sportsmanship and fair play were first codified into clear rules and regulations. It was here that sport was included as an educational tool in the school curriculum."<ref>{{Cite web |url=http://www.olympic.org/Documents/Games_London_2012/London_2012_Opening_ceremony_Speech_Jacques_Rogge.pdf |title=Opening Ceremony of the Games of the XXX Olympiad |website=Olympic.org |access-date=30 November 2013 |date=27 July 2012 |archive-date=19 August 2013 |archive-url=https://web.archive.org/web/20130819135346/http://www.olympic.org/Documents/Games_London_2012/London_2012_Opening_ceremony_Speech_Jacques_Rogge.pdf |url-status=dead}}</ref><ref>{{Cite web |url=http://uk.reuters.com/article/uk-oly-preview-ad-idUKBRE86M0I720120723 |title=Unparalleled Sporting History |work=Reuters |access-date=30 November 2013 |last=Mehaffey |first=John |location=London |archive-date=25 May 2017 |archive-url=https://web.archive.org/web/20170525164121/http://uk.reuters.com/article/uk-oly-preview-ad-idUKBRE86M0I720120723 |url-status=dead}}</ref>}}
A poll in 2003 found that football is the most popular sport in the UK.<ref name="sports poll">{{Cite web |date=22 December 2003 |title=Rugby Union 'Britain's Second Most Popular Sport' |url=http://www.ipsos-mori.com/researchpublications/researcharchive/928/Rugby-Union-Britains-Second-Most-Popular-Sport.aspx |access-date=28 April 2013 |publisher=Ipsos-Mori}}</ref> England is recognised by [[FIFA]] as the birthplace of club football, and the [[Football Association]] is the oldest of its kind, with the [[Laws of the Game (association football)|rules of football]] first drafted in 1863 by [[Ebenezer Cobb Morley]].<ref>{{Cite news |last=Rudd |first=Alyson |date=7 April 2008 |title=The father of football deserves much more |work=The Times |location=London |url=http://www.timesonline.co.uk/tol/sport/football/article3694775.ece |url-access=subscription |access-date=29 January 2015 |archive-date=4 June 2011 |archive-url=https://web.archive.org/web/20110604183514/http://www.timesonline.co.uk/tol/sport/football/article3694775.ece |url-status=dead}}; {{Cite web |date=24 October 2007 |title=Sheffield FC: 150 years of history |url=https://www.fifa.com/worldfootball/clubfootball/news/newsid=621801.html |archive-url=https://web.archive.org/web/20071025033006/http://www.fifa.com/worldfootball/clubfootball/news/newsid=621801.html |archive-date=25 October 2007 |access-date=29 January 2015 |publisher=[[FIFA]]}}</ref> Each of the [[Home Nations]] (England, Scotland, Wales and Northern Ireland) has its own football association, national team and [[league system]], and each is individually a governing member of the [[International Football Association Board]] alongside FIFA. The English top division, the [[Premier League]], is the most watched football league in the world.<ref>{{Cite news |last=Ebner |first=Sarah |date=2 July 2013 |title=History and time are key to power of football, says Premier League chief |work=The Times |location=London |url=http://www.thetimes.co.uk/tto/public/ceo-summit/article3804923.ece |url-access=subscription |access-date=30 November 2013}}</ref> The first international football match was contested by [[England national football team|England]] and [[Scotland national football team|Scotland]] on 30 November 1872.<ref>{{Cite web |last=Mitchell, Paul |author-link=Paul Mitchell (broadcaster) |date=November 2005 |title=The first international football match |url=https://www.bbc.co.uk/scotland/sportscotland/asportingnation/article/0012/index.shtml |access-date=15 December 2013 |publisher=BBC Sport Scotland}}</ref> England, Scotland, [[Wales national football team|Wales]] and [[Northern Ireland national football team|Northern Ireland]] usually compete as separate countries in international competitions.<ref>{{Cite news |last=Harlow |first=Phil |date=5 August 2008 |title=Why is there no GB Olympics football team? |work=[[BBC Sport]] |url=http://news.bbc.co.uk/sport1/hi/olympics/football/7529807.stm |access-date=31 December 2010}}</ref>
In 2003 rugby union was ranked the second-most-popular sport in the UK.<ref name="sports poll" /> The sport was created in [[Rugby School]], Warwickshire, and the [[1871 England versus Scotland rugby union match|first rugby international]] took place on 27 March 1871 between [[England national rugby union team|England]] and [[Scotland national rugby union team|Scotland]].<ref>{{Cite web |url=https://www.bbc.co.uk/news/uk-england-coventry-warwickshire-25946757 |title=Six ways the town of Rugby helped change the world |work=BBC News |access-date=29 January 2015 |date=1 February 2014}}</ref><ref>{{Cite book |last1=Godwin |first1=Terry |last2=Rhys |first2=Chris |year=1981 |title=The Guinness Book of Rugby Facts & Feats |page=10 |publisher=Guinness Superlatives |isbn=978-0-85112-214-4}}</ref> England, Scotland, [[Wales national rugby union team|Wales]], [[Ireland national rugby union team|Ireland]], [[France national rugby union team|France]] and [[Italy national rugby union team|Italy]] compete in the [[Six Nations Championship]], the premier international rugby union tournament in the northern hemisphere. [[Sports governing bodies]] in [[Rugby union in England|England]], [[Rugby union in Scotland|Scotland]], [[Rugby union in Wales|Wales]] and [[Rugby union in Ireland|Ireland]] organise and regulate the game separately.<ref>{{Cite book |last1=Louw, Jaco |url=https://books.google.com/books?id=0-IiowvNomMC&pg=PA95 |title=The Girlfriends Guide to Rugby |last2=Nesbit, Derrick |publisher=South Publishers |year=2008 |isbn=978-0-620-39541-0 |location=Johannesburg}}</ref> Every four years the Home Nations make a combined team known as the [[British and Irish Lions]] which tours Australia, New Zealand and South Africa.
The United Kingdom hosted the [[Summer Olympic Games]] in [[1908 Summer Olympics|1908]], [[1948 Summer Olympics|1948]] and [[2012 Summer Olympics|2012]], with London acting as the host city on all three occasions. Birmingham hosted the [[2022 Commonwealth Games]], the seventh time a country of the United Kingdom hosted the [[Commonwealth Games]] (England, Scotland and Wales have each hosted the Commonwealth Games at least once).<ref>{{Cite news |title=The journey of India in Commonwealth Games in 2022 |work=The Times of India |url=https://timesofindia.indiatimes.com/readersblog/allaboutsports/the-journey-of-india-in-commonwealth-games-in-2022-44477/ |access-date=29 June 2023}}</ref>
=== Symbols ===
{{Main|Symbols of the United Kingdom, the Channel Islands and the Isle of Man|l1 = Symbols of the United Kingdom}}
[[File:Queen Elizabeth II Platinum Jubilee 2022 - Platinum Pageant (52123378222).jpg|thumb|Union Jack flags on [[The Mall, London|The Mall]], London]]
The [[flag of the United Kingdom]] is the [[Union Flag]], which is also referred to as the Union Jack.<ref>{{Cite web |title=Union Jack or Union Flag? |url=https://www.flaginstitute.org/wp/uk-flags/the-union-jack-or-the-union-flag |access-date=26 September 2022 |website=The Flag Institute}}</ref> It was created in 1606 by the superimposition of the [[flag of England]], representing [[Saint George]], on the [[flag of Scotland]], representing [[Saint Andrew]], and was updated in 1801 with the addition of [[Saint Patrick's Flag]].<ref>{{Cite web |title=college-of-arms.gov.uk |url=https://www.college-of-arms.gov.uk/resources/union-flag-approved-designs |access-date=14 January 2022 |publisher=The College of Arms}}</ref> Wales is not represented in the Union Flag, as Wales had been conquered and [[annexed]] to England prior to the formation of the United Kingdom. The possibility of redesigning the Union Flag to include representation of Wales was discussed in 2007.<ref>{{Cite news |date=27 November 2007 |title=Welsh dragon call for Union flag |work=BBC News |url=http://news.bbc.co.uk/1/hi/uk/7114248.stm |access-date=17 October 2008}}</ref> The [[national anthem]] of the United Kingdom is "[[God Save the King]]", with "King" replaced with "Queen" in the lyrics whenever the monarch is a woman.
[[Britannia]] is a [[national personification]] of the United Kingdom, originating from [[Roman Britain]].<ref>{{Cite web |title=Britannia on British Coins |url=http://www.24carat.co.uk/britanniaframe.html |access-date=25 June 2006 |publisher=Chard}}</ref> Beside [[The Lion and the Unicorn]] and the [[Welsh Dragon|dragon]] of heraldry, the [[bulldog]] is an iconic animal and commonly represented with the Union Flag.<ref>{{Cite book |last=Baker |first=Steve |title=Picturing the Beast |publisher=University of Illinois Press |year=2001 |isbn=978-0-252-07030-3 |page=52}}</ref> A rare personification is a character originating in the 18th century, [[John Bull]].<ref>{{Cite web |last=<!--Not stated--> |title=Who is John Bull |url=https://www.loc.gov/wiseguide/jan04/johnbull.html |access-date=11 January 2022 |publisher=The Library of Congress}}</ref>
[[National symbols of England|England]], [[National symbols of Wales|Wales]] and [[National symbols of Scotland|Scotland]] each have their own national symbols, including their national flags. [[National symbols of Ireland, the Republic of Ireland and Northern Ireland|Northern Ireland]] also has symbols, many of which are shared with the [[Republic of Ireland]].
== See also ==
{{Portal|United Kingdom|England|Northern Ireland|Scotland|Wales}}
* [[Outline of the United Kingdom]]
** [[Outline of England]]
** [[Outline of Northern Ireland]]
** [[Outline of Scotland]]
** [[Outline of Wales]]
* [[International rankings of the United Kingdom]]
* [[Historiography of the United Kingdom]]
* [[Historiography of the British Empire]]
* [[United Kingdom–Crown Dependencies Customs Union]]
== Notes ==
{{Notelist}}
== References ==
{{Reflist}}
== External links ==
{{Sister project links|auto=yes}}
* [https://www.bbc.co.uk/news/world-europe-18023389 United Kingdom] from [[BBC News]]
* [https://web.archive.org/web/20260118175542/https://www.cia.gov/the-world-factbook/countries/united-kingdom/ United Kingdom]. ''[[The World Factbook]]''. [[Central Intelligence Agency]].
* [https://web.archive.org/web/20090406224510/http://ucblibraries.colorado.edu/govpubs/for/british.htm United Kingdom] from ''UCB Libraries GovPubs'' (archived 6 April 2009)
* {{Wikiatlas|United Kingdom}}
* {{OSM relation|62149}}
* [http://www.ifs.du.edu/ifs/frm_CountryProfile.aspx?Country=GB Key Development Forecasts for the United Kingdom] from [[International Futures]]
=== Government ===
* [https://www.gov.uk/ Official website of HM Government]
* [https://www.royal.uk/ Official website of the British Monarchy]
* [https://www.gov.uk/government/organisations/prime-ministers-office-10-downing-street Official website of the British Prime Minister's Office]
=== Travel ===
* [http://www.visitbritain.com/en/ Official tourist guide to Britain]
<!-- Please discuss links on the talk page before adding them to this list – remember to read the WP:EL guideline.-->
{{United Kingdom topics}}
{{Navboxes
| list =
{{United Kingdom constituents and affiliations}}
{{British Isles}}
{{Sovereign states of Europe}}
{{Commonwealth realms}}
{{English official language clickable map}}
{{The Commonwealth}}
}}
{{Authority control}}
{{Coord|55|N|3|W|type:country_region:GB|display=title}}
[[Category:United Kingdom| ]]
[[Category:British Islands]]
[[Category:Countries in Europe]]
[[Category:Countries and territories where English is an official language]]
[[Category:G20 members]]
[[Category:Island countries]]
[[Category:Member states of NATO]]
[[Category:Member states of the Commonwealth of Nations]]
[[Category:Member states of the Council of Europe]]
[[Category:Member states of the United Nations]]
[[Category:OECD members]]
[[Category:States and territories established in 1707]]
[[Category:States and territories established in 1801]]
[[Category:States and territories established in 1922]]
pov14ogirxro821rmu3zv10sbdjtyba
Mossa:Peji In Siri
1
897
9296
8137
2026-08-23T04:41:31Z
RAPTOR7762
18
RAPTOR7762 moved page [[Mossa:Peji Unsiri]] to [[Mossa:Peji In Siri]]
8137
wikitext
text/x-wiki
#REDIRECT [[Wikipidiya:Bobin miyƴah]]
6gvyoa3q4wwp6zrezpa27wpzdn9m60v
Tempilet:Bmbox
10
901
9283
8812
2026-08-23T03:41:05Z
RAPTOR7762
18
/* */
9283
wikitext
text/x-wiki
{| style="width: 100%; margin: 0 auto 0.2em; border-radius: 12px; border: 1.5px solid {{{border color|#1e3a8a}}}; border-left:10px solid {{{border color|#1e3a8a}}};"
| style="padding-left:15px; width:{{{image_width|40px}}}" | <div style="width:{{{image_width|40px}}}">[[Fayil:{{{image|Information icon4.svg}}}|{{{image_width|40px}}}|link=]]</div>
| style="padding-left:15px" | {{{text|}}}
|}
{{clear}}<noinclude>
{{Documentation}}
</noinclude>
68kv5rrao5vmsyh2w8if0iwcknu62rc
9284
9283
2026-08-23T03:41:20Z
RAPTOR7762
18
Protected "[[Tempilet:Bmbox]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
9283
wikitext
text/x-wiki
{| style="width: 100%; margin: 0 auto 0.2em; border-radius: 12px; border: 1.5px solid {{{border color|#1e3a8a}}}; border-left:10px solid {{{border color|#1e3a8a}}};"
| style="padding-left:15px; width:{{{image_width|40px}}}" | <div style="width:{{{image_width|40px}}}">[[Fayil:{{{image|Information icon4.svg}}}|{{{image_width|40px}}}|link=]]</div>
| style="padding-left:15px" | {{{text|}}}
|}
{{clear}}<noinclude>
{{Documentation}}
</noinclude>
68kv5rrao5vmsyh2w8if0iwcknu62rc
Tempilet:Cite web
10
923
9021
2016-12-05T05:36:52Z
en>Anthony Appleyard
0
Protected "[[Template:Cite web]]": restore old protection ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9021
wikitext
text/x-wiki
<includeonly>{{#invoke:citation/CS1|citation
|CitationClass=web
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
rcgmbcxu7hvs583g1f3rzz4c4dkizda
9022
8254
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cite_web]]
8254
wikitext
text/x-wiki
<includeonly>{{#invoke:citation/CS1|citation
|CitationClass=web
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
rcgmbcxu7hvs583g1f3rzz4c4dkizda
Module:Citation/CS1
828
924
9001
2026-08-08T13:56:56Z
en>Trappist the monk
0
synch from sandbox;
9001
Scribunto
text/plain
require ('strict');
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
each of these counts against the Lua upvalue limit
]]
local validation; -- functions in Module:Citation/CS1/Date_validation
local utilities; -- functions in Module:Citation/CS1/Utilities
local z = {}; -- table of tables in Module:Citation/CS1/Utilities
local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers
local metadata; -- functions in Module:Citation/CS1/COinS
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
--[[------------------< P A G E S C O P E V A R I A B L E S >---------------
declare variables here that have page-wide scope that are not brought in from
other modules; that are created here and used here
]]
local added_deprecated_cat; -- boolean flag so that the category is added only once
local added_vanc_errs; -- boolean flag so we only emit one Vancouver error / category
local added_generic_name_errs; -- boolean flag so we only emit one generic name error / category and stop testing names once an error is encountered
local added_numeric_name_errs; -- boolean flag so we only emit one numeric name error / category and stop testing names once an error is encountered
local added_numeric_name_maint; -- boolean flag so we only emit one numeric name maint category and stop testing names once a category has been emitted
local is_preview_mode; -- true when article is in preview mode; false when using 'Preview page with this template' (previewing the module)
local is_sandbox; -- true when using sandbox modules to render citation
local url_was_archive_today; -- boolean flag set to true when has_archive_today_url() has unset |url= because it held a deprecated archive.today url
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------
Locates and returns the first set value in a table of values where the order established in the table,
left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set.
This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs
version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate
the for-loop before it reached the actual end of the list.
]]
local function first_set (list, count)
local i = 1;
while i <= count do -- loop through all items in list
if utilities.is_set( list[i] ) then
return list[i]; -- return the first set list member
end
i = i + 1; -- point to next
end
end
--[[--------------------------< A D D _ V A N C _ E R R O R >----------------------------------------------------
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist.
To prevent duplication, added_vanc_errs is nil until an error message is emitted.
added_vanc_errs is a Boolean declared in page scope variables above
]]
local function add_vanc_error (source, position)
if added_vanc_errs then return end
added_vanc_errs = true; -- note that we've added this category
utilities.set_message ('err_vancouver', {source, position});
end
--[[--------------------------< I S _ S C H E M E >------------------------------------------------------------
does this thing that purports to be a URI scheme seem to be a valid scheme? The scheme is checked to see if it
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:
Scheme names consist of a sequence of characters beginning with a
letter and followed by any combination of letters, digits, plus
("+"), period ("."), or hyphen ("-").
returns true if it does, else false
]]
local function is_scheme (scheme)
return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern
end
--[=[-------------------------< I S _ D O M A I N _ N A M E >--------------------------------------------------
Does this thing that purports to be a domain name seem to be a valid domain name?
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5
BNF defined here: https://tools.ietf.org/html/rfc4234
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;
see also [[Single-letter second-level domain]]
list of TLDs: https://www.iana.org/domains/root/db
RFC 952 (modified by RFC 1123) requires the first and last character of a hostname to be a letter or a digit
(see http://tools.ietf.org/html/rfc952 §GRAMMATICAL HOST TABLE SPECIFICATION §§B. Lexical grammar <name>; see
http://tools.ietf.org/html/rfc1123#section-2). Between the first and last characters the name may use letters,
digits, and the hyphen.
Also allowed are IPv4 addresses. IPv6 not supported
domain is expected to be stripped of any path so that the last character in the last character of the TLD. tld
is two or more alpha characters. Any preceding '//' (from splitting a URL with a scheme) will be stripped
here. Perhaps not necessary but retained in case it is necessary for IPv4 dot decimal.
There are several tests:
the first character of the whole domain name including subdomains must be a letter or a digit
internationalized domain name (ASCII characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the TLD) see https://tools.ietf.org/html/rfc3490
single-letter/digit second-level domains in the .org, .cash, and .today TLDs
q, x, and z SL domains in the .com TLD
i and q SL domains in the .net TLD
single-letter SL domains in the ccTLDs (where the ccTLD is two letters)
two-character SL domains in gTLDs (where the gTLD is two or more letters)
three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)
IPv4 dot-decimal address format; TLD not allowed
returns true if domain appears to be a proper name and TLD or IPv4 address, else false
]=]
local function is_domain_name (domain)
if not domain then
return false; -- if not set, abandon
end
domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once
local sl_domain = domain:match ('[^%.]+') or domain; -- test the second level domain name
if not (sl_domain:match ('^%w') and sl_domain:match ('%w$') and -- first and last characters must be letter or digit
sl_domain:match ('^[%w%-]+$')) then -- all other characters must be letters, digits, or hyphen-minus
return false;
end
if domain:match ('^%a+:') then -- hack to detect things that look like s:Page:Title where Page: is namespace at Wikisource
return false;
end
local patterns = { -- patterns that look like URLs
'%f[%w][%w][%w%-]+[%w]%.%a%a+$', -- three or more character hostname.hostname or hostname.tld
'%f[%w][%w][%w%-]+[%w]%.xn%-%-[%w]+$', -- internationalized domain name with ACE prefix
'%f[%a][qxz]%.com$', -- assigned one character .com hostname (x.com times out 2015-12-10)
'%f[%a][iq]%.net$', -- assigned one character .net hostname (q.net registered but not active 2015-12-10)
'%f[%w][%w]%.%a%a$', -- one character hostname and ccTLD (2 chars)
'%f[%w][%w][%w]%.%a%a+$', -- two character hostname and TLD
'^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?', -- IPv4 address
'[%a%d]+%:?' -- IPv6 address
}
for _, pattern in ipairs (patterns) do -- loop through the patterns list
if domain:match (pattern) then
return true; -- if a match then we think that this thing that purports to be a URL is a URL
end
end
for _, d in ipairs (cfg.single_letter_2nd_lvl_domains_t) do -- look for single letter second level domain names for these top level domains
if domain:match ('%f[%w][%w]%.' .. d) then
return true
end
end
return false; -- no matches, we don't know what this thing is
end
--[[--------------------------< I S _ U R L >------------------------------------------------------------------
returns true if the scheme and domain parts of a URL appear to be a valid URL; else false.
This function is the last step in the validation process. This function is separate because there are cases that
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external
wikilinks.
]]
local function is_url (scheme, domain)
if utilities.is_set (scheme) then -- if scheme is set check it and domain
return is_scheme (scheme) and is_domain_name (domain);
else
return is_domain_name (domain); -- scheme not set when URL is protocol-relative
end
end
--[[--------------------------< S P L I T _ U R L >------------------------------------------------------------
Split a URL into a scheme, authority indicator, and domain.
First remove Fully Qualified Domain Name terminator (a dot following TLD) (if any) and any path(/), query(?) or fragment(#).
If protocol-relative URL, return nil scheme and domain else return nil for both scheme and domain.
When not protocol-relative, get scheme, authority indicator, and domain. If there is an authority indicator (one
or more '/' characters immediately following the scheme's colon), make sure that there are only 2.
Any URL that does not have news: scheme must have authority indicator (//). TODO: are there other common schemes
like news: that don't use authority indicator?
Strip off any port and path;
]]
local function split_url (url_str)
local scheme, authority, domain;
url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//')
if url_str:match ('^//%S*') then -- if there is what appears to be a protocol-relative URL
domain = url_str:match ('^//(%S*)')
elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name
scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions
if utilities.is_set (authority) then
authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing;
if utilities.is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then
return scheme; -- return scheme only making domain nil which will cause an error message
end
else
if not scheme:match ('^news:') then -- except for news:..., MediaWiki won't link URLs that do not have authority indicator; TODO: a better way to do this test?
return scheme; -- return scheme only making domain nil which will cause an error message
end
end
domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present
end
return scheme, domain;
end
--[[--------------------------< L I N K _ P A R A M _ O K >---------------------------------------------------
checks the content of |title-link=, |series-link=, |author-link=, etc. for properly formatted content: no wikilinks, no URLs
Link parameters are to hold the title of a Wikipedia article, so none of the WP:TITLESPECIALCHARACTERS are allowed:
# < > [ ] | { } _
except the underscore which is used as a space in wiki URLs and # which is used for section links
returns false when the value contains any of these characters.
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid URL (the
|<param>-link= parameter is ok); else false when value appears to be a valid URL (the |<param>-link= parameter is NOT ok).
]]
local function link_param_ok (value)
local scheme, domain;
if value:find ('[<>%[%]|{}]') then -- if any prohibited characters
return false;
end
scheme, domain = split_url (value); -- get scheme or nil and domain or nil from URL;
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid URL
end
--[[--------------------------< L I N K _ T I T L E _ O K >---------------------------------------------------
Use link_param_ok() to validate |<param>-link= value and its matching |<title>= value.
|<title>= may be wiki-linked but not when |<param>-link= has a value. This function emits an error message when
that condition exists
check <link> for inter-language interwiki-link prefix. prefix must be a MediaWiki-recognized language
code and must begin with a colon.
]]
local function link_title_ok (link, lorig, title, torig)
local orig;
if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value
if not link_param_ok (link) then -- check |<param>-link= markup
orig = lorig; -- identify the failing link parameter
elseif title:find ('%[%[') then -- check |title= for wikilink markup
orig = torig; -- identify the failing |title= parameter
elseif link:match ('^%a+:') then -- if the link is what looks like an interwiki
local prefix = link:match ('^(%a+):'):lower(); -- get the interwiki prefix
if cfg.inter_wiki_map[prefix] then -- if prefix is in the map, must have preceding colon
orig = lorig; -- flag as error
end
end
end
if utilities.is_set (orig) then
link = ''; -- unset
utilities.set_message ('err_bad_paramlink', orig); -- URL or wikilink in |title= with |title-link=;
end
return link; -- link if ok, empty string else
end
--[[--------------------------< C H E C K _ U R L >------------------------------------------------------------
Determines whether a URL string appears to be valid.
First we test for space characters. If any are found, return false. Then split the URL into scheme and domain
portions, or for protocol-relative (//example.com) URLs, just the domain. Use is_url() to validate the two
portions of the URL. If both are valid, or for protocol-relative if domain is valid, return true, else false.
Because it is different from a standard URL, and because this module used external_link() to make external links
that work for standard and news: links, we validate newsgroup names here. The specification for a newsgroup name
is at https://tools.ietf.org/html/rfc5536#section-3.1.4
]]
local function check_url( url_str )
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper URL
return false;
end
local scheme, domain;
scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from URL;
if 'news:' == scheme then -- special case for newsgroups
return domain:match('^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$');
end
return is_url (scheme, domain); -- return true if value appears to be a valid URL
end
--[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
non-space characters following the opening bracket appear to be a URL. The test will also find external wikilinks
that use protocol-relative URLs. Also finds bare URLs.
The frontier pattern prevents a match on interwiki-links which are similar to scheme:path URLs. The tests that
find bracketed URLs are required because the parameters that call this test (currently |title=, |chapter=, |work=,
and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]]
is possible as might be [[en://Hus]].
]=]
local function is_parameter_ext_wikilink (value)
local scheme, domain;
if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext. wikilink with scheme and domain: [xxxx://yyyyy.zzz]
scheme, domain = split_url (value:match ('%f[%[]%[(%a%S*:%S+).*%]'));
elseif value:match ('%f[%[]%[//%S+.*%]') then -- if protocol-relative ext. wikilink: [//yyyyy.zzz]
scheme, domain = split_url (value:match ('%f[%[]%[(//%S+).*%]'));
elseif value:match ('%a%S*:%S+') then -- if bare URL with scheme; may have leading or trailing plain text
scheme, domain = split_url (value:match ('(%a%S*:%S+)'));
elseif value:match ('^//%S+') or value:match ('%s//%S+') then -- if protocol-relative bare URL: //yyyyy.zzz; authority indicator (//) must be be preceded nothing or by whitespace
scheme, domain = split_url (value:match ('(//%S+)')); -- what is left should be the domain
else
return false; -- didn't find anything that is obviously a URL
end
return is_url (scheme, domain); -- return true if value appears to be a valid URL
end
--[[--------------------------< I S _ A R C H I V E _ T O D A Y _ U R L >--------------------------------------
archive.today (and .ph, .is, .md, .li, .fo, .vn) are deprecated. See Wikipedia:Requests_for_comment/Archive.is_RFC_5
(Special:Permalink/1339352976)
<val> is a string that may or may not be a url
]]
local function is_archive_today_url (val)
if is_parameter_ext_wikilink (val) then -- is <val> a url?
local tld = val:match ('archive%.(%l+)/'); -- get the tld; real archive.today urls have a '/' after the tld
return tld and cfg.archive_today_tlds_t[tld]; -- return true if <tld> is one of the archive.today tlds; nil else
end
end
--[[--------------------------< H A S _ A R C H I V E _ T O D A Y _ U R L >------------------------------------
blank any parameter that holds one of the archive.today tlds (.today, .ph, .is, .md, .li, .fo, .vn) and also
blank parameters that are dependent on the offending parameter.
input <cite_args_t> is a table of all of this template's parameters This function modifies <cite_args_t>
when |url= or its alias |URL= hold an archive.today url, this function sets the flag <url_was_archive_today>
which is used later to suppress the missing url error message from {{citation}} when it has |website=<summat>
or from the templates {{cite web}}, {{cite podcast}}, {{cite mailing list}} which all require a url.
returns nothing
]]
local function has_archive_today_url (cite_args_t)
local unset_params_t = {}; -- to hold a sequence of parameters to unset from cite_args_t
for p, v in pairs (cite_args_t) do -- look at each parameter in the template
if is_archive_today_url (v:lower()) then -- if it has a parameter with an archive.today url
table.insert (unset_params_t, p); -- add the url-holding parameter name to our list of parameters to unset (may or may not be a legitimate url parameter)
if 'url' == p:lower() then -- if this parameter is |url= or |URL=
url_was_archive_today = true; -- set a flag so that cite web / podcast / mailinglist don't emit a missing url error message
end
if p:match ('archive%-?url') and ('usurped' == cite_args_t['url-status'] or 'unfit' == cite_args_t['url-status']) then -- if |archive-url=archive.today and |url-status=unfit/usurped
url_was_archive_today = true; -- set a flag so that cite web / podcast / mailinglist don't emit a missing url error message
table.insert (unset_params_t, 'url'); -- add the url parameter name to our list of parameters to unset (may or may not be a legitimate url parameter)
table.insert (unset_params_t, 'URL'); -- this one because both are possible
end
if cfg.dependencies_t[p] then -- if this url-holding parameter (<p>) has dependencies
for _, dependent in ipairs (cfg.dependencies_t[p]) do -- loop through the url-holding parameter's dependency sequence
table.insert (unset_params_t, dependent); -- add dependent parameter to the list to be unset
end
end
end
end
if 0 < #unset_params_t then -- when there are parameters to unset
if not is_preview_mode then -- when in preview mode do not suppress any parameters
for _, unset_param in ipairs (unset_params_t) do -- loop through the sequence
cite_args_t[unset_param] = nil; -- and unset the url-holding parameter and its dependent parameters to avoid parameter-requires-other-parameter errors
end
end
utilities.set_message ('maint_deprecated_archive'); -- add a maintenance message
end
end
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message.
]]
local function check_for_url (parameter_list, error_list)
for k, v in pairs (parameter_list) do -- for each parameter in the list
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message
table.insert (error_list, utilities.wrap_style ('parameter', k));
end
end
end
--[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------
Escape sequences for content that will be used for URL descriptions
]]
local function safe_for_url( str )
if str:match( "%[%[.-%]%]" ) ~= nil then
utilities.set_message ('err_wikilink_in_url', {});
end
return str:gsub( '[%[%]\n]', {
['['] = '[',
[']'] = ']',
['\n'] = ' ' } );
end
--[[--------------------------< E X T E R N A L _ L I N K >----------------------------------------------------
Format an external link with error checking
]]
local function external_link (URL, label, source, access)
local domain;
local path;
local base_url;
if not utilities.is_set (label) then
label = URL;
if utilities.is_set (source) then
utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)});
else
error (cfg.messages["bare_url_no_origin"]); -- programmer error; valid parameter name does not have matching meta-parameter
end
end
if not check_url (URL) then
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)});
end
domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path
if path then -- if there is a path portion
path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); -- replace '[' and ']' with their percent-encoded values
URL = table.concat ({domain, path}); -- and reassemble
end
base_url = table.concat ({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL
if utilities.is_set (access) then -- access level (subscription, registration, limited)
base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon
end
return base_url;
end
--[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the
offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated
parameters in the citation.
added_deprecated_cat is a Boolean declared in page scope variables above
]]
local function deprecated_parameter(name)
if not added_deprecated_cat then
added_deprecated_cat = true; -- note that we've added this category
utilities.set_message ('err_deprecated_params', {name}); -- add error message
end
end
--[=[-------------------------< K E R N _ Q U O T E S >--------------------------------------------------------
Apply kerning to open the space between the quote mark provided by the module and a leading or trailing quote
mark contained in a |title= or |chapter= parameter's value.
This function will positive kern either single or double quotes:
"'Unkerned title with leading and trailing single quote marks'"
" 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example)
Double single quotes (italic or bold wiki-markup) are not kerned.
Replaces Unicode quote marks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter
quote marks regardless of the need for kerning. Unicode quote marks are not replaced in simple [[D]] wikilinks.
Call this function for chapter titles, for website titles, etc.; not for book titles.
]=]
local function kern_quotes (str)
local wl_type, label, link;
wl_type, label, link = utilities.is_wikilink (str); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]
if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks
if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks
str = utilities.substitute (cfg.presentation['kern-left'], str);
str = utilities.substitute (cfg.presentation['kern-right'], str);
elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks
str = utilities.substitute (cfg.presentation['kern-left'], str);
elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks
str = utilities.substitute (cfg.presentation['kern-right'], str);
end
else -- plain text or [[L|D]]; text in label variable
label = mw.ustring.gsub (label, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark)
label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark)
local cap = mw.ustring.match (label, "^([\"\'][^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup)
if utilities.is_set (cap) then
label = utilities.substitute (cfg.presentation['kern-left'], cap);
end
cap = mw.ustring.match (label, "^(.+[^\'][\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup)
if utilities.is_set (cap) then
label = utilities.substitute (cfg.presentation['kern-right'], cap);
end
if 2 == wl_type then
str = utilities.make_wikilink (link, label); -- reassemble the wikilink
else
str = label;
end
end
return str;
end
--[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >----------------------------------------
|script-title= holds title parameters that are not written in Latin-based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should
not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped
in italic markup.
Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate RTL languages from the English left to right.
|script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO 639-1 language code and a colon:
|script-title=ja:*** *** (where * represents a Japanese character)
Spaces between the two-character code and the colon and the colon and the first script character are allowed:
|script-title=ja : *** ***
|script-title=ja: *** ***
|script-title=ja :*** ***
Spaces preceding the prefix are allowed: |script-title = ja:*** ***
The prefix is checked for validity. If it is a valid ISO 639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can
know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute
is not added. At this time there is no error message for this condition.
Supports |script-title=, |script-chapter=, |script-<periodical>=
]]
local function format_script_value (script_value, script_param)
local lang=''; -- initialize to empty string
local name;
if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix
lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script
if not utilities.is_set (lang) then
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing title part']}); -- prefix without 'title'; add error message
return ''; -- script_value was just the prefix so return empty string
end
-- if we get this far we have prefix and script
name = cfg.lang_tag_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize
if utilities.is_set (name) then -- is prefix a proper ISO 639-1 language code?
script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script
-- is prefix one of these language codes?
if utilities.in_array (lang, cfg.script_lang_codes) then
utilities.add_prop_cat ('script', {name, lang})
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['unknown language code']}); -- unknown script-language; add error message
end
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['invalid language code']}); -- invalid language code; add error message
lang = ''; -- invalid so set lang to empty string
end
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing prefix']}); -- no language code prefix; add error message
end
script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL
return script_value;
end
--[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script
value has been wrapped in <bdi> tags.
]]
local function script_concatenate (title, script, script_param)
if utilities.is_set (script) then
script = format_script_value (script, script_param); -- <bdi> tags, lang attribute, categorization, etc.; returns empty string on error
if utilities.is_set (script) then
title = title .. ' ' .. script; -- concatenate title and script title
end
end
return title;
end
--[[--------------------------< W R A P _ M S G >--------------------------------------------------------------
Applies additional message text to various parameter values. Supplied string is wrapped using a message_list
configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken
from citation_config.messages - the reason this function is similar to but separate from wrap_style().
]]
local function wrap_msg (key, str, lower)
if not utilities.is_set ( str ) then
return "";
end
if true == lower then
local msg;
msg = cfg.messages[key]:lower(); -- set the message to lower case before
return utilities.substitute ( msg, str ); -- including template text
else
return utilities.substitute ( cfg.messages[key], str );
end
end
--[[----------------< W I K I S O U R C E _ U R L _ M A K E >-------------------
Makes a Wikisource URL from Wikisource interwiki-link. Returns the URL and appropriate
label; nil else.
str is the value assigned to |chapter= (or aliases) or |title= or |title-link=
]]
local function wikisource_url_make (str)
local wl_type, D, L;
local ws_url, ws_label;
local wikisource_prefix = table.concat ({'https://', cfg.this_wiki_code, '.wikisource.org/wiki/'});
wl_type, D, L = utilities.is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink)
if 0 == wl_type then -- not a wikilink; might be from |title-link=
str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title
});
ws_label = str; -- label for the URL
end
elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]]
str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title
});
ws_label = str; -- label for the URL
end
elseif 2 == wl_type then -- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]])
str = L:match ('^[Ww]ikisource:(.+)') or L:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_label = D; -- get ws article name from display portion of interwiki link
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title without namespace from link portion of wikilink
});
end
end
if ws_url then
ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable URL
ws_url = ws_url:gsub ('%%23', '#'); -- undo percent-encoding of fragment marker
end
return ws_url, ws_label, L or D; -- return proper URL or nil and a label or nil
end
--[[----------------< F O R M A T _ P E R I O D I C A L >-----------------------
Format the three periodical parameters: |script-<periodical>=, |<periodical>=,
and |trans-<periodical>= into a single Periodical meta-parameter.
]]
local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical)
if not utilities.is_set (periodical) then
periodical = ''; -- to be safe for concatenation
else
periodical = utilities.wrap_style ('italic-title', periodical); -- style
end
periodical = script_concatenate (periodical, script_periodical, script_periodical_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
if utilities.is_set (trans_periodical) then
trans_periodical = utilities.wrap_style ('trans-italic-title', trans_periodical);
if utilities.is_set (periodical) then
periodical = periodical .. ' ' .. trans_periodical;
else -- here when trans-periodical without periodical or script-periodical
periodical = trans_periodical;
utilities.set_message ('err_trans_missing_title', {'periodical'});
end
end
return periodical;
end
--[[------------------< F O R M A T _ C H A P T E R _ T I T L E >---------------
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=,
and |chapter-url= into a single chapter meta- parameter (chapter_url_source used
for error messages).
]]
local function format_chapter_title (script_chapter, script_chapter_source, chapter, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access)
local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link
if ws_url then
ws_label = ws_label:gsub ('_', ' '); -- replace underscore separators with space characters
chapter = ws_label;
end
if not utilities.is_set (chapter) then
chapter = ''; -- to be safe for concatenation
else
if false == no_quotes then
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from module provided quote marks
chapter = utilities.wrap_style ('quoted-title', chapter);
end
end
chapter = script_concatenate (chapter, script_chapter, script_chapter_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
if utilities.is_set (chapter_url) then
chapter = external_link (chapter_url, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate
elseif ws_url then
chapter = external_link (ws_url, chapter .. ' ', 'ws link in chapter'); -- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this?
chapter = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, chapter});
end
if utilities.is_set (trans_chapter) then
trans_chapter = utilities.wrap_style ('trans-quoted-title', trans_chapter);
if utilities.is_set (chapter) then
chapter = chapter .. ' ' .. trans_chapter;
else -- here when trans_chapter without chapter or script-chapter
chapter = trans_chapter;
utilities.set_message ('err_trans_missing_title', {trans_chapter_source:match ('trans%-?(.+)')}); -- when no chapter, get matching name from trans-<param>
end
end
return chapter;
end
--[[----------------< H A S _ I N V I S I B L E _ C H A R S >-------------------
This function searches a parameter's value for non-printable or invisible characters.
The search stops at the first match.
This function will detect the visible replacement character when it is part of the Wikisource.
Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers
(gallery, math, pre, ref) and identifies them with a slightly different error message.
See also coins_cleanup().
Output of this function is an error message that identifies the character or the
Unicode group, or the stripmarker that was detected along with its position (or,
for multi-byte characters, the position of its first byte) in the parameter value.
]]
local function has_invisible_chars (param, v)
local position; -- position of invisible char or starting position of stripmarker
local capture; -- used by stripmarker detection to hold name of the stripmarker
local stripmarker; -- boolean set true when a stripmarker is found
capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true
if capture == v then -- if same there are no Unicode characters
return;
end
for _, invisible_char in ipairs (cfg.invisible_chars) do
local char_name = invisible_char[1]; -- the character or group name
local pattern = invisible_char[2]; -- the pattern used to find it
position, _, capture = mw.ustring.find (v, pattern); -- see if the parameter value contains characters that match the pattern
if position and (cfg.invisible_defs.zwj == capture) then -- if we found a zero-width joiner character
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts
position = nil; -- unset position
elseif cfg.emoji_t[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}?
position = nil; -- unset position
end
end
if position then
if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition)
('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters
stripmarker = true; -- set a flag
elseif true == stripmarker and cfg.invisible_defs.del == capture then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
position = nil; -- unset; for now, ignore linter warning
else
local err_msg;
if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then
err_msg = utilities.substitute (cfg.messages.invisible_1, {capture, char_name}); -- <capture> here is stripmarker name
else
err_msg = utilities.substitute (cfg.messages.invisible_2, char_name);
end
utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}); -- add error message
return; -- and done with this parameter
end
end
end
end
--[[-------------------< A R G U M E N T _ W R A P P E R >----------------------
Argument wrapper. This function provides support for argument mapping defined
in the configuration file so that multiple names can be transparently aliased to
single internal variable.
]]
local function argument_wrapper ( args )
local origin = {};
return setmetatable({
ORIGIN = function ( self, k )
local dummy = self[k]; -- force the variable to be loaded; for now, ignore linter warning
return origin[k];
end
},
{
__index = function ( tbl, k )
if origin[k] ~= nil then
return nil;
end
local v;
local list = cfg.aliases[k];
if type( list ) == 'table' then
v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' );
if origin[k] == nil then
origin[k] = ''; -- Empty string, not nil
end
elseif list ~= nil then
v, origin[k] = args[list], list;
else
-- maybe let through instead of raising an error?
-- v, origin[k] = args[k], k;
error( cfg.messages['unknown_argument_map'] .. ': ' .. k);
end
-- Empty strings, not nil;
if v == nil then
v = '';
origin[k] = '';
end
-- tbl = rawset( tbl, k, v );
rawset( tbl, k, v );
return v;
end,
});
end
--[[--------------------------< N O W R A P _ D A T E >-------------------------
When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.
When date is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span:
<span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY
DOES NOT yet support MMMM YYYY or any of the date ranges.
]]
local function nowrap_date (date)
local cap;
local cap2;
if date:match("^%d%d%d%d%-%d%d%-%d%d$") then
date = utilities.substitute (cfg.presentation['nowrap1'], date);
elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then
cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$");
date = utilities.substitute (cfg.presentation['nowrap2'], {cap, cap2});
end
return date;
end
--[[--------------------------< S E T _ T I T L E T Y P E >---------------------
This function sets default title types (equivalent to the citation including
|type=<default value>) for those templates that have defaults. Also handles the
special case where it is desirable to omit the title type from the rendered citation
(|type=none).
]]
local function set_titletype (cite_class, title_type)
if utilities.is_set (title_type) then
if 'none' == cfg.keywords_xlate[title_type] then
title_type = ''; -- if |type=none then type parameter not displayed
end
return title_type; -- if |type= has been set to any other value use that value
end
return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation
end
--[[--------------------------< S A F E _ J O I N >-----------------------------
Joins a sequence of strings together while checking for duplicate separation characters.
]]
local function safe_join( tbl, duplicate_char )
local f = {}; -- create a function table appropriate to type of 'duplicate character'
if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions
f.gsub = string.gsub
f.match = string.match
f.sub = string.sub
else -- for multi-byte characters use the ustring library functions
f.gsub = mw.ustring.gsub
f.match = mw.ustring.match
f.sub = mw.ustring.sub
end
local str = ''; -- the output string
for _, value in ipairs( tbl ) do
if value == nil then value = ''; end
if str == '' then -- if output string is empty
str = value; -- assign value to it (first time through the loop)
elseif value ~= '' then
local comp; -- what does 'comp' mean?
if value:sub(1, 1) == '<' then -- special case of values enclosed in spans and other markup.
comp = value:gsub( "%b<>", "" ); -- remove HTML markup (<span>string</span> -> string)
else
comp = value;
end
-- typically duplicate_char is sepc
if f.sub(comp, 1, 1) == duplicate_char then -- is first character same as duplicate_char? why test first character?
-- Because individual string segments often (always?) begin with terminal punct for the
-- preceding segment: 'First element' .. 'sepc next element' .. etc.?
local trim = false;
local end_chr = f.sub(str, -1, -1); -- get the last character of the output string
-- str = str .. "<HERE(enchr=" .. end_chr .. ")" -- debug stuff?
if end_chr == duplicate_char then -- if same as separator
str = f.sub(str, 1, -2); -- remove it
elseif end_chr == "'" then -- if it might be wiki-markup
if f.sub(str, -3, -1) == duplicate_char .. "''" then -- if last three chars of str are sepc''
str = f.sub(str, 1, -4) .. "''"; -- remove them and add back ''
elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]''
trim = true; -- why? why do this and next differently from previous?
elseif f.sub(str, -4, -1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]''
trim = true; -- same question
end
elseif end_chr == "]" then -- if it might be wiki-markup
if f.sub(str, -3, -1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink
trim = true;
elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link
trim = true;
elseif f.sub(str, -2, -1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link
trim = true;
elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title.
trim = true;
end
elseif end_chr == " " then -- if last char of output string is a space
if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space>
str = f.sub(str, 1, -3); -- remove them both
end
end
if trim then
if value ~= comp then -- value does not equal comp when value contains HTML markup
local dup2 = duplicate_char;
if f.match(dup2, "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it
value = f.gsub(value, "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows HTML markup
else
value = f.sub(value, 2, -1 ); -- remove duplicate_char when it is first character
end
end
end
str = str .. value; -- add it to the output string
end
end
return str;
end
--[[--------------------------< I S _ S U F F I X >-----------------------------
returns true if suffix is properly formed Jr, Sr, or ordinal in the range 1–9.
Puncutation not allowed.
]]
local function is_suffix (suffix)
if utilities.in_array (suffix, {'Jr', 'Sr', 'Jnr', 'Snr', '1st', '2nd', '3rd'}) or suffix:match ('^%dth$') then
return true;
end
return false;
end
--[[--------------------< I S _ G O O D _ V A N C _ N A M E >-------------------
For Vancouver style, author/editor names are supposed to be rendered in Latin
(read ASCII) characters. When a name uses characters that contain diacritical
marks, those characters are to be converted to the corresponding Latin
character. When a name is written using a non-Latin alphabet or logogram, that
name is to be transliterated into Latin characters. The module doesn't do this
so editors may/must.
This test allows |first= and |last= names to contain any of the letters defined
in the four Unicode Latin character sets
[http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A
[http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF
[http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F
[http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F
|lastn= also allowed to contain hyphens, spaces, and apostrophes.
(http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
|firstn= also allowed to contain hyphens, spaces, apostrophes, and periods
This original test:
if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$")
or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]+[2-6%a]*$") then
was written outside of the code editor and pasted here because the code editor
gets confused between character insertion point and cursor position. The test has
been rewritten to use decimal character escape sequence for the individual bytes
of the Unicode characters so that it is not necessary to use an external editor
to maintain this code.
\195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls)
\195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls)
\195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A & B)
\199\132-\201\143 – DŽ-ɏ (U+01C4-U+024F – Latin extended B)
]]
local function is_good_vanc_name (last, first, suffix, position)
if not suffix then
if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix
first = first:match ('(.-)[,%s]+'); -- get name/initials
suffix = first:match ('[,%s]+(.+)$'); -- get generational suffix
end
end
if utilities.is_set (suffix) then
if not is_suffix (suffix) then
add_vanc_error (cfg.err_msg_supl.suffix, position);
return false; -- not a name with an appropriate suffix
end
end
if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%']*$") or
nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%'%.]*$") then
add_vanc_error (cfg.err_msg_supl['non-Latin char'], position);
return false; -- not a string of Latin characters; Vancouver requires Romanization
end;
return true;
end
--[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------
Attempts to convert names to initials in support of |name-list-style=vanc.
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period.
See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/.
Vancouver style requires family rank designations (Jr, II, III, etc.) to be rendered
as Jr, 2nd, 3rd, etc. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/.
This code only accepts and understands generational suffix in the Vancouver format
because Roman numerals look like, and can be mistaken for, initials.
This function uses ustring functions because firstname initials may be any of the
Unicode Latin characters accepted by is_good_vanc_name ().
]]
local function reduce_to_initials (first, position)
if first:find (',', 1, true) then
return first; -- commas not allowed; abandon
end
local name, suffix = mw.ustring.match (first, "^(%u+) ([%dJS][%drndth]+)$");
if not name then -- if not initials and a suffix
name = mw.ustring.match (first, "^(%u+)$"); -- is it just initials?
end
if name then -- if first is initials with or without suffix
if 3 > mw.ustring.len (name) then -- if one or two initials
if suffix then -- if there is a suffix
if is_suffix (suffix) then -- is it legitimate?
return first; -- one or two initials and a valid suffix so nothing to do
else
add_vanc_error (cfg.err_msg_supl.suffix, position); -- one or two initials with invalid suffix so error message
return first; -- and return first unmolested
end
else
return first; -- one or two initials without suffix; nothing to do
end
end
end -- if here then name has 3 or more uppercase letters so treat them as a word
local initials_t = {}; -- table to hold initials
local i = 1; -- counter for number of initials
local names_t = mw.text.split (first, '[%s%-]+'); -- split into a sequence of names and possible suffix
while names_t[i] do -- loop through the sequence
if 1 < i and names_t[i]:match ('[%dJS][%drndth]+%.?$') then -- if not the first name, and looks like a suffix (may have trailing dot)
names_t[i] = names_t[i]:gsub ('%.', ''); -- remove terminal dot if present
if is_suffix (names_t[i]) then -- if a legitimate suffix
table.insert (initials_t, ' ' .. names_t[i]); -- add a separator space, insert at end of initials sequence
break; -- and done because suffix must fall at the end of a name
end -- no error message if not a suffix; possibly because of Romanization
end
if 3 > i then
table.insert (initials_t, mw.ustring.sub (names_t[i], 1, 1)); -- insert the initial at end of initials sequence
end
i = i + 1; -- bump the counter
end
return table.concat (initials_t); -- Vancouver format does not include spaces.
end
--[[--------------------------< I N T E R W I K I _ P R E F I X E N _ G E T >----------------------------------
extract interwiki prefixen from <value>. Returns two one or two values:
false – no prefixen
nil – prefix exists but not recognized
project prefix, language prefix – when value has either of:
:<project>:<language>:<article>
:<language>:<project>:<article>
project prefix, nil – when <value> has only a known single-letter prefix
nil, language prefix – when <value> has only a known language prefix
accepts single-letter project prefixen: 'd' (wikidata), 's' (wikisource), and 'w' (wikipedia) prefixes; at this
writing, the other single-letter prefixen (b (wikibook), c (commons), m (meta), n (wikinews), q (wikiquote), and
v (wikiversity)) are not supported.
]]
local function interwiki_prefixen_get (value, is_link)
if not value:find (':%l+:') then -- if no prefix
return false; -- abandon; boolean here to distinguish from nil fail returns later
end
local prefix_patterns_linked_t = { -- sequence of valid interwiki and inter project prefixen
'^%[%[:([dsw]):(%l%l+):', -- wikilinked; project and language prefixes
'^%[%[:(%l%l+):([dsw]):', -- wikilinked; language and project prefixes
'^%[%[:([dsw]):', -- wikilinked; project prefix
'^%[%[:(%l%l+):', -- wikilinked; language prefix
}
local prefix_patterns_unlinked_t = { -- sequence of valid interwiki and inter project prefixen
'^:([dsw]):(%l%l+):', -- project and language prefixes
'^:(%l%l+):([dsw]):', -- language and project prefixes
'^:([dsw]):', -- project prefix
'^:(%l%l+):', -- language prefix
}
local cap1, cap2;
for _, pattern in ipairs ((is_link and prefix_patterns_linked_t) or prefix_patterns_unlinked_t) do
cap1, cap2 = value:match (pattern);
if cap1 then
break; -- found a match so stop looking
end
end
if cap1 and cap2 then -- when both then :project:language: or :language:project: (both forms allowed)
if 1 == #cap1 then -- length == 1 then :project:language:
if cfg.inter_wiki_map[cap2] then -- is language prefix in the interwiki map?
return cap1, cap2; -- return interwiki project and interwiki language
end
else -- here when :language:project:
if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map?
return cap2, cap1; -- return interwiki project and interwiki language
end
end
return nil; -- unknown interwiki language
elseif not (cap1 or cap2) then -- both are nil?
return nil; -- we got something that looks like a project prefix but isn't; return fail
elseif 1 == #cap1 then -- here when one capture
return cap1, nil; -- length is 1 so return project, nil language
else -- here when one capture and its length it more than 1
if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map?
return nil, cap1; -- return nil project, language
end
end
end
--[[--------------------------< L I S T _ P E O P L E >--------------------------
Formats a list of people (authors, contributors, editors, interviewers, translators)
names in the list will be linked when
|<name>-link= has a value
|<name>-mask- does NOT have a value; masked names are presumed to have been
rendered previously so should have been linked there
when |<name>-mask=0, the associated name is not rendered
]]
local function list_people (control, people, etal)
local sep;
local namesep;
local format = control.format;
local maximum = control.maximum;
local name_list = {};
if 'vanc' == format then -- Vancouver-like name styling?
sep = cfg.presentation['sep_nl_vanc']; -- name-list separator between names is a comma
namesep = cfg.presentation['sep_name_vanc']; -- last/first separator is a space
else
sep = cfg.presentation['sep_nl']; -- name-list separator between names is a semicolon
namesep = cfg.presentation['sep_name']; -- last/first separator is <comma><space>
end
if sep:sub (-1, -1) ~= " " then sep = sep .. " " end
if utilities.is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for other names
for i, person in ipairs (people) do
if utilities.is_set (person.last) then
local mask = person.mask;
local one;
local sep_one = sep;
if utilities.is_set (maximum) and i > maximum then
etal = true;
break;
end
if mask then
local n = tonumber (mask); -- convert to a number if it can be converted; nil else
if n then
one = 0 ~= n and string.rep("—", n) or nil; -- make a string of (n > 0) mdashes, nil else, to replace name
person.link = nil; -- don't create link to name if name is replaces with mdash string or has been set nil
else
one = mask; -- replace name with mask text (must include name-list separator)
sep_one = " "; -- modify name-list separator
end
else
one = person.last; -- get surname
local first = person.first -- get given name
if utilities.is_set (first) then
if ("vanc" == format) then -- if Vancouver format
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
if not person.corporate and is_good_vanc_name (one, first, nil, i) then -- and name is all Latin characters; corporate authors not tested
first = reduce_to_initials (first, i); -- attempt to convert first name(s) to initials
end
end
one = one .. namesep .. first;
end
end
if utilities.is_set (person.link) then
one = utilities.make_wikilink (person.link, one); -- link author/editor
end
if one then -- if <one> has a value (name, mdash replacement, or mask text replacement)
local proj, tag = interwiki_prefixen_get (one, true); -- get the interwiki prefixen if present
if 'w' == proj and ('Wikipedia' == mw.site.namespaces.Project['name']) then
proj = nil; -- for stuff like :w:de:<article>, :w is unnecessary TODO: maint cat?
end
if proj then
local proj_name = ({['d'] = cfg.messages.wikidata, ['s'] = cfg.messages.wikisource, ['w'] = cfg.messages.wikipedia})[proj]; -- :w (wikipedia) for linking from a non-wikipedia project
if proj_name then
one = one .. utilities.wrap_style ('interproj', proj_name); -- add resized leading space, brackets, static text, language name
utilities.add_prop_cat ('interproj-linked-name', proj); -- categorize it; <proj> is sort key
tag = nil; -- unset; don't do both project and language
end
end
if tag == cfg.this_wiki_code then
tag = nil; -- stuff like :en:<article> at en.wiki is pointless TODO: maint cat?
end
if tag then
local lang = cfg.lang_tag_remap[tag] or cfg.mw_languages_by_tag_t[tag];
if lang then -- error messaging done in extract_names() where we know parameter names
one = one .. utilities.wrap_style ('interwiki', lang); -- add resized leading space, brackets, static text, language name
utilities.add_prop_cat ('interwiki-linked-name', tag); -- categorize it; <tag> is sort key
end
end
table.insert (name_list, one); -- add it to the list of names
table.insert (name_list, sep_one); -- add the proper name-list separator
end
end
end
local count = #name_list / 2; -- (number of names + number of separators) divided by 2
if 0 < count then
if 1 < count and not etal then
if 'amp' == format then
name_list[#name_list-2] = " & "; -- replace last separator with ampersand text
elseif 'and' == format then
if 2 == count then
name_list[#name_list-2] = cfg.presentation.sep_nl_and; -- replace last separator with 'and' text
else
name_list[#name_list-2] = cfg.presentation.sep_nl_end; -- replace last separator with '(sep) and' text
end
end
end
name_list[#name_list] = nil; -- erase the last separator
end
local result = table.concat (name_list); -- construct list
if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
result = result .. sep .. cfg.messages['et al']; -- we've got a last-first list and etal so add et al.
end
return result, count; -- return name-list string and count of number of names (count used for editor names only)
end
--[[--------------------< M A K E _ C I T E R E F _ I D >-----------------------
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise
returns an empty string.
namelist is one of the contributor-, author-, or editor-name lists chosen in that
order. year is Year or anchor_year.
]]
local function make_citeref_id (namelist, year)
local names={}; -- a table for the one to four names and year
for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names
names[i] = v.last
if i == 4 then break end -- if four then done
end
table.insert (names, year); -- add the year at the end
local id = table.concat(names); -- concatenate names and year for CITEREF id
if utilities.is_set (id) then -- if concatenation is not an empty string
return "CITEREF" .. id; -- add the CITEREF portion
else
return ''; -- return an empty string; no reason to include CITEREF id in this citation
end
end
--[[--------------------------< C I T E _ C L A S S _A T T R I B U T E _M A K E >------------------------------
construct <cite> tag class attribute for this citation.
<cite_class> – config.CitationClass from calling template
<mode> – value from |mode= parameter
]]
local function cite_class_attribute_make (cite_class, mode)
local class_t = {};
table.insert (class_t, 'citation'); -- required for blue highlight
if 'citation' ~= cite_class then
table.insert (class_t, cite_class); -- identify this template for user css
table.insert (class_t, utilities.is_set (mode) and mode or 'cs1'); -- identify the citation style for user css or javascript
else
table.insert (class_t, utilities.is_set (mode) and mode or 'cs2'); -- identify the citation style for user css or javascript
end
for _, prop_key in ipairs (z.prop_keys_t) do
table.insert (class_t, prop_key); -- identify various properties for user css or javascript
end
return table.concat (class_t, ' '); -- make a big string and done
end
--[[---------------------< N A M E _ H A S _ E T A L >--------------------------
Evaluates the content of name parameters (author, editor, etc.) for variations on
the theme of et al. If found, the et al. is removed, a flag is set to true and
the function returns the modified name and the flag.
This function never sets the flag to false but returns its previous state because
it may have been set by previous passes through this function or by the associated
|display-<names>=etal parameter
]]
local function name_has_etal (name, etal, nocat, param)
if utilities.is_set (name) then -- name can be nil in which case just return
local patterns = cfg.et_al_patterns; -- get patterns from configuration
for _, pattern in ipairs (patterns) do -- loop through all of the patterns
if name:match (pattern) then -- if this 'et al' pattern is found in name
name = name:gsub (pattern, ''); -- remove the offending text
etal = true; -- set flag (may have been set previously here or by |display-<names>=etal)
if not nocat then -- no categorization for |vauthors=
utilities.set_message ('err_etal', {param}); -- and set an error if not added
end
end
end
end
return name, etal;
end
--[[---------------------< N A M E _ I S _ N U M E R I C >----------------------
Add an error message and category when <name> parameter value does not contain letters.
Add a maintenance category when <name> parameter value has numeric characters mixed with characters that are
not numeric characters; could be letters and/or punctuation characters.
This function will only emit one error and one maint message for the current template. Does not emit both error
and maint messages/categories for the same parameter value.
returns nothing
]]
local function name_is_numeric (name, name_alias, list_name)
local patterns = {
'^%D+%d', -- <name> must have digits preceded by other characters
'^%D*%d+%D+', -- <name> must have digits followed by other characters
}
if not added_numeric_name_errs and mw.ustring.match (name, '^[%A]+$') then -- if we have not already set an error message and <name> does not have any alpha characters
utilities.set_message ('err_numeric_names', name_alias); -- add an error message
added_numeric_name_errs = true; -- set the flag so we emit only one error message
return; -- when here no point in further testing; abandon
end
if not added_numeric_name_maint then -- if we have already set a maint message
for _, pattern in ipairs (patterns) do -- spin through list of patterns
if mw.ustring.match (name, pattern) then -- digits preceded or followed by anything but digits; %D+ includes punctuation
utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template
added_numeric_name_maint = true; -- set the flag so we emit only one maint message
return; -- when here no point in further testing; abandon
end
end
end
end
--[[-----------------< N A M E _ H A S _ M U L T _ N A M E S >------------------
Evaluates the content of last/surname (authors etc.) parameters for multiple names.
Multiple names are indicated if there is more than one comma or any "unescaped"
semicolons. Escaped semicolons are ones used as part of selected HTML entities.
If the condition is met, the function adds the multiple name maintenance category.
Same test for first except that commas should not appear in given names (MOS:JR says
that the generational suffix does not take a separator character). Titles, degrees,
postnominals, affiliations, all normally comma separated don't belong in a citation.
<name> – name parameter value
<list_name> – AuthorList, EditorList, etc
<limit> – number of allowed commas; 1 (default) for surnames; 0 for given names
returns nothing
]]
local function name_has_mult_names (name, list_name, limit)
local _, commas, semicolons, nbsps;
limit = limit and limit or 1;
if utilities.is_set (name) then
_, commas = name:gsub (',', ''); -- count the number of commas
_, semicolons = name:gsub (';', ''); -- count the number of semicolons
-- nbsps probably should be its own separate count rather than merged in
-- some way with semicolons because Lua patterns do not support the
-- grouping operator that regex does, which means there is no way to add
-- more entities to escape except by adding more counts with the new
-- entities
_, nbsps = name:gsub (' ',''); -- count nbsps
-- There is exactly 1 semicolon per entity, so subtract nbsps
-- from semicolons to 'escape' them. If additional entities are added,
-- they also can be subtracted.
if limit < commas or 0 < (semicolons - nbsps) then
utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message
end
end
end
--[=[-------------------------< I S _ G E N E R I C >----------------------------------------------------------
Compares values assigned to various parameters according to the string provided as <item> in the function call.
<item> can have on of two values:
'generic_names' – for name-holding parameters: |last=, |first=, |editor-last=, etc
'generic_titles' – for |title=
There are two types of generic tests. The 'accept' tests look for a pattern that should not be rejected by the
'reject' test. For example,
|author=[[John Smith (author)|Smith, John]]
would be rejected by the 'author' reject test. But piped wikilinks with 'author' disambiguation should not be
rejected so the 'accept' test prevents that from happening. Accept tests are always performed before reject
tests.
Each of the 'accept' and 'reject' sequence tables hold tables for en.wiki (['en']) and local.wiki (['local'])
that each can hold a test sequence table The sequence table holds, at index [1], a test pattern, and, at index
[2], a boolean control value. The control value tells string.find() or mw.ustring.find() to do plain-text search (true)
or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so
that we don't run out of processing time on very large articles.
Returns
true when a reject test finds the pattern or string
false when an accept test finds the pattern or string
nil else
]=]
local function is_generic (item, value)
local str_lower = { -- use string.lower() for en.wiki (['en']) and use mw.ustring.lower() or local.wiki (['local'])
['en'] = string.lower,
['local'] = mw.ustring.lower,
}
local str_find = { -- use string.find() for en.wiki (['en']) and use mw.ustring.find() or local.wiki (['local'])
['en'] = string.find,
['local'] = mw.ustring.find,
}
local function test (val, test_t, wiki) -- local function to do the testing; <wiki> selects lower() and find() functions
val = test_t[2] and str_lower[wiki](value) or val; -- when <test_t[2]> set to 'true', plaintext search using lowercase value
return str_find[wiki] (val, test_t[1], 1, test_t[2]); -- return nil when not found or matched
end
local test_types_t = {'accept', 'reject'}; -- test accept patterns first, then reject patterns
local wikis_t = {'en', 'local'}; -- do tests for each of these keys; en.wiki first, local.wiki second
for _, test_type in ipairs (test_types_t) do -- for each test type
for _, generic_value in pairs (cfg.special_case_translation[item][test_type]) do -- spin through the list of generic value fragments to accept or reject
for _, wiki in ipairs (wikis_t) do
if generic_value[wiki] then
if test (value, generic_value[wiki], wiki) then -- go do the test
return ('reject' == test_type); -- param value rejected, return true; false else
end
end
end
end
end
end
--[[--------------------------< N A M E _ I S _ G E N E R I C >------------------------------------------------
calls is_generic() to determine if <name> is a 'generic name' listed in cfg.generic_names; <name_alias> is the
parameter name used in error messaging
]]
local function name_is_generic (name, name_alias)
if not added_generic_name_errs and is_generic ('generic_names', name) then
utilities.set_message ('err_generic_name', name_alias); -- set an error message
added_generic_name_errs = true;
end
end
--[[--------------------------< N A M E _ C H E C K S >--------------------------------------------------------
This function calls various name checking functions used to validate the content of the various name-holding parameters.
]]
local function name_checks (last, first, list_name, last_alias, first_alias)
local accept_name;
if utilities.is_set (last) then
last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last>
if not accept_name then -- <last> not wrapped in accept-as-written markup
name_has_mult_names (last, list_name); -- check for multiple names in the parameter
name_is_numeric (last, last_alias, list_name); -- check for names that have no letters or are a mix of digits and other characters
name_is_generic (last, last_alias); -- check for names found in the generic names list
end
end
if utilities.is_set (first) then
first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first>
if not accept_name then -- <first> not wrapped in accept-as-written markup
name_has_mult_names (first, list_name, 0); -- check for multiple names in the parameter; 0 is number of allowed commas in a given name
name_is_numeric (first, first_alias, list_name); -- check for names that have no letters or are a mix of digits and other characters
name_is_generic (first, first_alias); -- check for names found in the generic names list
end
local wl_type, D = utilities.is_wikilink (first);
if 0 ~= wl_type then
first = D;
utilities.set_message ('err_bad_paramlink', first_alias);
end
end
return last, first; -- done
end
--[[----------------------< E X T R A C T _ N A M E S >-------------------------
Gets name list from the input arguments
Searches through args in sequential order to find |lastn= and |firstn= parameters
(or their aliases), and their matching link and mask parameters. Stops searching
when both |lastn= and |firstn= are not found in args after two sequential attempts:
found |last1=, |last2=, and |last3= but doesn't find |last4= and |last5= then the
search is done.
This function emits an error message when there is a |firstn= without a matching
|lastn=. When there are 'holes' in the list of last names, |last1= and |last3=
are present but |last2= is missing, an error message is emitted. |lastn= is not
required to have a matching |firstn=.
When an author or editor parameter contains some form of 'et al.', the 'et al.'
is stripped from the parameter and a flag (etal) returned that will cause list_people()
to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps
'et al.' out of the template's metadata. When this occurs, an error is emitted.
]]
local function extract_names(args, list_name)
local names = {}; -- table of names
local last; -- individual name components
local first;
local link;
local mask;
local i = 1; -- loop counter/indexer
local n = 1; -- output table indexer
local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors)
local etal = false; -- return value set to true when we find some form of et al. in an author parameter
local last_alias, first_alias, link_alias; -- selected parameter aliases used in error messaging
while true do
last, last_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'err_redundant_parameters', i ); -- search through args for name components beginning at 1
first, first_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'err_redundant_parameters', i );
link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i );
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i );
if last then -- error check |lastn= alias for unknown interwiki link prefix; done here because this is where we have the parameter name
local project, language = interwiki_prefixen_get (last, true); -- true because we expect interwiki links in |lastn= to be wikilinked
if nil == project and nil == language then -- when both are nil
utilities.set_message ('err_bad_paramlink', last_alias); -- not known, emit an error message -- TODO: err_bad_interwiki?
last = utilities.remove_wiki_link (last); -- remove wikilink markup; show display value only
end
end
if link then -- error check |linkn= alias for unknown interwiki link prefix
local project, language = interwiki_prefixen_get (link, false); -- false because wiki links in |author-linkn= is an error
if nil == project and nil == language then -- when both are nil
utilities.set_message ('err_bad_paramlink', link_alias); -- not known, emit an error message -- TODO: err_bad_interwiki?
link = nil; -- unset so we don't link
link_alias = nil;
end
end
last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al.
first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al.
last, first = name_checks (last, first, list_name, last_alias, first_alias); -- multiple names, extraneous annotation, etc. checks
if first and not last then -- if there is a firstn without a matching lastn
local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias
utilities.set_message ('err_first_missing_last', {
first_alias, -- param name of alias missing its mate
first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form
}); -- add this error message
elseif not first and not last then -- if both firstn and lastn aren't found, are we done?
count = count + 1; -- number of times we haven't found last and first
if 2 <= count then -- two missing names and we give up
break; -- normal exit or there is a two-name hole in the list; can't tell which
end
else -- we have last with or without a first
link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup
if first then
link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup
end
names[n] = {last = last, first = first, link = link, mask = mask, corporate = false}; -- add this name to our names list (corporate for |vauthors= only)
n = n + 1; -- point to next location in the names table
if 1 == count then -- if the previous name was missing
utilities.set_message ('err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}); -- add this error message
end
count = 0; -- reset the counter, we're looking for two consecutive missing names
end
i = i + 1; -- point to next args location
end
return names, etal; -- all done, return our list of names and the etal flag
end
--[[--------------------------< N A M E _ T A G _ G E T >------------------------------------------------------
attempt to decode |language=<lang_param> and return language name and matching tag; nil else.
This function looks for:
<lang_param> as a tag in cfg.lang_tag_remap{}
<lang_param> as a name in cfg.lang_name_remap{}
<lang_param> as a name in cfg.mw_languages_by_name_t
<lang_param> as a tag in cfg.mw_languages_by_tag_t
when those fail, presume that <lang_param> is an IETF-like tag that MediaWiki does not recognize. Strip all
script, region, variant, whatever subtags from <lang_param> to leave just a two or three character language tag
and look for the new <lang_param> in cfg.mw_languages_by_tag_t{}
on success, returns name (in properly capitalized form) and matching tag (in lowercase); on failure returns nil
]]
local function name_tag_get (lang_param)
local lang_param_lc = mw.ustring.lower (lang_param); -- use lowercase as an index into the various tables
local name;
local tag;
name = cfg.lang_tag_remap[lang_param_lc]; -- assume <lang_param_lc> is a tag; attempt to get remapped language name
if name then -- when <name>, <lang_param> is a tag for a remapped language name
if cfg.lang_name_remap[name:lower()][2] ~= lang_param_lc then
utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added
return name, cfg.lang_name_remap[name:lower()][2]; -- so return name and tag from lang_name_remap[name]; special case to xlate sr-ec and sr-el to sr-cyrl and sr-latn
end
return name, lang_param_lc; -- so return <name> from remap and <lang_param_lc>
end
tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags
name = cfg.lang_tag_remap[tag]; -- attempt to get remapped language name with language subtag only
if name then -- when <name>, <tag> is a tag for a remapped language name
return name, tag; -- so return <name> from remap and <tag>
end
if cfg.lang_name_remap[lang_param_lc] then -- not a remapped tag, assume <lang_param_lc> is a name; attempt to get remapped language tag
return cfg.lang_name_remap[lang_param_lc][1], cfg.lang_name_remap[lang_param_lc][2]; -- for this <lang_param_lc>, return a (possibly) new name and appropriate tag
end
name = cfg.mw_languages_by_tag_t[lang_param_lc]; -- assume that <lang_param_lc> is a tag; attempt to get its matching language name
if name then
return name, lang_param_lc; -- <lang_param_lc> is a tag so return it and <name>
end
tag = cfg.mw_languages_by_name_t[lang_param_lc]; -- assume that <lang_param_lc> is a language name; attempt to get its matching tag
if tag then
return cfg.mw_languages_by_tag_t[tag], tag; -- <lang_param_lc> is a name so return the name from the table and <tag>
end
tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- is <lang_param_lc> an IETF-like tag that MediaWiki doesn't recognize? <tag> gets the language subtag; nil else
if tag then
name = cfg.mw_languages_by_tag_t[tag]; -- attempt to get a language name using the shortened <tag>
if name then
return name, tag; -- <lang_param_lc> is an unrecognized IETF-like tag so return <name> and language subtag
end
end
end
--[[-------------------< L A N G U A G E _ P A R A M E T E R >------------------
Gets language name from a provided two- or three-character ISO 639 code. If a code
is recognized by MediaWiki, use the returned name; if not, then use the value that
was provided with the language parameter.
When |language= contains a recognized language (either code or name), the page is
assigned to the category for that code: Category:Norwegian-language sources (no).
For valid three-character code languages, the page is assigned to the single category
for '639-2' codes: Category:CS1 ISO 639-2 language sources.
Languages that are the same as the local wiki are not categorized. MediaWiki does
not recognize three-character equivalents of two-character codes: code 'ar' is
recognized but code 'ara' is not.
This function supports multiple languages in the form |language=nb, French, th
where the language names or codes are separated from each other by commas with
optional space characters.
]]
local function language_parameter (lang)
local tag; -- some form of IETF-like language tag; language subtag with optional region, sript, vatiant, etc subtags
local lang_subtag; -- ve populates |language= with mostly unecessary region subtags that MediaWiki does not recognize; this is the base language subtag
local name; -- the language name
local language_list = {}; -- table of language names to be rendered
local names_t = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list
for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag; for now, ignore linter warning
name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang>; <name> has proper capitalization; <tag> is lowercase
if utilities.is_set (tag) then
lang_subtag = tag:gsub ('^(%a%a%a?)%-.*', '%1'); -- for categorization, strip any IETF-like tags from language tag
if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language
if 2 == lang_subtag:len() then -- and is a two-character tag
utilities.add_prop_cat ('foreign-lang-source', {name, tag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization
else -- or is a recognized language (but has a three-character tag)
utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template?
end
elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled
utilities.add_prop_cat ('local-lang-source', {name, lang_subtag}); -- categorize it
end
else
name = lang; -- return whatever <lang> has so that we show something
utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added
end
table.insert (language_list, name);
end
name = utilities.make_sep_list (#language_list, language_list);
if (1 == #language_list) and (lang_subtag == cfg.this_wiki_code) then -- when only one language, find lang name in this wiki lang name; for |language=en-us, 'English' in 'American English'
return ''; -- if one language and that language is this wiki's return an empty string (no annotation)
end
return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)'
--[[ TODO: should only return blank or name rather than full list
so we can clean up the bunched parenthetical elements Language, Type, Format
]]
end
--[[-----------------------< S E T _ C S _ S T Y L E >--------------------------
Gets the default CS style configuration for the given mode.
Returns default separator and either postscript as passed in or the default.
In CS1, the default postscript and separator are '.'.
In CS2, the default postscript is the empty string and the default separator is ','.
]]
local function set_cs_style (postscript, mode)
if utilities.is_set(postscript) then
-- emit a maintenance message if user postscript is the default cs1 postscript
-- we catch the opposite case for cs2 in set_style
if mode == 'cs1' and postscript == cfg.presentation['ps_' .. mode] then
utilities.set_message ('maint_postscript');
end
else
postscript = cfg.presentation['ps_' .. mode];
end
return cfg.presentation['sep_' .. mode], postscript;
end
--[[--------------------------< S E T _ S T Y L E >-----------------------------
Sets the separator and postscript styles. Checks the |mode= first and the
#invoke CitationClass second. Removes the postscript if postscript == none.
]]
local function set_style (mode, postscript, cite_class)
local sep;
if 'cs2' == mode then
sep, postscript = set_cs_style (postscript, 'cs2');
elseif 'cs1' == mode then
sep, postscript = set_cs_style (postscript, 'cs1');
elseif 'citation' == cite_class then
sep, postscript = set_cs_style (postscript, 'cs2');
else
sep, postscript = set_cs_style (postscript, 'cs1');
end
if cfg.keywords_xlate[postscript:lower()] == 'none' then
-- emit a maintenance message if user postscript is the default cs2 postscript
-- we catch the opposite case for cs1 in set_cs_style
if 'cs2' == mode or ('cs1' ~= mode and 'citation' == cite_class) then -- {{citation |title=Title |mode=cs1 |postscript=none}} should not emit maint message
utilities.set_message ('maint_postscript');
end
postscript = '';
end
return sep, postscript
end
--[=[-------------------------< I S _ P D F >-----------------------------------
Determines if a URL has the file extension that is one of the PDF file extensions
used by [[MediaWiki:Common.css]] when applying the PDF icon to external links.
returns true if file extension is one of the recognized extensions, else false
]=]
local function is_pdf (url)
return url:match ('%.pdf$') or url:match ('%.PDF$') or
url:match ('%.pdf[%?#]') or url:match ('%.PDF[%?#]') or
url:match ('%.PDF#') or url:match ('%.pdf#');
end
--[[--------------------------< S T Y L E _ F O R M A T >-----------------------
Applies CSS style to |format=, |chapter-format=, etc. Also emits an error message
if the format parameter does not have a matching URL parameter. If the format parameter
is not set and the URL contains a file extension that is recognized as a PDF document
by MediaWiki's commons.css, this code will set the format parameter to (PDF) with
the appropriate styling.
]]
local function style_format (format, url, fmt_param, url_param)
if utilities.is_set (format) then
format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize
if not utilities.is_set (url) then
utilities.set_message ('err_format_missing_url', {fmt_param, url_param}); -- add an error message
end
elseif is_pdf (url) then -- format is not set so if URL is a PDF file then
format = utilities.wrap_style ('format', 'PDF'); -- set format to PDF
else
format = ''; -- empty string for concatenation
end
return format;
end
--[[---------------------< G E T _ D I S P L A Y _ N A M E S >------------------
Returns a number that defines the number of names displayed for author and editor
name lists and a Boolean flag to indicate when et al. should be appended to the name list.
When the value assigned to |display-xxxxors= is a number greater than or equal to zero,
return the number and the previous state of the 'etal' flag (false by default
but may have been set to true if the name list contains some variant of the text 'et al.').
When the value assigned to |display-xxxxors= is the keyword 'etal', return a number
that is one greater than the number of authors in the list and set the 'etal' flag true.
This will cause the list_people() to display all of the names in the name list followed by 'et al.'
In all other cases, returns nil and the previous state of the 'etal' flag.
inputs:
max: A['DisplayAuthors'] or A['DisplayEditors'], etc; a number or some flavor of etal
count: #a or #e
list_name: 'authors' or 'editors'
etal: author_etal or editor_etal
This function sets an error message when |display-xxxxors= value greater than or equal to number of names but
not when <max> comes from {{cs1 config}} global settings. When using global settings, <param> is set to the
keyword 'cs1 config' which is used to supress the normal error. Error is suppressed because it is to be expected
that some citations in an article will have the same or fewer names that the limit specified in {{cs1 config}}.
]]
local function get_display_names (max, count, etal, param)
if utilities.is_set (max) then
if 'etal' == cfg.keywords_xlate[max:lower():gsub("[ '%.]", '')] then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
max = count + 1; -- number of authors + 1 so display all author name plus et al.
etal = true; -- overrides value set by extract_names()
elseif max:match ('^%d+$') then -- if is a string of numbers
max = tonumber (max); -- make it a number
if (max >= count) and ('cs1 config' ~= param) then -- error when local |display-xxxxors= value greater than or equal to number of names; not an error when using global setting
utilities.set_message ('err_disp_name', {param, max}); -- add error message
max = nil;
end
else -- not a valid keyword or number
utilities.set_message ('err_disp_name', {param, max}); -- add error message
max = nil; -- unset; as if |display-xxxxors= had not been set
end
end
return max, etal;
end
--[[----------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >---------------
Adds error if |page=, |pages=, |quote-page=, |quote-pages= has what appears to be
some form of p. or pp. abbreviation in the first characters of the parameter content.
check page for extraneous p, p., pp, pp., pg, pg. at start of parameter value:
good pattern: '^P[^%.P%l]' matches when page begins PX or P# but not Px
where x and X are letters and # is a digit
bad pattern: '^[Pp][PpGg]' matches when page begins pp, pP, Pp, PP, pg, pG, Pg, PG
]]
local function extra_text_in_page_check (val, name)
if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns
if val:match (pattern) then -- when a match, error so
utilities.set_message ('err_extra_text_pages', name); -- add error message
return; -- and done
end
end
end
end
--[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------
Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. Applies to
both; this function looks for issue text in both |issue= and |volume= and looks for volume-like text in |voluem=
and |issue=.
For |volume=:
'V.', or 'Vol.' (with or without the dot) abbreviations or 'Volume' in the first characters of the parameter
content (all case insensitive). 'V' and 'v' (without the dot) are presumed to be roman numerals so
are allowed.
For |issue=:
'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the
parameter content (all case insensitive); numero styling: 'n°' with degree sign U+00B0, and № precomposed
numero sign U+2116.
Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or
whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module.
<val> is |volume= or |issue= parameter value
<name> is |volume= or |issue= parameter name for error message
<selector> is 'v' for |volume=, 'i' for |issue=
sets error message on failure; returns nothing
]]
local function extra_text_in_vol_iss_check (val, name, selector)
if not utilities.is_set (val) then
return;
end
local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue';
local accept_val; -- for now, ignore linter warning
val, accept_val = utilities.has_accept_as_written (val);
--if accept_val then -- if uncomment this, |volume=((vol. 1)) suppresses error
-- return;
--end
--val = mw.text.unstripNoWiki (val); -- if uncomment this, |volume=<nowiki>vol. 1</nowiki> shows error
val = val:lower(); -- force parameter value to lower case
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.vi_patterns_t) do -- spin through the sequence table of patterns
if val:match (pattern) then -- when a match, error so
utilities.set_message (handler, name); -- add error message
return; -- and done
end
end
end
--[=[-------------------------< G E T _ V _ N A M E _ T A B L E >----------------------------------------------
split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled
parentheses to also have commas; in the old version of the code, the doubled parentheses were included in the
rendered citation and in the metadata. Individual author names may be wikilinked
|vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.))
]=]
local function get_v_name_table (vparam, output_table, output_link_table)
local _, accept = utilities.has_accept_as_written (vparam);
if accept then
utilities.add_prop_cat ('vanc-accept'); -- add properties category
end
local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas
local wl_type, label, link; -- wl_type not used here; just a placeholder
local i = 1;
while name_table[i] do
if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses
local name = name_table[i];
i = i + 1; -- bump indexer to next segment
while name_table[i] do
name = name .. ', ' .. name_table[i]; -- concatenate with previous segments
if name_table[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses
break; -- and done reassembling so
end
i = i + 1; -- bump indexer
end
table.insert (output_table, name); -- and add corporate name to the output table
table.insert (output_link_table, ''); -- no wikilink
else
wl_type, label, link = utilities.is_wikilink (name_table[i]); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]
table.insert (output_table, label); -- add this name
if 1 == wl_type then
table.insert (output_link_table, label); -- simple wikilink [[D]]
else
table.insert (output_link_table, link); -- no wikilink or [[L|D]]; add this link if there is one, else empty string
end
end
i = i + 1;
end
return output_table;
end
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >--------------------------------
This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and
|xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does.
Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
tests, are wrapped in doubled parentheses ((corporate name)) to suppress the format tests.
Supports generational suffixes Jr, 2nd, 3rd, 4th–6th.
This function sets the Vancouver error when a required comma is missing and when there is a space between an author's initials.
]]
local function parse_vauthors_veditors (args, vparam, list_name)
local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn=
local v_name_table = {};
local v_link_table = {}; -- when name is wikilinked, targets go in this table
local etal = false; -- return value set to true when we find some form of et al. vauthors parameter
local last, first, link, mask, suffix;
local corporate = false;
vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period)
v_name_table = get_v_name_table (vparam, v_name_table, v_link_table); -- names are separated by commas
for i, v_name in ipairs(v_name_table) do
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
local accept_name;
v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name>
if accept_name then
last = v_name;
corporate = true; -- flag used in list_people()
elseif string.find(v_name, "%s") then
if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters;
add_vanc_error (cfg.err_msg_supl.punctuation, i);
end
local lastfirst_t = mw.text.split(v_name, "%s+");
first = table.remove (lastfirst_t); -- removes and returns value of last element in table which should be initials or generational suffix
if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters
suffix = first; -- not initials so assume that whatever we got is a generational suffix
first = table.remove (lastfirst_t); -- get what should be the initials from the table
end
last = table.concat (lastfirst_t, ' '); -- returns a string that is the concatenation of all other names that are not initials and generational suffix
if not utilities.is_set (last) then
first = ''; -- unset
last = v_name; -- last empty because something wrong with first
add_vanc_error (cfg.err_msg_supl.name, i);
end
if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then
add_vanc_error (cfg.err_msg_supl['missing comma'], i); -- matches last II last; the case when a comma is missing
end
if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test
add_vanc_error (cfg.err_msg_supl.initials, i); -- matches a space between two initials
end
else
last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this?
end
if utilities.is_set (first) then
if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else
add_vanc_error (cfg.err_msg_supl.initials, i); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials
end
is_good_vanc_name (last, first, suffix, i); -- check first and last before restoring the suffix which may have a non-Latin digit
if utilities.is_set (suffix) then
first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials
suffix = ''; -- unset so we don't add this suffix to all subsequent names
end
else
if not corporate then
is_good_vanc_name (last, '', nil, i);
end
end
link = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ) or v_link_table[i];
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i );
names[i] = {last = last, first = first, link = link, mask = mask, corporate = corporate}; -- add this assembled name to our names list
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------
Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or
select one of |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list.
Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest;
|editorn= (and aliases) highest and |veditors= lowest (support for |editors= withdrawn)
When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second
test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better
way to do this, I just haven't discovered what that way is.
Emits an error message when more than one xxxxor name source is provided.
In this function, vxxxxors = vauthors or veditors; xxxxors = authors as appropriate.
]]
local function select_author_editor_source (vxxxxors, xxxxors, args, list_name)
local lastfirst = false;
if utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice in case we have a |first1= without a |last1=; this ...
utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors=
utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) or
utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 2 ) then
lastfirst = true;
end
if (utilities.is_set (vxxxxors) and true == lastfirst) or -- these are the three error conditions
(utilities.is_set (vxxxxors) and utilities.is_set (xxxxors)) or
(true == lastfirst and utilities.is_set (xxxxors)) then
utilities.set_message ('err_redundant_parameters',
utilities.substitute (cfg.special_case_translation.name_list_params,
('AuthorList' == list_name) and cfg.special_case_translation.author or cfg.special_case_translation.editor)); -- add error message
end
if true == lastfirst then return 1 end; -- return a number indicating which author name source to use
if utilities.is_set (vxxxxors) then return 2 end;
if utilities.is_set (xxxxors) then return 3 end;
return 1; -- no authors so return 1; this allows missing author name test to run in case there is a first without last
end
--[[--------------------------< I S _ V A L I D _ P A R A M E T E R _ V A L U E >------------------------------
This function is used to validate a parameter's assigned value for those parameters that have only a limited number
of allowable values (yes, y, true, live, dead, etc.). When the parameter value has not been assigned a value (missing
or empty in the source template) the function returns the value specified by ret_val. If the parameter value is one
of the list of allowed values returns the translated value; else, emits an error message and returns the value
specified by ret_val.
TODO: explain <invert>
]]
local function is_valid_parameter_value (value, name, possible, ret_val, invert)
if not utilities.is_set (value) then
return ret_val; -- an empty parameter is ok
end
if (not invert and utilities.in_array (value, possible)) then -- normal; <value> is in <possible> table
return cfg.keywords_xlate[value]; -- return translation of parameter keyword
elseif invert and not utilities.in_array (value, possible) then -- invert; <value> is not in <possible> table
return value; -- return <value> as it is
else
utilities.set_message ('err_invalid_param_val', {name, value}); -- not an allowed value so add error message
return ret_val;
end
end
--[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >----------------------------------------
This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space
when the last character is not a sepc character or when the last three characters are not sepc followed by two
closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a
single space character.
]]
local function terminate_name_list (name_list, sepc)
if (string.sub (name_list, -3, -1) == sepc .. '. ') then -- if already properly terminated
return name_list; -- just return the name list
elseif (string.sub (name_list, -1, -1) == sepc) or (string.sub (name_list, -3, -1) == sepc .. ']]') then -- if last name in list ends with sepc char
return name_list .. " "; -- don't add another
else
return name_list .. sepc .. ' '; -- otherwise terminate the name list
end
end
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >-----------------------------------------
returns the concatenation of the formatted volume and issue (or journal article number) parameters as a single
string; or formatted volume or formatted issue, or an empty string if neither are set.
]]
local function format_volume_issue (volume, issue, article, cite_class, origin, sepc, lower)
if not utilities.is_set (volume) and not utilities.is_set (issue) and not utilities.is_set (article) then
return '';
end
-- same condition as in format_pages_sheets()
local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin);
local is_numeric_vol = volume and (volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$')); -- is only uppercase roman numerals or only digits?
local is_long_vol = volume and (4 < mw.ustring.len(volume)); -- is |volume= value longer than 4 characters?
if volume and (not is_numeric_vol and is_long_vol) then -- when not all digits or Roman numerals, is |volume= longer than 4 characters?
utilities.add_prop_cat ('long-vol'); -- yes, add properties cat
end
if is_journal then -- journal-style formatting
local vol = '';
if utilities.is_set (volume) then
if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals?
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, volume}); -- render in bold face
elseif is_long_vol then -- not all digits or Roman numerals; longer than 4 characters?
vol = utilities.substitute (cfg.messages['j-vol'], {sepc, utilities.hyphen_to_dash (volume)}); -- not bold
else -- four or fewer characters
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, utilities.hyphen_to_dash (volume)}); -- bold
end
end
vol = vol .. (utilities.is_set (issue) and utilities.substitute (cfg.messages['j-issue'], issue) or '')
vol = vol .. (utilities.is_set (article) and utilities.substitute (cfg.messages['j-article-num'], article) or '')
return vol;
end
if 'podcast' == cite_class and utilities.is_set (issue) then
return wrap_msg ('issue', {sepc, issue}, lower);
end
if 'conference' == cite_class and utilities.is_set (article) then -- |article-number= supported only in journal and conference cites
if utilities.is_set (volume) and utilities.is_set (article) then -- both volume and article number
return wrap_msg ('vol-art', {sepc, utilities.hyphen_to_dash (volume), article}, lower);
elseif utilities.is_set (article) then -- article number alone; when volume alone, handled below
return wrap_msg ('art', {sepc, article}, lower);
end
end
-- all other types of citation
if utilities.is_set (volume) and utilities.is_set (issue) then
return wrap_msg ('vol-no', {sepc, utilities.hyphen_to_dash (volume), issue}, lower);
elseif utilities.is_set (volume) then
return wrap_msg ('vol', {sepc, utilities.hyphen_to_dash (volume)}, lower);
else
return wrap_msg ('issue', {sepc, issue}, lower);
end
end
--[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >-----------------------------------------
adds static text to one of |page(s)= or |sheet(s)= values and returns it with all of the others set to empty strings.
The return order is:
page, pages, sheet, sheets
Singular has priority over plural when both are provided.
]]
local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower)
if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators
if utilities.is_set (sheet) then
if 'journal' == origin then
return '', '', wrap_msg ('j-sheet', sheet, lower), '';
else
return '', '', wrap_msg ('sheet', {sepc, sheet}, lower), '';
end
elseif utilities.is_set (sheets) then
if 'journal' == origin then
return '', '', '', wrap_msg ('j-sheets', sheets, lower);
else
return '', '', '', wrap_msg ('sheets', {sepc, sheets}, lower);
end
end
end
local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin);
if utilities.is_set (page) then
if is_journal then
return utilities.substitute (cfg.messages['j-page(s)'], page), '', '', '';
elseif not nopp then
return utilities.substitute (cfg.messages['p-prefix'], {sepc, page}), '', '', '';
else
return utilities.substitute (cfg.messages['nopp'], {sepc, page}), '', '', '';
end
elseif utilities.is_set (pages) then
if is_journal then
return utilities.substitute (cfg.messages['j-page(s)'], pages), '', '', '';
elseif tonumber(pages) ~= nil and not nopp then -- if pages is only digits, assume a single page number
return '', utilities.substitute (cfg.messages['p-prefix'], {sepc, pages}), '', '';
elseif not nopp then
return '', utilities.substitute (cfg.messages['pp-prefix'], {sepc, pages}), '', '';
else
return '', utilities.substitute (cfg.messages['nopp'], {sepc, pages}), '', '';
end
end
return '', '', '', ''; -- return empty strings
end
--[[--------------------------< I N S O U R C E _ L O C _ G E T >----------------------------------------------
returns one of the in-source locators: page, pages, or at.
If any of these are interwiki links to Wikisource, returns the label portion of the interwiki-link as plain text
for use in COinS. This COinS thing is done because here we convert an interwiki-link to an external link and
add an icon span around that; get_coins_pages() doesn't know about the span. TODO: should it?
TODO: add support for sheet and sheets?; streamline;
TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned
to a new name)?
]]
local function insource_loc_get (page, page_orig, pages, pages_orig, at)
local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?)
if utilities.is_set (page) then
if utilities.is_set (pages) or utilities.is_set (at) then
pages = ''; -- unset the others
at = '';
end
extra_text_in_page_check (page, page_orig); -- emit error message when |page= value begins with what looks like p., pp., etc.
ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label
if ws_url then
page = external_link (ws_url, ws_label .. ' ', 'ws link in page'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
page = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, page});
coins_pages = ws_label;
end
elseif utilities.is_set (pages) then
if utilities.is_set (at) then
at = ''; -- unset
end
extra_text_in_page_check (pages, pages_orig); -- emit error message when |page= value begins with what looks like p., pp., etc.
ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label
if ws_url then
pages = external_link (ws_url, ws_label .. ' ', 'ws link in pages'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
pages = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, pages});
coins_pages = ws_label;
end
elseif utilities.is_set (at) then
ws_url, ws_label, L = wikisource_url_make (at); -- make ws URL from |at= interwiki link; link portion L becomes tooltip label
if ws_url then
at = external_link (ws_url, ws_label .. ' ', 'ws link in at'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
at = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, at});
coins_pages = ws_label;
end
end
return page, pages, at, coins_pages;
end
--[[--------------------------< I S _ U N I Q U E _ A R C H I V E _ U R L >------------------------------------
add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value
]]
local function is_unique_archive_url (archive, url, c_url, source, date)
if utilities.is_set (archive) then
if archive == url or archive == c_url then
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); -- add error message
return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url=
end
end
return archive, date;
end
--[=[-------------------------< A R C H I V E _ U R L _ C H E C K >--------------------------------------------
Check archive.org URLs to make sure they at least look like they are pointing at valid archives and not to the
save snapshot URL or to calendar pages. When the archive URL is 'https://web.archive.org/save/' (or http://...)
archive.org saves a snapshot of the target page in the URL. That is something that Wikipedia should not allow
unwitting readers to do.
When the archive.org URL does not have a complete timestamp, archive.org chooses a snapshot according to its own
algorithm or provides a calendar 'search' result. [[WP:ELNO]] discourages links to search results.
This function looks at the value assigned to |archive-url= and returns empty strings for |archive-url= and
|archive-date= and an error message when:
|archive-url= holds an archive.org save command URL
|archive-url= is an archive.org URL that does not have a complete timestamp (YYYYMMDDhhmmss 14 digits) in the
correct place
otherwise returns |archive-url= and |archive-date=
There are two mostly compatible archive.org URLs:
//web.archive.org/<timestamp>... -- the old form
//web.archive.org/web/<timestamp>... -- the new form
The old form does not support or map to the new form when it contains a display flag. There are four identified flags
('id_', 'js_', 'cs_', 'im_') but since archive.org ignores others following the same form (two letters and an underscore)
we don't check for these specific flags but we do check the form.
This function supports a preview mode. When the article is rendered in preview mode, this function may return a modified
archive URL:
for save command errors, return undated wildcard (/*/)
for timestamp errors when the timestamp has a wildcard, return the URL unmodified
for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/)
A secondary function is to return an archive-url timestamp from those archive urls that have them. The timestamp
is used by validation.archive_date_check() to see if the value in |archive-date= matches the timestamp in the
archive url.
]=]
local function archive_url_check (url, date)
local err_msg; -- start with the error message empty
local path, timestamp, flag; -- portions of the archive.org URL
local function is_ts_date_valid (ts, origin_date) -- local function to validate archive url taimestamp date; time ignored
local y, m, d = ts:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- split into parts
if y and validation.is_valid_date (y, m, d) and (tonumber (y) >= 1996) then
return true, tonumber (y) >= origin_date; -- <origin_date> is 1996 for archive.org
end
end
if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL
return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate
end
if url:match('//web%.archive%.org/save/') then -- if a save command URL, we don't want to allow saving of the target page
err_msg = cfg.err_msg_supl.save;
url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL
elseif url:match('//liveweb%.archive%.org/') then
err_msg = cfg.err_msg_supl.liveweb;
else
path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation
if not path then -- malformed in some way; pattern did not match
err_msg = cfg.err_msg_supl.timestamp;
elseif 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here
err_msg = cfg.err_msg_supl.timestamp;
if '*' ~= flag then
local replacement = timestamp:match ('^%d%d%d%d%d%d') or timestamp:match ('^%d%d%d%d'); -- get the first 6 (YYYYMM) or first 4 digits (YYYY)
if replacement then -- nil if there aren't at least 4 digits (year)
replacement = replacement .. string.rep ('0', 14 - replacement:len()); -- year or yearmo (4 or 6 digits) zero-fill to make 14-digit timestamp
url=url:gsub ('(//web%.archive%.org/[^%d]*)%d[^/]*', '%1' .. replacement .. '*', 1) -- for preview, modify ts to 14 digits plus splat for calendar display
end
end
elseif not is_ts_date_valid (timestamp, 1996) then -- is ymd portion of timestamp a valid date?
err_msg = cfg.err_msg_supl.timestamp;
timestamp = nil; -- unset because invalid
elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element
err_msg = cfg.err_msg_supl.path;
elseif utilities.is_set (flag) and not utilities.is_set (path) then -- flag not allowed with the old form URL (without the 'web/' path element)
err_msg = cfg.err_msg_supl.flag;
elseif utilities.is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element)
err_msg = cfg.err_msg_supl.flag;
else
return url, date, timestamp; -- return ArchiveURL, ArchiveDate, and timestamp from |archive-url=
end
end
-- if here, something not right so
utilities.set_message ('err_archive_url', {err_msg}); -- add error message and
if is_preview_mode then
return url, date, timestamp; -- preview mode so return ArchiveURL, ArchiveDate, and timestamp from |archive-url=
else
return '', ''; -- return empty strings for ArchiveURL and ArchiveDate
end
end
--[[--------------------------< P L A C E _ C H E C K >--------------------------------------------------------
check |place=, |publication-place=, |location= to see if these params include digits. This function added because
many editors misuse location to specify the in-source location (|page(s)= and |at= are supposed to do that)
returns the original parameter value without modification; added maint cat when parameter value contains digits
]]
local function place_check (param_val)
if not utilities.is_set (param_val) then -- parameter empty or omitted
return param_val; -- return that empty state
end
if mw.ustring.find (param_val, '%d') then -- not empty, are there digits in the parameter value
utilities.set_message ('maint_location'); -- yep, add maint cat
end
return param_val; -- and done
end
--[[--------------------------< I S _ A R C H I V E D _ C O P Y >----------------------------------------------
compares |title= to 'Archived copy' (placeholder added by bots that can't find proper title); if matches, return true; nil else
]]
local function is_archived_copy (title)
title = mw.ustring.lower(title); -- switch title to lower case
if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy'
return true;
elseif cfg.special_case_translation.archived_copy['local'] then
if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script
return true;
end
end
end
--[[--------------------------< D I S P L A Y _ N A M E S _ S E L E C T >--------------------------------------
for any of the |display-authors=, |display-editors=, etc parameters, select either the local or global setting.
When both are present, look at <local_display_names> value. When the value is some sort of 'et al.'string,
special handling is required.
When {{cs1 config}} has |display-<namelist>= AND this template has |display-<namelist>=etal AND:
the number of names specified by <number_of_names> is:
greater than the number specified in the global |display-<namelist>= parameter (<global_display_names>)
use global |display-<namelist>= parameter value
set overridden maint category
less than or equal to the number specified in the global |display-<namelist>= parameter
use local |display-<namelist>= parameter value
The purpose of this function is to prevent categorizing a template that has fewer names than the global setting
to keep the etal annotation specified by <local_display_names>.
]]
local function display_names_select (global_display_names, local_display_names, param_name, number_of_names)
if global_display_names and utilities.is_set (local_display_names) then -- when both
if 'etal' == local_display_names:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
number_of_names = tonumber (number_of_names); -- convert these to numbers for comparison
local global_display_names_num = tonumber (global_display_names); -- <global_display_names> not set when parameter value is not digits
if number_of_names > global_display_names_num then -- template has more names than global config allows to be displayed?
utilities.set_message ('maint_overridden_setting'); -- set a maint message because global is overriding local |display-<namelist>=etal
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
else
return local_display_names, param_name; -- return local because fewer names so let <local_display_names> control
end
end
-- here when <global_display_names> and <local_display_names> both numbers; <global_display_names> controls
utilities.set_message ('maint_overridden_setting'); -- set a maint message
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
end
-- here when only one of <global_display_names> or <local_display_names> set
if global_display_names then
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
else
return local_display_names, param_name; -- return local
end
end
--[[--------------------------< M O D E _ S E T >--------------------------------------------------------------
fetch global mode setting from {{cs1 config}} (if present) or from |mode= (if present); global setting overrides
local |mode= parameter value. When both are present, emit maintenance message
]]
local function mode_set (Mode, Mode_origin)
local mode;
if cfg.global_cs1_config_t['Mode'] then -- global setting in {{cs1 config}}; nil when empty or assigned value invalid
mode = is_valid_parameter_value (cfg.global_cs1_config_t['Mode'], 'cs1 config: mode', cfg.keywords_lists['mode'], ''); -- error messaging 'param' here is a hoax
else
mode = is_valid_parameter_value (Mode, Mode_origin, cfg.keywords_lists['mode'], '');
end
if cfg.global_cs1_config_t['Mode'] and utilities.is_set (Mode) then -- when template has |mode=<something> which global setting has overridden
utilities.set_message ('maint_overridden_setting'); -- set a maint message
end
return mode;
end
--[[--------------------------< Q U O T E _ M A K E >----------------------------------------------------------
create quotation from |quote=, |trans-quote=, and/or script-quote= with or without |quote-page= or |quote-pages=
when any of those three quote parameters are set, this function unsets <PostScript>. When none of those parameters
are set, |quote-page= and |quote-pages= are unset to nil so that they are not included in the template's metadata
]]
local function quote_make (quote, trans_quote, script_quote, quote_page, quote_pages, nopp, sepc, postscript)
if utilities.is_set (quote) or utilities.is_set (trans_quote) or utilities.is_set (script_quote) then
if utilities.is_set (quote) then
if quote:sub(1, 1) == '"' and quote:sub(-1, -1) == '"' then -- if first and last characters of quote are quote marks
quote = quote:sub(2, -2); -- strip them off
end
end
quote = kern_quotes (quote); -- kern if needed
quote = utilities.wrap_style ('quoted-text', quote ); -- wrap in <q>...</q> tags
if utilities.is_set (script_quote) then
quote = script_concatenate (quote, script_quote, 'script-quote'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after quote is wrapped
end
if utilities.is_set (trans_quote) then
if trans_quote:sub(1, 1) == '"' and trans_quote:sub(-1, -1) == '"' then -- if first and last characters of |trans-quote are quote marks
trans_quote = trans_quote:sub(2, -2); -- strip them off
end
quote = quote .. " " .. utilities.wrap_style ('trans-quoted-title', trans_quote );
end
if utilities.is_set (quote_page) or utilities.is_set (quote_pages) then -- add page prefix
local quote_prefix = '';
if utilities.is_set (quote_page) then
extra_text_in_page_check (quote_page, 'quote-page'); -- add to maint cat if |quote-page= value begins with what looks like p., pp., etc.
if not nopp then
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, quote_page});
else
quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, quote_page});
end
elseif utilities.is_set (quote_pages) then
extra_text_in_page_check (quote_pages, 'quote-pages'); -- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc.
if tonumber(quote_pages) ~= nil and not nopp then -- if only digits, assume single page
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, quote_pages});
elseif not nopp then
quote_prefix = utilities.substitute (cfg.messages['pp-prefix'], {sepc, quote_pages});
else
quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, quote_pages});
end
end
quote = quote_prefix .. ": " .. quote;
else
quote = sepc .. " " .. quote;
end
postscript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set
elseif utilities.is_set (quote_page) or utilities.is_set (quote_pages) then
quote_page = nil; -- unset; these require |quote=; TODO: error message?
quote_pages = nil;
end
return quote, quote_page, quote_pages, postscript;
end
--[[--------------------------< C H E C K _ P U B L I S H E R _ N A M E >--------------------------------------
look for variations of '<text>: <text>' that might be '<location>: <publisher>' in |publisher= parameter value.
when found, emit a maintenance message; return nil else
<publisher> is the value assigned to |publisher= or |institution=
]]
local function check_publisher_name (publisher)
local patterns_t = {
'^[%w%s]+%s*:%s*[%w%s]+$', -- plain text <location>: <publisher>
'^%[+[%w%s:|]+%]+%s*:%s*[%w%s]+$', -- partially wikilinked [[<location>]]: <publisher>
'^[%w%s]+%s*:%s*%[+[%w%s:|]+%]+$', -- partially wikilinked <location>: [[<publisher>]]
'^%[+[%w%s:|]+%]+%s*:%s*%[+[%w%s:|]+%]+$', -- wikilinked [[<location>]]: [[<publisher>]]
}
for _, pattern in ipairs (patterns_t) do -- spin through the patterns_t sequence
if mw.ustring.match (publisher, pattern) then -- does this pattern match?
utilities.set_message ('maint_publisher_location'); -- set a maint message
return; -- and done
end
end
end
--[[--------------------------< I S _ P A G E _ A R T _ N U M >------------------------------------------------
compare the trailing (rightmost) characters of the |doi= value against the whole value assigned to |page(s)=.
return boolean true when:
|page(s)= has exactly 8 digits and a dot between the fourth and fifth digits matches the trailing 9 characters
of the |doi= value: |page=12345678 → |page=1234.5678 matches |doi=10.xxxx/yyyy1234.5678
|page(s)= is 5 or more characters and matches |doi= values's trailing characters
|page(s)= begins with a lowercase 'e' and |page(s)= without the 'e' matches |doi= values's trailing
characters: |page=e12345 → |page=12345 matches |doi=10.xxxx/yyyy12345
|page(s)= begins with a uppercase 'CD' followed by (typically) six digits matches |doi= values that ends with
'CDxxxxxx.pubx' (where 'x' is any single digit)
return nil when |page(s)= values:
are ranges separated by underscore, hyphen, emdash, endash, figure dash, or minus character
are comma- or semicolon-separated lists of pages
have external urls (has text 'http')
are digit-only values less than 10000
do not match |doi= values's trailing characters
]]
local function is_page_art_num (page, doi)
if not (utilities.is_set (page) and utilities.is_set (doi)) then -- both required
return; -- abandon; nothing to do
end
if page:match ('[,;_−–—‒%-]') then -- when |page(s)= might be a page range or a separated list of pages
return; -- abandon
end
page = page:lower(); -- because doi names are case insensitive
doi = doi:lower(); -- force these to lowercase for testing
if page:match ('http') then -- when |page(s)= appears to hold a url
return; -- abandon
end
if tonumber (page) then -- is |page(s)= digits only
if 10000 > tonumber (page) then -- when |page(s)= less than 10000
return; -- abandon
end
if doi:match (page .. '$') then -- digits only page number match the last digits in |doi=?
return true;
end
if 8 == page:len() then -- special case when |page(s)= is exactly 8 digits
local dot_page = page:gsub ('(%d%d%d%d)(%d%d%d%d)', '%1.%2'); -- make a |page=xxxx.yyyy version commonly used in |doi=
if doi:match (dot_page .. '$') then -- 8-digit dotted page number match the last characters in |doi=?
return true;
end
end
else -- here when |page(s)= is alpha-numeric
if 4 < page:len() then -- when |page(s)= is five or more characters
if doi:match (page .. '$') then -- alpha-numeric page match the last characters in |doi=?
return true;
end
local epage = page:match ('^e([%w]+)$'); -- if first character of |page= is 'e', remove it
if epage and doi:match (epage .. '$') then -- page number match the last characters in |doi=?
return true;
end
local cdpage = page:match ('^cd%d+$'); -- if first characters of |page= are 'CD' and last characters are digits (typically 6 digits)
if cdpage and doi:match (cdpage .. '%.pub%d$') then -- page number matches doi 'CDxxxxxx.pubx' where 'x' is a digit
return true;
end
end
end
end
--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------
This is the main function doing the majority of the citation formatting.
]]
local function citation0( config, args )
--[[
Load Input Parameters
The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.
]]
local A = argument_wrapper ( args );
-- Pick out the relevant fields from the arguments. Different citation templates
-- define different field names for the same underlying things.
local author_etal;
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors=
local Authors;
local NameListStyle;
if cfg.global_cs1_config_t['NameListStyle'] then -- global setting in {{cs1 config}} overrides local |name-list-style= parameter value; nil when empty or assigned value invalid
NameListStyle = is_valid_parameter_value (cfg.global_cs1_config_t['NameListStyle'], 'cs1 config: name-list-style', cfg.keywords_lists['name-list-style'], ''); -- error messaging 'param' here is a hoax
else
NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], '');
end
if cfg.global_cs1_config_t['NameListStyle'] and utilities.is_set (A['NameListStyle']) then -- when template has |name-list-style=<something> which global setting has overridden
utilities.set_message ('maint_overridden_setting'); -- set a maint message
end
local Collaboration = A['Collaboration'];
do -- to limit scope of selected
local selected = select_author_editor_source (A['Vauthors'], A['Authors'], args, 'AuthorList');
if 1 == selected then
a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn=
elseif 2 == selected then
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be
a, author_etal = parse_vauthors_veditors (args, A['Vauthors'], 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn=
elseif 3 == selected then
Authors = A['Authors']; -- use content of |people= or |credits=; |authors= is deprecated; TODO: constrain |people= and |credits= to cite av media, episode, serial?
end
if utilities.is_set (Collaboration) then
author_etal = true; -- so that |display-authors=etal not required
end
end
local editor_etal;
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors=
do -- to limit scope of selected
local selected = select_author_editor_source (A['Veditors'], nil, args, 'EditorList'); -- support for |editors= withdrawn
if 1 == selected then
e, editor_etal = extract_names (args, 'EditorList'); -- fetch editor list from |editorn= / |editor-lastn= / |editor-firstn=, |editor-linkn=, and |editor-maskn=
elseif 2 == selected then
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be
e, editor_etal = parse_vauthors_veditors (args, args.veditors, 'EditorList'); -- fetch editor list from |veditors=, |editor-linkn=, and |editor-maskn=
end
end
local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= and |script-chapter= aliases
local Chapter_origin = A:ORIGIN ('Chapter');
local ScriptChapter = A['ScriptChapter'];
local ScriptChapter_origin = A:ORIGIN ('ScriptChapter');
local Contribution; -- because contribution is required for contributor(s)
if 'contribution' == Chapter_origin then -- is there a |contribution= parameter?
Contribution = Chapter; -- get the name of the contribution
elseif 'script-contribution' == ScriptChapter_origin then -- no, so is there a |script-contribution= parameter?
Contribution = ScriptChapter; -- get the name of the contribution
end
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (A['Periodical']) then -- |contributor= and |contribution= only supported in book cites
c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn=
if 0 < #c then
if not utilities.is_set (Contribution) then -- |contributor= requires |contribution=
utilities.set_message ('err_contributor_missing_required_param', 'contribution'); -- add missing contribution error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
if 0 == #a then -- |contributor= requires |author=
utilities.set_message ('err_contributor_missing_required_param', 'author'); -- add missing author error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
end
else -- if not a book cite
if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters?
utilities.set_message ('err_contributor_ignored'); -- add contributor ignored error message
end
Contribution = nil; -- unset
end
local Title = A['Title'];
local TitleLink = A['TitleLink'];
local auto_select = ''; -- default is auto
local accept_link;
TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup
if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords
auto_select = TitleLink; -- remember selection for later
TitleLink = ''; -- treat as if |title-link= would have been empty
end
TitleLink = link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wiki-markup in |title-link= or wiki-markup in |title= when |title-link= is set
local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used
if 'map' == config.CitationClass and 'section' == Chapter_origin then
Section = A['Chapter']; -- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}}
Chapter = ''; -- unset for now; will be reset later from |map= if present
end
local Periodical = A['Periodical'];
local Periodical_origin = A:ORIGIN('Periodical');
local ScriptPeriodical = A['ScriptPeriodical'];
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical');
local TransPeriodical = A['TransPeriodical'];
local TransPeriodical_origin = A:ORIGIN ('TransPeriodical');
if (utilities.in_array (config.CitationClass, {'book', 'encyclopaedia'}) and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical))) then
local param;
if utilities.is_set (Periodical) then -- get a parameter name from one of these periodical related meta-parameters
Periodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = Periodical_origin -- get parameter name for error messaging
elseif utilities.is_set (TransPeriodical) then
TransPeriodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = TransPeriodical_origin; -- get parameter name for error messaging
elseif utilities.is_set (ScriptPeriodical) then
ScriptPeriodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = ScriptPeriodical_origin; -- get parameter name for error messaging
end
if utilities.is_set (param) then -- if we found one
utilities.set_message ('err_periodical_ignored', {param}); -- emit an error message
end
end
if utilities.is_set (Periodical) then
local i;
Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated
if i then -- non-zero when markup was stripped so emit an error message
utilities.set_message ('err_apostrophe_markup', {Periodical_origin});
end
end
if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}}
if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'mailinglist')});
end
Periodical = A ['MailingList']; -- error or no, set Periodical to |mailinglist= value because this template is {{cite mailing list}}
Periodical_origin = A:ORIGIN('MailingList');
end
-- web and news not tested for now because of
-- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors?
if not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter
-- local p = {['journal'] = 'journal', ['magazine'] = 'magazine', ['news'] = 'newspaper', ['web'] = 'website'}; -- for error message
local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message
if p[config.CitationClass] then
utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]});
end
end
local Volume;
if 'citation' == config.CitationClass then
if utilities.is_set (Periodical) then
if not utilities.in_array (Periodical_origin, cfg.citation_no_volume_t) then -- {{citation}} does not render |volume= when these parameters are used
Volume = A['Volume']; -- but does for all other 'periodicals'
end
elseif utilities.is_set (ScriptPeriodical) then
if 'script-website' ~= ScriptPeriodical_origin then -- {{citation}} does not render volume for |script-website=
Volume = A['Volume']; -- but does for all other 'periodicals'
end
else
Volume = A['Volume']; -- and does for non-'periodical' cites
end
elseif utilities.in_array (config.CitationClass, cfg.templates_using_volume) then -- render |volume= for cs1 according to the configuration settings
Volume = A['Volume'];
end
extra_text_in_vol_iss_check (Volume, A:ORIGIN ('Volume'), 'v');
local Issue;
if 'citation' == config.CitationClass then
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, cfg.citation_issue_t) then -- {{citation}} may render |issue= when these parameters are used
Issue = A['Issue'];
end
elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table
if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then
Issue = A['Issue'];
end
end
local ArticleNumber;
if utilities.in_array (config.CitationClass, {'journal', 'conference'}) or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then
ArticleNumber = A['ArticleNumber'];
end
extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i');
Issue = utilities.hyphen_to_dash (Issue);
local Page;
local Pages;
local At;
local QuotePage;
local QuotePages;
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then -- TODO: rewrite to emit ignored parameter error message?
Page = A['Page'];
Pages = utilities.hyphen_to_dash (A['Pages']);
At = A['At'];
QuotePage = A['QuotePage'];
QuotePages = utilities.hyphen_to_dash (A['QuotePages']);
end
local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil);
local Mode = mode_set (A['Mode'], A:ORIGIN('Mode'));
-- separator character and postscript
local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass);
local Quote;
Quote, QuotePage, QuotePages, PostScript = quote_make (A['Quote'], A['TransQuote'], A['ScriptQuote'], QuotePage, QuotePages, NoPP, sepc, PostScript);
local Edition = A['Edition'];
local PublicationPlace = place_check (A['PublicationPlace'], A:ORIGIN('PublicationPlace'));
local Place = place_check (A['Place'], A:ORIGIN('Place'));
local PublisherName = A['PublisherName'];
local PublisherName_origin = A:ORIGIN('PublisherName');
if utilities.is_set (PublisherName) and (cfg.keywords_xlate['none'] ~= PublisherName) then
local i;
PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized
if i and (0 < i) then -- non-zero when markup was stripped so emit an error message
utilities.set_message ('err_apostrophe_markup', {PublisherName_origin});
end
end
if ('document' == config.CitationClass) and not utilities.is_set (PublisherName) then
utilities.set_message ('err_missing_publisher', {config.CitationClass, 'publisher'});
end
local Newsgroup = A['Newsgroup']; -- TODO: strip apostrophe markup?
local Newsgroup_origin = A:ORIGIN('Newsgroup');
if 'newsgroup' == config.CitationClass then
if utilities.is_set (PublisherName) and (cfg.keywords_xlate['none'] ~= PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup
utilities.set_message ('err_parameter_ignored', {PublisherName_origin});
end
PublisherName = nil; -- ensure that this parameter is unset for the time being; will be used again after COinS
end
if 'book' == config.CitationClass or 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and not utilities.is_set (Periodical)) then
local accept;
PublisherName, accept = utilities.has_accept_as_written (PublisherName); -- check for and remove accept-as-written markup from |publisher= wrapped
if not accept then -- when no accept-as-written markup
check_publisher_name (PublisherName); -- emit maint message when |publisher= might be prefixed with publisher's location
end
end
local URL = A['URL']; -- TODO: better way to do this for URL, ChapterURL, and MapURL?
local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then
UrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', 'url');
end
local ChapterURL = A['ChapterURL'];
local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then
ChapterUrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')});
end
local MapUrlAccess = is_valid_parameter_value (A['MapUrlAccess'], A:ORIGIN('MapUrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then
MapUrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', {'map-url'});
end
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language
local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil);
-- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories
if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page
if cfg.uncategorized_namespaces[this_page.namespace] then -- is this page's namespace id one of the uncategorized namespace ids?
no_tracking_cats = "true"; -- set no_tracking_cats
end
for _, v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns
if this_page.text:match (v) then -- test page name against each pattern
no_tracking_cats = "true"; -- set no_tracking_cats
break; -- bail out if one is found
end
end
end
-- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it)
utilities.select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'err_redundant_parameters'); -- this is a dummy call simply to get the error message and category
local coins_pages;
Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN('Page'), Pages, A:ORIGIN('Pages'), At);
if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different
utilities.add_prop_cat ('location-test'); -- add property cat to evaluate how often PublicationPlace and Place are used together
if PublicationPlace == Place then
Place = ''; -- unset; don't need both if they are the same
end
elseif not utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- when only |place= (|location=) is set ...
PublicationPlace = Place; -- promote |place= (|location=) to |publication-place
end
if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same
local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL
local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL
-- local ScriptChapter = A['ScriptChapter'];
-- local ScriptChapter_origin = A:ORIGIN ('ScriptChapter');
local Format = A['Format'];
local ChapterFormat = A['ChapterFormat'];
local TransChapter = A['TransChapter'];
local TransChapter_origin = A:ORIGIN ('TransChapter');
local TransTitle = A['TransTitle'];
local ScriptTitle = A['ScriptTitle'];
--[[
Parameter remapping for cite encyclopedia:
When the citation has these parameters:
|encyclopedia= and |title= then map |title= to |article= and |encyclopedia= to |title= for rendering
|encyclopedia= and |article= then map |encyclopedia= to |title= for rendering
|trans-title= maps to |trans-chapter= when |title= is re-mapped
|url= maps to |chapter-url= when |title= is remapped
All other combinations of |encyclopedia=, |title=, and |article= are not modified
]]
local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS
local ScriptEncyclopedia = A['ScriptEncyclopedia'];
local TransEncyclopedia = A['TransEncyclopedia'];
if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}}
if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then
if utilities.is_set (Encyclopedia) then
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')});
else
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('ScriptEncyclopedia')});
end
Encyclopedia = nil; -- unset these because not supported by this template
ScriptEncyclopedia = nil;
TransEncyclopedia = nil;
end
elseif utilities.is_set (TransEncyclopedia) then
utilities.set_message ('err_trans_missing_title', {'encyclopedia'});
end
if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then
if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both parameters set emit an error message; {{citation}} only; Periodical not allowed in {{cite encyclopedia}}
utilities.set_message ('err_periodical_ignored', {Periodical_origin});
end
if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then
Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia for rendering; {{citation}} could (not legitimately) have both; use Encyclopedia
Periodical_origin = A:ORIGIN ('Encyclopedia');
ScriptPeriodical = ScriptEncyclopedia;
ScriptPeriodical_origin = A:ORIGIN ('ScriptEncyclopedia');
if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then
if not utilities.is_set (Chapter) then
Chapter = Title; -- |encyclopedia= and |title= are set so map |title= params to |article= params for rendering
ScriptChapter = ScriptTitle;
ScriptChapter_origin = A:ORIGIN('ScriptTitle')
TransChapter = TransTitle;
ChapterURL = URL;
ChapterURL_origin = URL_origin;
ChapterUrlAccess = UrlAccess;
ChapterFormat = Format;
if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then
Chapter = utilities.make_wikilink (TitleLink, Chapter);
end
Title = Periodical; -- now map |encyclopedia= params to |title= params for rendering
ScriptTitle = ScriptPeriodical or '';
TransTitle = TransEncyclopedia or '';
Periodical = ''; -- redundant so unset
ScriptPeriodical = '';
URL = '';
Format = '';
TitleLink = '';
end
elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set
Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= for rendering
ScriptTitle = ScriptPeriodical or '';
TransTitle = TransEncyclopedia or '';
Periodical = ''; -- redundant so unset
ScriptPeriodical = '';
end
end
end
-- special case for cite techreport.
local ID = A['ID'];
if (config.CitationClass == "techreport") then -- special case for cite techreport
if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue'
if not utilities.is_set (ID) then -- can we use ID for the "number"?
ID = A['Number']; -- yes, use it
else -- ID has a value so emit error message
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'number')});
end
end
end
-- Account for the oddity that is {{cite conference}}, before generation of COinS data.
local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode
local Conference = A['Conference'];
local BookTitle = A['BookTitle'];
local TransTitle_origin = A:ORIGIN ('TransTitle');
if 'conference' == config.CitationClass then
if utilities.is_set (BookTitle) then
Chapter = Title;
Chapter_origin = 'title';
-- ChapterLink = TitleLink; -- |chapter-link= is deprecated
ChapterURL = URL;
ChapterUrlAccess = UrlAccess;
ChapterURL_origin = URL_origin;
URL_origin = '';
ChapterFormat = Format;
TransChapter = TransTitle;
TransChapter_origin = TransTitle_origin;
Title = BookTitle;
Format = '';
-- TitleLink = '';
TransTitle = '';
URL = '';
end
elseif 'speech' ~= config.CitationClass then
Conference = ''; -- not cite conference or cite speech so make sure this is empty string
end
local cs2_lower = function (text) -- if mode is cs2, use lower case
if (sepc ~= '.') then
return text:lower();
end
return text;
end
local use_lowercase = ( sepc == ',' ); -- controls capitalization of certain static text
-- cite map oddities
local Cartography = "";
local Scale = "";
local Sheet = A['Sheet'] or '';
local Sheets = A['Sheets'] or '';
if config.CitationClass == "map" then
if utilities.is_set (Chapter) then --TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message
end
Chapter = A['Map'];
Chapter_origin = A:ORIGIN('Map'); -- for now, ignore linter warning
ChapterURL = A['MapURL'];
ChapterURL_origin = A:ORIGIN('MapURL');
TransChapter = A['TransMap'];
ScriptChapter = A['ScriptMap']
ScriptChapter_origin = A:ORIGIN('ScriptMap')
ChapterUrlAccess = MapUrlAccess;
ChapterFormat = A['MapFormat'];
Cartography = A['Cartography'];
if utilities.is_set ( Cartography ) then
Cartography = sepc .. " " .. wrap_msg ('cartography', Cartography, use_lowercase);
end
Scale = A['Scale'];
if utilities.is_set ( Scale ) then
Scale = sepc .. " " .. Scale;
end
end
-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.
local Series = A['Series'];
if 'episode' == config.CitationClass or 'serial' == config.CitationClass then
local SeriesLink = A['SeriesLink'];
SeriesLink = link_title_ok (SeriesLink, A:ORIGIN ('SeriesLink'), Series, 'series'); -- check for wiki-markup in |series-link= or wiki-markup in |series= when |series-link= is set
local Network = A['Network'];
local Station = A['Station'];
local s, n = {}, {};
-- do common parameters first
if utilities.is_set (Network) then table.insert(n, Network); end
if utilities.is_set (Station) then table.insert(n, Station); end
ID = table.concat(n, sepc .. ' ');
if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}}
local Season = A['Season'];
local SeriesNumber = A['SeriesNumber'];
if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message
SeriesNumber = ''; -- unset; prefer |season= over |seriesno=
end
-- assemble a table of parts concatenated later into Series
if utilities.is_set (Season) then table.insert(s, wrap_msg ('season', Season, use_lowercase)); end
if utilities.is_set (SeriesNumber) then table.insert(s, wrap_msg ('seriesnum', SeriesNumber, use_lowercase)); end
if utilities.is_set (Issue) then table.insert(s, wrap_msg ('episode', Issue, use_lowercase)); end
Issue = ''; -- unset because this is not a unique parameter
Chapter = Title; -- promote title parameters to chapter
ScriptChapter = ScriptTitle;
ScriptChapter_origin = A:ORIGIN('ScriptTitle');
ChapterLink = TitleLink; -- alias |episode-link=
TransChapter = TransTitle;
ChapterURL = URL;
ChapterUrlAccess = UrlAccess;
ChapterURL_origin = URL_origin;
ChapterFormat = Format;
Title = Series; -- promote series to title
TitleLink = SeriesLink;
Series = table.concat(s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number
if utilities.is_set (ChapterLink) and not utilities.is_set (ChapterURL) then -- link but not URL
Chapter = utilities.make_wikilink (ChapterLink, Chapter);
elseif utilities.is_set (ChapterLink) and utilities.is_set (ChapterURL) then -- if both are set, URL links episode;
Series = utilities.make_wikilink (ChapterLink, Series);
end
URL = ''; -- unset
TransTitle = '';
ScriptTitle = '';
Format = '';
else -- now oddities that are cite serial
Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
if utilities.is_set (Series) and utilities.is_set (SeriesLink) then
Series = utilities.make_wikilink (SeriesLink, Series);
end
Series = utilities.wrap_style ('italic-title', Series); -- series is italicized
end
end
-- end of {{cite episode}} stuff
-- handle type parameter for those CS1 citations that have default values
local TitleType = A['TitleType'];
local Degree = A['Degree'];
if utilities.in_array (config.CitationClass, {'AV-media-notes', 'document', 'interview', 'mailinglist', 'map', 'podcast', 'pressrelease', 'report', 'speech', 'techreport', 'thesis'}) then
TitleType = set_titletype (config.CitationClass, TitleType);
if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis
TitleType = Degree .. ' ' .. cfg.title_types ['thesis']:lower();
end
end
if utilities.is_set (TitleType) then -- if type parameter is specified
TitleType = utilities.substitute ( cfg.messages['type'], TitleType); -- display it in parentheses
-- TODO: Hack on TitleType to fix bunched parentheses problem
end
-- legacy: promote PublicationDate to Date if neither Date nor Year are set.
local Date = A['Date'];
local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging
local PublicationDate = A['PublicationDate'];
local Year = A['Year'];
if utilities.is_set (Year) then
validation.year_check (Year); -- returns nothing; emits maint message when |year= doesn't hold a 'year' value
end
if not utilities.is_set (Date) then
Date = Year; -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
if not utilities.is_set (Date) and utilities.is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate; -- promote PublicationDate to Date
PublicationDate = ''; -- unset, no longer needed
Date_origin = A:ORIGIN('PublicationDate'); -- save the name of the promoted parameter
else
Date_origin = A:ORIGIN('Year'); -- save the name of the promoted parameter
end
else
Date_origin = A:ORIGIN('Date'); -- not a promotion; name required for error messaging
end
if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation
--[[
Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where
we get the date used in the metadata.
Date validation supporting code is in Module:Citation/CS1/Date_validation
]]
local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], '');
if not utilities.is_set (DF) then
DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template
end
local ArchiveURL;
local ArchiveDate;
local ArchiveFormat = A['ArchiveFormat'];
local archive_url_timestamp; -- timestamp from wayback machine url
ArchiveURL, ArchiveDate, archive_url_timestamp = archive_url_check (A['ArchiveURL'], A['ArchiveDate'])
ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url');
ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN('ArchiveURL'), ArchiveDate); -- add error message when URL or ChapterURL == ArchiveURL
local AccessDate = A['AccessDate'];
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification
local DoiBroken = A['DoiBroken'];
local Embargo = A['Embargo'];
local anchor_year; -- used in the CITEREF identifier
do -- create defined block to contain local variables date_parameters_list, mismatch
local date_parameters_list = { -- AirDate has been promoted to Date so not necessary to check it
['access-date'] = {val = AccessDate, name = A:ORIGIN ('AccessDate')},
['archive-date'] = {val = ArchiveDate, name = A:ORIGIN ('ArchiveDate')},
['date'] = {val = Date, name = Date_origin},
['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')},
['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')},
['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')},
['year'] = {val = Year, name = A:ORIGIN ('Year')},
};
local error_list = {};
anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list);
if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed;
validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list);
end
if 0 == #error_list then -- error free dates only; 0 when error_list is empty
local modified = false; -- flag
if utilities.is_set (DF) then -- if we need to reformat dates
modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate
end
if true == validation.date_hyphen_to_dash (date_parameters_list) then -- convert hyphens to dashes where appropriate
modified = true;
utilities.set_message ('maint_date_format'); -- hyphens were converted so add maint category
end
-- for those wikis that can and want to have English date names translated to the local language; not supported at en.wiki
if cfg.date_name_auto_xlate_enable and validation.date_name_xlate (date_parameters_list, cfg.date_digit_auto_xlate_enable ) then
utilities.set_message ('maint_date_auto_xlated'); -- add maint cat
modified = true;
end
if modified then -- if the date_parameters_list values were modified
AccessDate = date_parameters_list['access-date'].val; -- overwrite date holding parameters with modified values
ArchiveDate = date_parameters_list['archive-date'].val;
Date = date_parameters_list['date'].val;
DoiBroken = date_parameters_list['doi-broken-date'].val;
PublicationDate = date_parameters_list['publication-date'].val;
end
if archive_url_timestamp and utilities.is_set (ArchiveDate) then
validation.archive_date_check (ArchiveDate, archive_url_timestamp, DF); -- does YYYYMMDD in archive_url_timestamp match date in ArchiveDate
end
else
utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}); -- add this error message
end
end -- end of do
if utilities.in_array (config.CitationClass, {'book', 'encyclopaedia'}) or -- {{cite book}}, {{cite encyclopedia}}; TODO: {{cite conference}} and others?
('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) or -- {{citation}} as an encylopedia citation
('citation' == config.CitationClass and not utilities.is_set (Periodical)) then -- {{citation}} as a book citation
if utilities.is_set (PublicationPlace) then
if not utilities.is_set (PublisherName) then
local date = COinS_date.rftdate and tonumber (COinS_date.rftdate:match ('%d%d%d%d')); -- get year portion of COinS date (because in Arabic numerals); convert string to number
if date and (1850 <= date) then -- location has no publisher; if date is 1850 or later
utilities.set_message ('maint_location_no_publisher'); -- add maint cat
end
else -- PublisherName has a value
if cfg.keywords_xlate['none'] == PublisherName then -- if that value is 'none' (only for book and encyclopedia citations)
PublisherName = ''; -- unset
end
end
end
end
local ID_list_t; -- sequence table of rendered identifiers
local ID_list_coins_t; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key
local Class = A['Class']; -- arxiv class identifier
local ID_support = {
{A['ASINTLD'], 'ASIN', 'err_asintld_missing_asin', A:ORIGIN ('ASINTLD')},
{DoiBroken, 'DOI', 'err_doibroken_missing_doi', A:ORIGIN ('DoiBroken')},
{Embargo, 'PMC', 'err_embargo_missing_pmc', A:ORIGIN ('Embargo')},
}
ID_list_t, ID_list_coins_t = identifiers.identifier_lists_get (args, {
DoiBroken = DoiBroken, -- for |doi=
ASINTLD = A['ASINTLD'], -- for |asin=
Embargo = Embargo, -- for |pmc=
Class = Class, -- for |arxiv=
CitationClass = config.CitationClass, -- for |arxiv=
Year=anchor_year, -- for |isbn=
}, ID_support);
for _, id in ipairs (ID_list_t) do -- search through the ID_list_t sequence looking for an ISBN identifier string
if id:find ('ISBN', 3, true) then -- plain find, start at index 3 ([[ISBN)
if 'citation' == config.CitationClass then -- catch ve/citoid malformed book cites in {{citation}} templates
if utilities.is_set (Periodical) then -- when a |work= alias is set
utilities.set_message ('maint_work_isbn'); -- add maint cat
break; -- and abandon
end
elseif ({['journal'] = true, ['magazine'] = true, ['news'] = true, ['web'] = true})[config.CitationClass] then
utilities.set_message ('maint_periodical_has_isbn'); -- add maint cat
break; -- and abandon
end
end
end
-- if 'citation' == config.CitationClass then -- catch ve/citoid malformed book cites in {{citation}} templates
-- for _, id in ipairs (ID_list_t) do -- search through the ID_list_t sequence looking for an ISBN identifier string
-- if id:find ('ISBN', 3, true) then -- plain find, start at index 3 ([[ISBN)
-- if utilities.is_set (Periodical) then -- when a |work= alias is set
-- utilities.set_message ('maint_work_isbn'); -- add maint cat
-- end
-- end
-- end
-- end
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite medrxiv}}, {{cite ssrn}}, before generation of COinS data.
if utilities.in_array (config.CitationClass, whitelist.preprint_template_list_t) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv=, |citeseerx=, |medrxiv=, |ssrn= required for their templates
if not (args[cfg.id_handlers[config.CitationClass:upper()].parameters[1]] or -- can't use ID_list_coins_t k/v table here because invalid parameters omitted
args[cfg.id_handlers[config.CitationClass:upper()].parameters[2]]) then -- which causes unexpected parameter missing error message
utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message
end
Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX', ['medrxiv'] = 'medRxiv', ['ssrn'] = 'Social Science Research Network'})[config.CitationClass];
end
-- Link the title of the work if no |url= was provided, but we have a |pmc= or a |doi= with |doi-access=free
if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead
if 'none' ~= cfg.keywords_xlate[auto_select] then -- if auto-linking not disabled
if identifiers.auto_link_urls[auto_select] then -- manual selection
URL = identifiers.auto_link_urls[auto_select]; -- set URL to be the same as identifier's external link
URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title=
elseif identifiers.auto_link_urls['pmc'] then -- auto-select PMC
URL = identifiers.auto_link_urls['pmc']; -- set URL to be the same as the PMC external link if not embargoed
URL_origin = cfg.id_handlers['PMC'].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title=
elseif identifiers.auto_link_urls['doi'] then -- auto-select DOI
URL = identifiers.auto_link_urls['doi'];
URL_origin = cfg.id_handlers['DOI'].parameters[1];
end
end
if utilities.is_set (URL) then -- set when using an identifier-created URL
if utilities.is_set (AccessDate) then -- |access-date= requires |url=; identifier-created URL is not |url=
utilities.set_message ('err_accessdate_missing_url'); -- add an error message
AccessDate = ''; -- unset
end
if utilities.is_set (ArchiveURL) then -- |archive-url= requires |url=; identifier-created URL is not |url=
utilities.set_message ('err_archive_missing_url'); -- add an error message
ArchiveURL = ''; -- unset
end
end
end
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
-- Test if citation has no title
if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode
utilities.set_message ('err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'});
end
if utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) and
utilities.in_array (config.CitationClass, {'journal', 'citation'}) and
(utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and
('journal' == Periodical_origin or 'script-journal' == ScriptPeriodical_origin) then -- special case for journal cites
Title = ''; -- set title to empty string
utilities.set_message ('maint_untitled'); -- add maint cat
end
if 'journal' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then
if is_page_art_num (((utilities.is_set (Page) and Page) or (utilities.is_set (Pages) and Pages)) or nil, ID_list_coins_t['DOI']) then -- does |page(s)= look like it holds an article number
utilities.set_message ('maint_page_art_num'); -- add maint cat
end
end
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
-- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that
-- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title
-- is the article title, and Chapter is a section within the article. So, we remap
local coins_chapter = Chapter; -- default assuming that remapping not required
local coins_title = Title; -- et tu
if 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then
if utilities.is_set (Chapter) and utilities.is_set (Title) and utilities.is_set (Periodical) then -- if all are used then
coins_chapter = Title; -- remap
coins_title = Periodical;
end
end
local coins_author = a; -- default for coins rft.au
if 0 < #c then -- but if contributor list
coins_author = c; -- use that instead
end
-- this is the function call to COinS()
local OCinSoutput = metadata.COinS({
['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata
['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS
['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic / accept-as-written markup
['Degree'] = Degree; -- cite thesis only
['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup
['PublicationPlace'] = PublicationPlace,
['Date'] = COinS_date.rftdate, -- COinS_date.* has correctly formatted date values if Date is valid;
['Season'] = COinS_date.rftssn,
['Quarter'] = COinS_date.rftquarter,
['Chron'] = COinS_date.rftchron,
['Series'] = Series,
['Volume'] = Volume,
['Issue'] = Issue,
['ArticleNumber'] = ArticleNumber,
['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links
['Edition'] = Edition,
['PublisherName'] = PublisherName or Newsgroup, -- any apostrophe markup already removed from PublisherName
['URL'] = first_set ({ChapterURL, URL}, 2),
['Authors'] = coins_author,
['ID_list'] = ID_list_coins_t,
['RawPage'] = this_page.prefixedText,
}, config.CitationClass);
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite medrxiv}}, and {{cite ssrn}} AFTER generation of COinS data.
if utilities.in_array (config.CitationClass, whitelist.preprint_template_list_t) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, medRxiv, or ssrn now unset so it isn't displayed
Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal
end
-- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text
if 'newsgroup' == config.CitationClass and utilities.is_set (Newsgroup) then
PublisherName = utilities.substitute (cfg.messages['newsgroup'], external_link( 'news:' .. Newsgroup, Newsgroup, Newsgroup_origin, nil ));
end
local Editors;
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list
local Contributors; -- assembled contributors name list
local contributor_etal = nil; -- must be intentionally initialized
local Translators; -- assembled translators name list
local translator_etal = nil; -- must be intentionally initialized
local t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
local Interviewers;
local interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters
local interviewer_etal = nil; -- must be intentionally initialized
-- Now perform various field substitutions.
-- We also add leading spaces and surrounding markup and punctuation to the
-- various parts of the citation, but only when they are non-nil.
do
local last_first_list;
local control = {
format = NameListStyle, -- empty string, '&', 'amp', 'and', or 'vanc'
maximum = nil, -- as if display-authors or display-editors not set
mode = Mode
};
do -- do editor name list first because the now unsupported coauthors used to modify control table
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayEditors'], A['DisplayEditors'], A:ORIGIN ('DisplayEditors'), #e);
control.maximum, editor_etal = get_display_names (display_names, #e, editor_etal, param);
Editors, EditorCount = list_people (control, e, editor_etal);
if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then
EditorCount = 2; -- spoof to display (eds.) annotation
end
end
do -- now do interviewers
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayInterviewers'], A['DisplayInterviewers'], A:ORIGIN ('DisplayInterviewers'), #interviewers_list);
control.maximum, interviewer_etal = get_display_names (display_names, #interviewers_list, interviewer_etal, param);
Interviewers = list_people (control, interviewers_list, interviewer_etal);
end
do -- now do translators
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayTranslators'], A['DisplayTranslators'], A:ORIGIN ('DisplayTranslators'), #t);
control.maximum, translator_etal = get_display_names (display_names, #t, translator_etal, param);
Translators = list_people (control, t, translator_etal);
end
do -- now do contributors
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayContributors'], A['DisplayContributors'], A:ORIGIN ('DisplayContributors'), #c);
control.maximum, contributor_etal = get_display_names (display_names, #c, contributor_etal, param);
Contributors = list_people (control, c, contributor_etal);
end
do -- now do authors
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayAuthors'], A['DisplayAuthors'], A:ORIGIN ('DisplayAuthors'), #a, author_etal);
control.maximum, author_etal = get_display_names (display_names, #a, author_etal, param);
last_first_list = list_people (control, a, author_etal);
if utilities.is_set (Authors) then
Authors, author_etal = name_has_etal (Authors, author_etal, false, 'authors'); -- find and remove variations on et al.
if author_etal then
Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter
end
else
Authors = last_first_list; -- either an author name list or an empty string
end
end -- end of do
if utilities.is_set (Authors) and utilities.is_set (Collaboration) then
Authors = utilities.substitute (cfg.messages['collaboration'], {Authors, Collaboration}); -- add collaboration after et al.
end
end
local ConferenceFormat = A['ConferenceFormat'];
local ConferenceURL = A['ConferenceURL'];
ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url');
Format = style_format (Format, URL, 'format', 'url');
-- special case for chapter format so no error message or cat when chapter not supported
if not (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then
ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url');
end
if not utilities.is_set (URL) then
if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for {{cite web}}, {{cite podcast}}, and {{cite mailing list}}
('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website=
if not url_was_archive_today then -- is <URL> empty/missing because it was a deprecated archive.today url
utilities.set_message ('err_cite_web_url'); -- no; emit an error message for an empty/ missing |url=
end
end
-- do we have |accessdate= without either |url= or |chapter-url=?
if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set;
utilities.set_message ('err_accessdate_missing_url');
AccessDate = '';
end
end
local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], '');
local OriginalURL
local OriginalURL_origin
local OriginalFormat
local OriginalAccess;
UrlStatus = UrlStatus:lower(); -- used later when assembling archived text
if utilities.is_set ( ArchiveURL ) then
if utilities.is_set (ChapterURL) then -- if chapter-url= is set apply archive url to it
OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text
OriginalURL_origin = ChapterURL_origin; -- name of |chapter-url= parameter for error messages
OriginalFormat = ChapterFormat; -- and original |chapter-format=
if 'live' ~= UrlStatus then
ChapterURL = ArchiveURL -- swap-in the archive's URL
ChapterURL_origin = A:ORIGIN('ArchiveURL') -- name of |archive-url= parameter for error messages
ChapterFormat = ArchiveFormat or ''; -- swap in archive's format
ChapterUrlAccess = nil; -- restricted access levels do not make sense for archived URLs
end
elseif utilities.is_set (URL) then
OriginalURL = URL; -- save copy of original source URL
OriginalURL_origin = URL_origin; -- name of URL parameter for error messages
OriginalFormat = Format; -- and original |format=
OriginalAccess = UrlAccess;
if 'live' ~= UrlStatus then -- if URL set then |archive-url= applies to it
URL = ArchiveURL -- swap-in the archive's URL
URL_origin = A:ORIGIN('ArchiveURL') -- name of archive URL parameter for error messages
Format = ArchiveFormat or ''; -- swap in archive's format
UrlAccess = nil; -- restricted access levels do not make sense for archived URLs
end
end
elseif utilities.is_set (UrlStatus) then -- if |url-status= is set when |archive-url= is not set
utilities.set_message ('maint_url_status'); -- add maint cat
end
if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or -- if any of the 'periodical' cites except encyclopedia
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then
local chap_param;
if utilities.is_set (Chapter) then -- get a parameter name from one of these chapter related meta-parameters
chap_param = A:ORIGIN ('Chapter')
elseif utilities.is_set (TransChapter) then
chap_param = A:ORIGIN ('TransChapter')
elseif utilities.is_set (ChapterURL) then
chap_param = A:ORIGIN ('ChapterURL')
elseif utilities.is_set (ScriptChapter) then
chap_param = ScriptChapter_origin;
else utilities.is_set (ChapterFormat)
chap_param = A:ORIGIN ('ChapterFormat')
end
if utilities.is_set (chap_param) then -- if we found one
utilities.set_message ('err_chapter_ignored', {chap_param}); -- add error message
Chapter = ''; -- and set them to empty string to be safe with concatenation
TransChapter = ''; -- for now, ignore linter warnings
ChapterURL = '';
ScriptChapter = '';
ChapterFormat = '';
end
else -- otherwise, format chapter / article title
local no_quotes = false; -- default assume that we will be quoting the chapter parameter value
if utilities.is_set (Contribution) and 0 < #c then -- if this is a contribution with contributor(s)
if utilities.in_array (Contribution:lower(), cfg.keywords_lists.contribution) then -- and a generic contribution title
no_quotes = true; -- then render it unquoted
end
end
Chapter = format_chapter_title (ScriptChapter, ScriptChapter_origin, Chapter, TransChapter, TransChapter_origin, ChapterURL, ChapterURL_origin, no_quotes, ChapterUrlAccess); -- Contribution is also in Chapter
if utilities.is_set (Chapter) then
Chapter = Chapter .. ChapterFormat ;
if 'map' == config.CitationClass and utilities.is_set (TitleType) then
Chapter = Chapter .. ' ' .. TitleType; -- map annotation here; not after title
end
Chapter = Chapter .. sepc .. ' ';
elseif utilities.is_set (ChapterFormat) then -- |chapter= not set but |chapter-format= is so ...
Chapter = ChapterFormat .. sepc .. ' '; -- ... ChapterFormat has error message, we want to see it
end
end
-- Format main title
local plain_title = false;
local accept_title;
Title, accept_title = utilities.has_accept_as_written (Title, true); -- remove accept-this-as-written markup when it wraps all of <Title>
if accept_title and ('' == Title) then -- only support forced empty for now "(())"
Title = cfg.messages['notitle']; -- replace by predefined "No title" message
-- TODO: utilities.set_message ( 'err_redundant_parameters', ...); -- issue proper error message instead of muting
ScriptTitle = ''; -- just mute for now
TransTitle = ''; -- just mute for now
plain_title = true; -- suppress text decoration for descriptive title
utilities.set_message ('maint_untitled'); -- add maint cat
end
if not accept_title then -- <Title> not wrapped in accept-as-written markup
if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title=
Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three
elseif not mw.ustring.find (Title, '%.%s*%a%.$') and -- end of title is not a 'dot-(optional space-)letter-dot' initialism ...
not mw.ustring.find (Title, '%s+%a%.$') then -- ...and not a 'space-letter-dot' initial (''Allium canadense'' L.)
Title = mw.ustring.gsub(Title, '%' .. sepc .. '$', ''); -- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters
end
if utilities.is_set (ArchiveURL) and is_archived_copy (Title) then
utilities.set_message ('maint_archived_copy'); -- add maintenance category before we modify the content of Title
end
if is_generic ('generic_titles', Title) then
utilities.set_message ('err_generic_title'); -- set an error message
end
end
if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'document', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or
('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article
Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from module provided quote marks
Title = utilities.wrap_style ('quoted-title', Title);
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle );
elseif plain_title or ('report' == config.CitationClass) then -- no styling for cite report and descriptive titles (otherwise same as above)
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title
else
Title = utilities.wrap_style ('italic-title', Title);
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-italic-title', TransTitle);
end
if utilities.is_set (TransTitle) then
if utilities.is_set (Title) then
TransTitle = " " .. TransTitle;
else
utilities.set_message ('err_trans_missing_title', {'title'});
end
end
if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs?
if utilities.is_set (TitleLink) and utilities.is_set (URL) then
utilities.set_message ('err_wikilink_in_url'); -- set an error message because we can't have both
TitleLink = ''; -- unset
end
if not utilities.is_set (TitleLink) and utilities.is_set (URL) then
Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format;
URL = ''; -- unset these because no longer needed
Format = ''; -- for now, ignore linter warning
elseif utilities.is_set (TitleLink) and not utilities.is_set (URL) then
local ws_url;
ws_url = wikisource_url_make (TitleLink); -- ignore ws_label return; not used here
if ws_url then
Title = external_link (ws_url, Title .. ' ', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title});
Title = Title .. TransTitle;
else
Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle;
end
else
local ws_url, ws_label, L; -- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink)
ws_url, ws_label, L = wikisource_url_make (Title:gsub('^[\'"]*(.-)[\'"]*$', '%1')); -- make ws URL from |title= interwiki link (strip italic or quote markup); link portion L becomes tooltip label
if ws_url then
Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup
Title = external_link (ws_url, Title .. ' ', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title});
Title = Title .. TransTitle;
else
Title = Title .. TransTitle;
end
end
else
Title = TransTitle;
end
if utilities.is_set (Place) then
Place = " " .. wrap_msg ('written', Place, use_lowercase) .. sepc .. " ";
end
local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL
if utilities.is_set (Conference) then
if utilities.is_set (ConferenceURL) then
Conference = external_link( ConferenceURL, Conference, ConferenceURL_origin, nil );
end
Conference = sepc .. " " .. Conference .. ConferenceFormat;
elseif utilities.is_set (ConferenceURL) then
Conference = sepc .. " " .. external_link( ConferenceURL, nil, ConferenceURL_origin, nil );
end
local Position = '';
if not utilities.is_set (Position) then
local Minutes = A['Minutes'];
local Time = A['Time'];
if utilities.is_set (Minutes) then
if utilities.is_set (Time) then --TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'time')});
end
Position = utilities.substitute (cfg.messages.minutes, Minutes);
else
if utilities.is_set (Time) then
local TimeCaption = A['TimeCaption']
if not utilities.is_set (TimeCaption) then
TimeCaption = cs2_lower(cfg.messages['event']);
end
Position = " " .. TimeCaption .. " " .. Time;
end
end
else
Position = " " .. Position;
At = '';
end
Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase);
At = utilities.is_set (At) and (sepc .. " " .. At) or "";
Position = utilities.is_set (Position) and (sepc .. " " .. Position) or "";
if config.CitationClass == 'map' then
local Sections = A['Sections']; -- Section (singular) is an alias of Chapter so set earlier
local Inset = A['Inset'];
if utilities.is_set ( Inset ) then
Inset = sepc .. " " .. wrap_msg ('inset', Inset, use_lowercase);
end
if utilities.is_set ( Sections ) then
Section = sepc .. " " .. wrap_msg ('sections', Sections, use_lowercase);
elseif utilities.is_set ( Section ) then
Section = sepc .. " " .. wrap_msg ('section', Section, use_lowercase);
end
At = At .. Inset .. Section;
end
local Others = A['Others'];
if utilities.is_set (Others) and 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor=
if config.CitationClass == "AV-media-notes"
or config.CitationClass == "audio-visual" then -- special maint for AV/M which has a lot of 'false' positives right now
utilities.set_message ('maint_others_avm')
else
utilities.set_message ('maint_others');
end
end
Others = utilities.is_set (Others) and (sepc .. " " .. Others) or "";
if utilities.is_set (Translators) then
Others = safe_join ({sepc .. ' ', wrap_msg ('translated', Translators, use_lowercase), Others}, sepc);
end
if utilities.is_set (Interviewers) then
Others = safe_join ({sepc .. ' ', wrap_msg ('interview', Interviewers, use_lowercase), Others}, sepc);
end
local TitleNote = A['TitleNote'];
TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or "";
if utilities.is_set (Edition) then
if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn.
utilities.set_message ('err_extra_text_edition'); -- add error message
end
Edition = " " .. wrap_msg ('edition', Edition);
else
Edition = '';
end
Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum
local Agency = A['Agency'] or ''; -- |agency= is supported by {{cite magazine}}, {{cite news}}, {{cite press release}}, {{cite web}}, and certain {{citation}} templates
if utilities.is_set (Agency) then -- this testing done here because {{citation}} supports 'news' citations
if utilities.in_array (config.CitationClass, {'magazine', 'news', 'pressrelease', 'web'}) or ('citation' == config.CitationClass and utilities.in_array (Periodical_origin, {"magazine", "newspaper", "work"})) then
Agency = wrap_msg ('agency', {sepc, Agency}); -- format for rendering
else
Agency = ''; -- unset; not supported
utilities.set_message ('err_parameter_ignored', {'agency'}); -- add error message
end
end
Volume = format_volume_issue (Volume, Issue, ArticleNumber, config.CitationClass, Periodical_origin, sepc, use_lowercase);
if utilities.is_set (AccessDate) then
local retrv_text = " " .. cfg.messages['retrieved'];
AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format
retrv_text = cs2_lower(retrv_text); -- if mode is cs2, lower case
AccessDate = utilities.substitute (retrv_text, AccessDate); -- add retrieved text
AccessDate = utilities.substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates
end
if utilities.is_set (ID) then ID = sepc .. " " .. ID; end
local Docket = A['Docket'];
if "thesis" == config.CitationClass and utilities.is_set (Docket) then
ID = sepc .. " Docket " .. Docket .. ID;
end
if "report" == config.CitationClass and utilities.is_set (Docket) then -- for cite report when |docket= is set
ID = sepc .. ' ' .. Docket; -- overwrite ID even if |id= is set
end
if utilities.is_set (URL) then
URL = " " .. external_link( URL, nil, URL_origin, UrlAccess );
end
-- We check length of PostScript here because it will have been nuked by
-- the quote parameters. We'd otherwise emit a message even if there wasn't
-- a displayed postscript.
-- TODO: Should the max size (1) be configurable?
-- TODO: Should we check a specific pattern?
if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then
utilities.set_message ('maint_postscript')
end
local Archived;
if utilities.is_set (ArchiveURL) then
if not utilities.is_set (ArchiveDate) then -- ArchiveURL set but ArchiveDate not set
utilities.set_message ('err_archive_missing_date'); -- emit an error message
ArchiveURL = ''; -- empty string for concatenation
ArchiveDate = ''; -- empty string for concatenation
end
else
if utilities.is_set (ArchiveDate) then -- ArchiveURL not set but ArchiveDate is set
utilities.set_message ('err_archive_date_missing_url'); -- emit an error message
ArchiveURL = ''; -- empty string for concatenation
ArchiveDate = ''; -- empty string for concatenation
end
end
if utilities.is_set (ArchiveURL) then
if "live" == UrlStatus then
if utilities.is_set (ArchiveDate) then
Archived = sepc .. ' ' .. utilities.substitute ( cfg.messages['archived-live'],
{ external_link( ArchiveURL, cs2_lower(cfg.messages['archived']), A:ORIGIN('ArchiveURL'), nil) .. ArchiveFormat, ArchiveDate } );
else
Archived = '';
end
if not utilities.is_set (OriginalURL) then
utilities.set_message ('err_archive_missing_url');
Archived = ''; -- empty string for concatenation
end
elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown'
if utilities.in_array (UrlStatus, {'unfit', 'usurped', 'bot: unknown'}) then
Archived = sepc .. ' ' .. utilities.substitute ( cs2_lower(cfg.messages['archived-unfit']), ArchiveDate);
if 'bot: unknown' == UrlStatus then
utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added
else
utilities.add_prop_cat ('unfit'); -- and add a category if not already added
end
else -- UrlStatus is empty, 'dead'
if utilities.is_set (ArchiveDate) then
Archived = sepc .. ' ' .. utilities.substitute ( cs2_lower(cfg.messages['archived-dead']),
{ external_link( OriginalURL, cfg.messages['original'], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } );
else
Archived = ''; -- unset for concatenation
end
end
else -- OriginalUrl not set
utilities.set_message ('err_archive_missing_url');
Archived = ''; -- empty string for concatenation
end
elseif utilities.is_set (ArchiveFormat) then
Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message
else
Archived = '';
end
local TranscriptURL = A['TranscriptURL']
local TranscriptFormat = A['TranscriptFormat'];
TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl');
local Transcript = A['Transcript'];
local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL
if utilities.is_set (Transcript) then
if utilities.is_set (TranscriptURL) then
Transcript = external_link( TranscriptURL, Transcript, TranscriptURL_origin, nil );
end
Transcript = sepc .. ' ' .. Transcript .. TranscriptFormat;
elseif utilities.is_set (TranscriptURL) then
Transcript = external_link( TranscriptURL, nil, TranscriptURL_origin, nil );
end
local Publisher;
if utilities.is_set (PublicationDate) then
PublicationDate = wrap_msg ('published', PublicationDate);
end
if utilities.is_set (PublisherName) then
if utilities.is_set (PublicationPlace) then
Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate;
else
Publisher = sepc .. " " .. PublisherName .. PublicationDate;
end
elseif utilities.is_set (PublicationPlace) then
Publisher= sepc .. " " .. PublicationPlace .. PublicationDate;
else
Publisher = PublicationDate;
end
-- Several of the above rely upon detecting this as nil, so do it last.
if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then
if utilities.is_set (Title) or utilities.is_set (TitleNote) then
Periodical = sepc .. " " .. format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);
else
Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);
end
end
local Language = A['Language'];
if utilities.is_set (Language) then
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc.
else
Language=''; -- language not specified so make sure this is an empty string;
--[[ TODO: need to extract the wrap_msg from language_parameter
so that we can solve parentheses bunching problem with Format/Language/TitleType
]]
end
--[[
Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that
the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).
]]
if "speech" == config.CitationClass then -- cite speech only
TitleNote = TitleType; -- move TitleType to TitleNote so that it renders ahead of |event=
TitleType = ''; -- and unset
if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter
if utilities.is_set (Conference) then -- and if |event= is set
Conference = Conference .. sepc .. " "; -- then add appropriate punctuation to the end of the Conference variable before rendering
end
end
end
-- Piece all bits together at last. Here, all should be non-nil.
-- We build things this way because it is more efficient in LUA
-- not to keep reassigning to the same string variable over and over.
local tcommon;
local tcommon2; -- used for book cite when |contributor= is set
local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At;
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (Periodical) then -- special cases for book cites
if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc.
tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2
tcommon2 = safe_join ({TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc);
else
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc);
end
elseif 'map' == config.CitationClass then -- special cases for cite map
if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter
tcommon = safe_join ({Title, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc);
elseif utilities.is_set (Periodical) then -- map in a periodical
tcommon = safe_join ({Title, TitleType, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc);
else -- a sheet or stand-alone map
tcommon = safe_join ({Title, TitleType, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc);
end
elseif 'episode' == config.CitationClass then -- special case for cite episode
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc);
else -- all other CS1 templates
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc);
end
if #ID_list_t > 0 then
ID_list_t = safe_join( { sepc .. " ", table.concat( ID_list_t, sepc .. " " ), ID }, sepc );
else
ID_list_t = ID;
end
local Via = A['Via'];
Via = utilities.is_set (Via) and wrap_msg ('via', Via) or '';
local idcommon;
if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript
idcommon = safe_join( { ID_list_t, URL, Archived, Transcript, AccessDate, Via, Quote }, sepc );
else
idcommon = safe_join( { ID_list_t, URL, Archived, AccessDate, Via, Quote }, sepc );
end
local text;
-- local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At;
local OrigDate = A['OrigDate'];
OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or '';
if utilities.is_set (Date) then
if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set
Date = " (" .. Date .. ")" .. OrigDate .. sepc .. " "; -- in parentheses
else -- neither of authors and editors set
if (string.sub(tcommon, -1, -1) == sepc) then -- if the last character of tcommon is sepc
Date = " " .. Date .. OrigDate; -- Date does not begin with sepc
else
Date = sepc .. " " .. Date .. OrigDate; -- Date begins with sepc
end
end
end
if utilities.is_set (Authors) then
if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Authors termination
Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space
end
if utilities.is_set (Editors) then
local in_text = '';
local post_text;
if utilities.is_set (Chapter) and 0 == #c then
in_text = cfg.messages['in'] .. ' ';
in_text = cs2_lower(in_text); -- lowercase for cs2
end
if EditorCount <= 1 then
post_text = ' (' .. cfg.messages['editor'] .. ')'; -- be consistent with no-author, no-date case
else
post_text = ' (' .. cfg.messages['editors'] .. ')';
end
Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space
end
if utilities.is_set (Contributors) then -- book cite and we're citing the intro, preface, etc.
local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' ';
by_text = cs2_lower(by_text); -- lowercase for cs2
Authors = by_text .. Authors; -- author follows title so tweak it here
if utilities.is_set (Editors) and utilities.is_set (Date) then -- when Editors make sure that Authors gets terminated
Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space
end
if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Contributors termination
Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space
end
text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc );
else
text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc );
end
elseif utilities.is_set (Editors) then
if utilities.is_set (Date) then
if EditorCount <= 1 then
Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editor'];
else
Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editors'];
end
else
if EditorCount <= 1 then
Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "
else
Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " "
end
end
text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc );
else
if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then
text = safe_join( {Chapter, Place, tcommon, pgtext, Date, idcommon}, sepc );
else
text = safe_join( {Chapter, Place, tcommon, Date, pgtext, idcommon}, sepc );
end
end
if utilities.is_set (PostScript) and PostScript ~= sepc then
text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc.
if '.' == sepc then -- remove final seperator if present
text = text:gsub ('%' .. sepc .. '$', ''); -- dot must be escaped here
else
text = mw.ustring.gsub (text, sepc .. '$', ''); -- using ustring for non-dot sepc (likely a non-Latin character)
end
end
text = safe_join( {text, PostScript}, sepc );
-- Now enclose the whole thing in a <cite> element
local options_t = {};
options_t.class = cite_class_attribute_make (config.CitationClass, Mode);
local Ref = is_valid_parameter_value (A['Ref'], A:ORIGIN('Ref'), cfg.keywords_lists['ref'], nil, true); -- nil when |ref=harv; A['Ref'] else
if 'none' ~= cfg.keywords_xlate[(Ref and Ref:lower()) or ''] then
local namelist_t = {}; -- holds selected contributor, author, editor name list
local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation
if #c > 0 then -- if there is a contributor list
namelist_t = c; -- select it
elseif #a > 0 then -- or an author list
namelist_t = a;
elseif #e > 0 then -- or an editor list
namelist_t = e;
end
local citeref_id;
if #namelist_t > 0 then -- if there are names in namelist_t
citeref_id = make_citeref_id (namelist_t, year); -- go make the CITEREF anchor
if mw.uri.anchorEncode (citeref_id) == ((Ref and mw.uri.anchorEncode (Ref)) or '') then -- Ref may already be encoded (by {{sfnref}}) so citeref_id must be encoded before comparison
utilities.set_message ('maint_ref_duplicates_default');
end
else
citeref_id = ''; -- unset
end
options_t.id = Ref or citeref_id;
end
if string.len (text:gsub('%b<>', '')) <= 2 then -- remove html and html-like tags; then get length of what remains;
z.error_cats_t = {}; -- blank the categories list
z.error_msgs_t = {}; -- blank the error messages list
OCinSoutput = nil; -- blank the metadata string
text = ''; -- blank the the citation
utilities.set_message ('err_empty_citation'); -- set empty citation message and category
end
local render_t = {}; -- here we collect the final bits for concatenation into the rendered citation
if is_preview_mode and (0 ~= #z.error_msgs_t or 0 ~= #z.maint_cats_t) then -- when in preview mode
if not utilities.is_set (options_t.id) then -- and when this template has not created an anchor ID
math.randomseed (tonumber (mw.getLanguage ('en'):formatDate ('U')) * 10000 + os.clock() * 10000);
options_t.id = 'CITEREF_temp_preview_id_' .. math.random (100000, 999999); -- create temporary anchor ID for preview mode
end
end
if utilities.is_set (options_t.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags
options_t.id = mw.uri.anchorEncode(options_t.id); -- do this here; also used when adding preview warning messages
table.insert (render_t, utilities.substitute (cfg.presentation['cite-id'], {options_t.id, mw.text.nowiki(options_t.class), text})); -- when |ref= is set or when there is a namelist
else
table.insert (render_t, utilities.substitute (cfg.presentation['cite'], {mw.text.nowiki(options_t.class), text})); -- when |ref=none or when namelist_t empty and |ref= is missing or is empty
end
if OCinSoutput then -- blanked when citation is 'empty' so don't bother to add boilerplate metadata span
table.insert (render_t, utilities.substitute (cfg.presentation['ocins'], OCinSoutput)); -- format and append metadata to the citation
end
local template_name = cfg.citation_class_map_t[config.CitationClass];
local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]';
local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: ';
if 0 ~= #z.error_msgs_t then
mw.addWarning (utilities.substitute (cfg.messages.warning_msg_e, {template_link, options_t.id}));
table.insert (render_t, ' '); -- insert a space between citation and its error messages
table.sort (z.error_msgs_t); -- sort the error messages list; sorting includes wrapping <span> and <code> tags; hidden-error sorts ahead of visible-error
local hidden = true; -- presume that the only error messages emited by this template are hidden
for _, v in ipairs (z.error_msgs_t) do -- spin through the list of error messages
if v:find ('cs1-visible-error', 1, true) then -- look for the visible error class name
hidden = false; -- found one; so don't hide the error message prefix
break; -- and done because no need to look further
end
end
z.error_msgs_t[1] = table.concat ({utilities.error_comment (msg_prefix, hidden), z.error_msgs_t[1]}); -- add error message prefix to first error message to prevent extraneous punctuation
table.insert (render_t, table.concat (z.error_msgs_t, '; ')); -- make a big string of error messages and add it to the rendering
end
if 0 ~= #z.maint_cats_t then
mw.addWarning (utilities.substitute (cfg.messages.warning_msg_m, {template_link, options_t.id}));
table.sort (z.maint_cats_t); -- sort the maintenance messages list
local maint_msgs_t = {}; -- here we collect all of the maint messages
if 0 == #z.error_msgs_t then -- if no error messages
table.insert (maint_msgs_t, msg_prefix); -- insert message prefix in maint message livery
end
for _, v in ipairs( z.maint_cats_t ) do -- append maintenance categories
table.insert (maint_msgs_t, -- assemble new maint message and add it to the maint_msgs_t table
table.concat ({v, ' (', utilities.substitute (cfg.messages[':cat wikilink'], v), ')'})
);
end
table.insert (render_t, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs_t, ' '))); -- wrap the group of maint messages with proper presentation and save
end
if not no_tracking_cats then
local sort_key;
local cat_wikilink = 'cat wikilink';
if cfg.enable_sort_keys then -- when namespace sort keys enabled
local namespace_number = mw.title.getCurrentTitle().namespace; -- get namespace number for this wikitext
sort_key = (0 ~= namespace_number and (cfg.name_space_sort_keys[namespace_number] or cfg.name_space_sort_keys.other)) or nil; -- get sort key character; nil for mainspace
cat_wikilink = (not sort_key and 'cat wikilink') or 'cat wikilink sk'; -- make <cfg.messages> key
end
for _, v in ipairs (z.error_cats_t) do -- append error categories
table.insert (render_t, utilities.substitute (cfg.messages[cat_wikilink], {v, sort_key}));
end
if cfg.id_limits_data_load_fail then -- boolean true when load failed
utilities.set_message ('maint_id_limit_load_fail'); -- done here because this maint cat emits no message
end
for _, v in ipairs (z.maint_cats_t) do -- append maintenance categories
table.insert (render_t, utilities.substitute (cfg.messages[cat_wikilink], {v, sort_key}));
end
for _, v in ipairs (z.prop_cats_t) do -- append properties categories
table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); -- no sort keys
end
end
return table.concat (render_t); -- make a big string and done
end
--[[--------------------------< V A L I D A T E >--------------------------------------------------------------
Looks for a parameter's name in one of several whitelists.
Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
local function validate (name, cite_class, empty)
local enum_name; -- parameter name with enumerator (if any) replaced with '#'
local state;
local function state_test () -- local function to do testing of state values; operates on the upvalues <state> and <name>
if true == state then return true; end -- valid actively supported parameter
if false == state then
if empty then return nil; end -- empty deprecated parameters are treated as unknowns
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
if 'tracked' == state then
local base_name = name:gsub ('%d', ''); -- strip enumerators from parameter names that have them to get the base name
utilities.add_prop_cat ('tracked-param', {base_name}, base_name); -- add a properties category; <base_name> modifies <key>
return true;
end
return nil;
end
if 'string' ~= type (name) or name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted; positional params are 'number' type; not supported
return nil;
end
-- replace enumerator digit(s) with # (|last25= becomes |last#=) (mw.ustring because non-Western 'local' digits)
enum_name = mw.ustring.gsub (name, '%d+$', '#'); -- where enumerator is last charaters in parameter name (these to protect |s2cid=)
enum_name = mw.ustring.gsub (enum_name, '%d+([%-l])', '#%1'); -- where enumerator is in the middle of the parameter name; |author#link= is the oddity
if 'document' == cite_class then -- special case for {{cite document}}
state = whitelist.document_parameters_t[enum_name]; -- this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
return false;
end
if utilities.in_array (cite_class, whitelist.preprint_template_list_t) then -- limited parameter sets allowed for these templates
state = whitelist.limited_parameters_t[enum_name]; -- this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
state = whitelist.preprint_arguments_t[cite_class][name]; -- look in the parameter-list for the template identified by cite_class
if true == state_test () then return true; end
return false; -- not supported because not found or name is set to nil
end -- end limited parameter-set templates
if utilities.in_array (cite_class, whitelist.unique_param_template_list_t) then -- template-specific parameters for templates that accept parameters from the basic argument list
state = whitelist.unique_arguments_t[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class
if true == state_test () then return true; end
end -- if here, fall into general validation
state = whitelist.common_parameters_t[enum_name]; -- all other templates; all normal parameters allowed; this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
return false; -- not supported because not found or name is set to nil
end
--[=[-------------------------< I N T E R _ W I K I _ C H E C K >----------------------------------------------
check <value> for inter-language interwiki-link markup. <prefix> must be a MediaWiki-recognized language
code. when these values have the form (without leading colon):
[[<prefix>:link|label]] return label as plain-text
[[<prefix>:link]] return <prefix>:link as plain-text
return value as is else
]=]
local function inter_wiki_check (parameter, value)
local prefix = value:match ('%[%[(%a+):'); -- get an interwiki prefix if one exists
local _;
if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so
utilities.set_message ('err_bad_paramlink', parameter); -- emit an error message
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink
end
return value;
end
--[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------
Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal
sign, compare the alphanumeric string to the list of cs1|2 parameters. If found, then the string is possibly a
parameter that is missing its pipe. There are two tests made:
{{cite ... |title=Title access-date=2016-03-17}} -- the first parameter has a value and whitespace separates that value from the missing pipe parameter name
{{cite ... |title=access-date=2016-03-17}} -- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki)
cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc. To prevent false positives XML/HTML
tags are removed before the search.
If a missing pipe is detected, this function adds the missing pipe maintenance category.
]]
local function missing_pipe_check (parameter, value)
local capture;
value = value:gsub ('%b<>', ''); -- remove XML/HTML tags because attributes: class=, title=, etc.
capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes
if capture and validate (capture) then -- if the capture is a valid parameter name
utilities.set_message ('err_missing_pipe', parameter);
end
end
--[[--------------------------< H A S _ E X T R A N E O U S _ P U N C T >--------------------------------------
look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked
]]
local function has_extraneous_punc (param, value)
if 'number' == type (param) then
return;
end
param = param:gsub ('%d+', '#'); -- enumerated name-list mask params allow terminal punct; normalize
if cfg.punct_skip[param] then
return; -- parameter name found in the skip table so done
end
if value:match ('[,;:]$') then
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
if value:match ('^=') then -- sometimes an extraneous '=' character appears ...
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
end
--[[--------------------------< H A S _ T W L _ U R L >--------------------------------------------------------
look for The Wikipedia Library urls in url-holding parameters. TWL urls are accessible only for readers who are
active extended confirmed Wikipedia editors. This function sets an error message when such urls are discovered
and when appropriate, sets the |<param>-url-access=subscription. returns nothing.
looks for: '.wikipedialibrary.idm.oclc.org'
]]
local function has_twl_url (url_params_t, cite_args_t)
local url_error_t = {}; -- sequence of url-holding parameters that have a TWL url
for param, value in pairs (url_params_t) do
if value:find ('%.wikipedialibrary%.idm%.oclc%.org') then -- has the TWL base url?
table.insert (url_error_t, param); -- add parameter name to the error list
end
end
if 0 ~= #url_error_t then -- non-zero when there are errors
table.sort (url_error_t); -- sor for error messaging
for i, param in ipairs (url_error_t) do
if cfg.url_access_map_t[param] then -- if <param> has a matching -access parameter
cite_args_t[cfg.url_access_map_t[param]] = cfg.keywords_xlate.subscription; -- set |<param>-url-access=subscription
end
url_error_t[i] = utilities.wrap_style ('parameter', param); -- make the parameter pretty for error message
end
utilities.set_message ('err_param_has_twl_url', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message
end
end
--[[--------------------------< M I S C _ U R L _ D E T E C T >------------------------------------------------
look for miscellaneous urls that might be converted to, or are duplicates of, identifiers.
]]
local misc_url_patterns_t = {
'idm%.oclc%.org', -- but not wikipedialibrary.idm.oclc.org; has_twl_url()
'https?://citeseerx?%.ist%.psu%.edu/', -- simplified so we catch all citeseer and citeseerx urls except ~/document/... (the 'new' form)
}
local ignore_patterns_t = {
'wikipedialibrary.idm.oclc.org', -- handled by has_twl_url()
'https?://citeseerx?%.ist%.psu%.edu/document', -- 'new'-form citeseerx urls that mostly work; ignore for now
}
local function misc_url_detect (url_params_t)
local ignore_flag = false;
for _, value in pairs (url_params_t) do
for _, ignore_pattern in ipairs (ignore_patterns_t) do
if value:find (ignore_pattern) then -- matches this ignore_pattern?
ignore_flag = true; -- found a pattern to ignore
break; --
end
end
if not ignore_flag then -- if ignore_flag is set then don't bother to test this url <value>
for _, misc_pattern in ipairs (misc_url_patterns_t) do
if value:find (misc_pattern) then -- matches this misc_pattern?
utilities.set_message ('maint_misc_url'); -- found one; set the message
return; -- and done; no need to test other <value>s
end
end
end
ignore_flag = false; -- reset
end
end
--[[--------------------------< H A S _ E X T R A N E O U S _ U R L >------------------------------------------
look for extraneous url parameter values; parameters listed in skip table are not checked
]]
local function has_extraneous_url (non_url_param_t)
local url_error_t = {};
check_for_url (non_url_param_t, url_error_t); -- extraneous url check
if 0 ~= #url_error_t then -- non-zero when there are errors
table.sort (url_error_t);
utilities.set_message ('err_param_has_ext_link', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message
end
end
--[[--------------------------< _ C I T A T I O N >------------------------------------------------------------
Module entry point
frame – from template call (citation()); may be nil when called from another module
args_t – table of all cs1|2 parameters in the template (the parent frame)
config_t – table of template-supplied parameter (the #invoke frame)
]]
local function _citation (frame, args_t, config_t) -- save a copy in case we need to display an error message in preview mode
if not frame then
frame = mw.getCurrentFrame(); -- if called from another module, get a frame for frame-provided functions
end
-- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here)
local sandbox = ((config_t.SandboxPath and '' ~= config_t.SandboxPath) and config_t.SandboxPath) or '/sandbox'; -- sandbox path from {{#invoke:Citation/CS1/sandbox|citation|SandboxPath=/...}}
is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module?
sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else
cfg = mw.loadData ('Module:Citation/CS1/Configuration' .. sandbox); -- load sandbox versions of support modules when {{#invoke:Citation/CS1/sandbox|...}}; live modules else
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist' .. sandbox);
utilities = require ('Module:Citation/CS1/Utilities' .. sandbox);
validation = require ('Module:Citation/CS1/Date_validation' .. sandbox);
identifiers = require ('Module:Citation/CS1/Identifiers' .. sandbox);
metadata = require ('Module:Citation/CS1/COinS' .. sandbox);
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables
identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module
validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module
metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities
local cite_args_t = {}; -- because args_t is the parent (template) frame args (which cannot be modified); params and their values will be placed here
is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}'));
local suggestions = {}; -- table where we store suggestions if we need to loadData them
local error_text; -- used as a flag
local capture; -- the single supported capture when matching unknown parameters using patterns
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing
for k, v in pairs (args_t) do -- get parameters from the parent (template) frame
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string
if v ~= '' then
if cfg.enum_needs_xlation and 'string' == type (k) then -- for wikis that set date_names['local_digits'] to non-western digits
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- translate 'local' digits enumerators to Western 0-9
end
if not validate( k, config_t.CitationClass ) then
if type (k) ~= 'string' then -- exclude empty numbered parameters
if v:match("%S+") ~= nil then
error_text = utilities.set_message ('err_text_ignored', {v});
end
elseif validate (k:lower(), config_t.CitationClass) then
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter
else
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' .. sandbox); --load sandbox version of suggestion module when {{#invoke:Citation/CS1/sandbox|...}}; live module else
end
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
capture = k:match (pattern); -- the whole match if no capture in pattern else the capture if a match
if capture then -- if the pattern matches
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
if validate (param, config_t.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists)
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message
else
error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template
v = ''; -- unset
end
end
end
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion?
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config_t.CitationClass) then
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]});
else
utilities.set_message ('err_parameter_ignored', {k});
v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists)
end
end
end
end
cite_args_t[k] = v; -- save this parameter and its value
elseif not utilities.is_set (v) then -- for empty parameters
if not validate (k, config_t.CitationClass, true) then -- is this empty parameter a valid parameter
k = ('' == k) and cfg.err_msg_supl.empty_str or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text
table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list
end
end
end
if 0 ~= #empty_unknowns then -- create empty unknown error message
utilities.set_message ('err_param_unknown_empty', {
1 == #empty_unknowns and '' or 's',
utilities.make_sep_list (#empty_unknowns, empty_unknowns)
});
end
local non_url_param_t = {}; -- table of parameters and values that are not url-holding parameters
local url_param_t = {}; -- table of url-holding paramters and their values
for k, v in pairs (cite_args_t) do
if 'string' == type (k) then -- don't evaluate positional parameters
has_invisible_chars (k, v); -- look for invisible characters
end
has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values
missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe?
cite_args_t[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label
if 'string' == type (k) then -- when parameter k is not positional
if not cfg.url_skip[k] then -- and not in url skip table
non_url_param_t[k] = v; -- make a parameter/value list for extraneous url check
else -- and is in url skip table (a url-holding parameter)
url_param_t[k] = v; -- make a parameter/value list to check for values that are The Wikipedia Library url
end
end
end
if cfg.suppress_archive_today_urls then
has_archive_today_url (cite_args_t); -- look for and suppress archive.today urls and dependent parameters for all templates
end
has_extraneous_url (non_url_param_t); -- look for url in parameter values where a url does not belong
has_twl_url (url_param_t, cite_args_t); -- look for url-holding parameters that hold a The Wikipedia Library url
misc_url_detect (url_param_t); -- look for url-holding parameters that hold certain miscellaneous urls
return table.concat ({
frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1' .. sandbox .. '/styles.css'}),
citation0 (config_t, cite_args_t)
});
end
--[[--------------------------< C I T A T I O N >--------------------------------------------------------------
Template entry point
]]
local function citation (frame)
local config_t = {}; -- table to store parameters from the module {{#invoke:}}
local args_t = frame:getParent().args; -- get template's preset parameters
for k, v in pairs (frame.args) do -- get parameters from the {{#invoke}} frame
config_t[k] = v;
-- args_t[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep?
end
return _citation (frame, args_t, config_t)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
citation = citation, -- template entry point
_citation = _citation, -- module entry point
}
mzkfjlhyhvftcb93lj0ik7zu7t1myhw
9002
8255
2026-08-22T12:06:24Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1]]
8255
Scribunto
text/plain
require ('strict');
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
each of these counts against the Lua upvalue limit
]]
local validation; -- functions in Module:Citation/CS1/Date_validation
local utilities; -- functions in Module:Citation/CS1/Utilities
local z = {}; -- table of tables in Module:Citation/CS1/Utilities
local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers
local metadata; -- functions in Module:Citation/CS1/COinS
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
--[[------------------< P A G E S C O P E V A R I A B L E S >---------------
declare variables here that have page-wide scope that are not brought in from
other modules; that are created here and used here
]]
local added_deprecated_cat; -- boolean flag so that the category is added only once
local added_vanc_errs; -- boolean flag so we only emit one Vancouver error / category
local added_generic_name_errs; -- boolean flag so we only emit one generic name error / category and stop testing names once an error is encountered
local added_numeric_name_errs; -- boolean flag so we only emit one numeric name error / category and stop testing names once an error is encountered
local added_numeric_name_maint; -- boolean flag so we only emit one numeric name maint category and stop testing names once a category has been emitted
local is_preview_mode; -- true when article is in preview mode; false when using 'Preview page with this template' (previewing the module)
local is_sandbox; -- true when using sandbox modules to render citation
local url_was_archive_today; -- boolean flag set to true when has_archive_today_url() has unset |url= because it held a deprecated archive.today url
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------
Locates and returns the first set value in a table of values where the order established in the table,
left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set.
This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs
version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate
the for-loop before it reached the actual end of the list.
]]
local function first_set (list, count)
local i = 1;
while i <= count do -- loop through all items in list
if utilities.is_set( list[i] ) then
return list[i]; -- return the first set list member
end
i = i + 1; -- point to next
end
end
--[[--------------------------< A D D _ V A N C _ E R R O R >----------------------------------------------------
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist.
To prevent duplication, added_vanc_errs is nil until an error message is emitted.
added_vanc_errs is a Boolean declared in page scope variables above
]]
local function add_vanc_error (source, position)
if added_vanc_errs then return end
added_vanc_errs = true; -- note that we've added this category
utilities.set_message ('err_vancouver', {source, position});
end
--[[--------------------------< I S _ S C H E M E >------------------------------------------------------------
does this thing that purports to be a URI scheme seem to be a valid scheme? The scheme is checked to see if it
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:
Scheme names consist of a sequence of characters beginning with a
letter and followed by any combination of letters, digits, plus
("+"), period ("."), or hyphen ("-").
returns true if it does, else false
]]
local function is_scheme (scheme)
return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern
end
--[=[-------------------------< I S _ D O M A I N _ N A M E >--------------------------------------------------
Does this thing that purports to be a domain name seem to be a valid domain name?
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5
BNF defined here: https://tools.ietf.org/html/rfc4234
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;
see also [[Single-letter second-level domain]]
list of TLDs: https://www.iana.org/domains/root/db
RFC 952 (modified by RFC 1123) requires the first and last character of a hostname to be a letter or a digit
(see http://tools.ietf.org/html/rfc952 §GRAMMATICAL HOST TABLE SPECIFICATION §§B. Lexical grammar <name>; see
http://tools.ietf.org/html/rfc1123#section-2). Between the first and last characters the name may use letters,
digits, and the hyphen.
Also allowed are IPv4 addresses. IPv6 not supported
domain is expected to be stripped of any path so that the last character in the last character of the TLD. tld
is two or more alpha characters. Any preceding '//' (from splitting a URL with a scheme) will be stripped
here. Perhaps not necessary but retained in case it is necessary for IPv4 dot decimal.
There are several tests:
the first character of the whole domain name including subdomains must be a letter or a digit
internationalized domain name (ASCII characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the TLD) see https://tools.ietf.org/html/rfc3490
single-letter/digit second-level domains in the .org, .cash, and .today TLDs
q, x, and z SL domains in the .com TLD
i and q SL domains in the .net TLD
single-letter SL domains in the ccTLDs (where the ccTLD is two letters)
two-character SL domains in gTLDs (where the gTLD is two or more letters)
three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)
IPv4 dot-decimal address format; TLD not allowed
returns true if domain appears to be a proper name and TLD or IPv4 address, else false
]=]
local function is_domain_name (domain)
if not domain then
return false; -- if not set, abandon
end
domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once
local sl_domain = domain:match ('[^%.]+') or domain; -- test the second level domain name
if not (sl_domain:match ('^%w') and sl_domain:match ('%w$') and -- first and last characters must be letter or digit
sl_domain:match ('^[%w%-]+$')) then -- all other characters must be letters, digits, or hyphen-minus
return false;
end
if domain:match ('^%a+:') then -- hack to detect things that look like s:Page:Title where Page: is namespace at Wikisource
return false;
end
local patterns = { -- patterns that look like URLs
'%f[%w][%w][%w%-]+[%w]%.%a%a+$', -- three or more character hostname.hostname or hostname.tld
'%f[%w][%w][%w%-]+[%w]%.xn%-%-[%w]+$', -- internationalized domain name with ACE prefix
'%f[%a][qxz]%.com$', -- assigned one character .com hostname (x.com times out 2015-12-10)
'%f[%a][iq]%.net$', -- assigned one character .net hostname (q.net registered but not active 2015-12-10)
'%f[%w][%w]%.%a%a$', -- one character hostname and ccTLD (2 chars)
'%f[%w][%w][%w]%.%a%a+$', -- two character hostname and TLD
'^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?', -- IPv4 address
'[%a%d]+%:?' -- IPv6 address
}
for _, pattern in ipairs (patterns) do -- loop through the patterns list
if domain:match (pattern) then
return true; -- if a match then we think that this thing that purports to be a URL is a URL
end
end
for _, d in ipairs (cfg.single_letter_2nd_lvl_domains_t) do -- look for single letter second level domain names for these top level domains
if domain:match ('%f[%w][%w]%.' .. d) then
return true
end
end
return false; -- no matches, we don't know what this thing is
end
--[[--------------------------< I S _ U R L >------------------------------------------------------------------
returns true if the scheme and domain parts of a URL appear to be a valid URL; else false.
This function is the last step in the validation process. This function is separate because there are cases that
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external
wikilinks.
]]
local function is_url (scheme, domain)
if utilities.is_set (scheme) then -- if scheme is set check it and domain
return is_scheme (scheme) and is_domain_name (domain);
else
return is_domain_name (domain); -- scheme not set when URL is protocol-relative
end
end
--[[--------------------------< S P L I T _ U R L >------------------------------------------------------------
Split a URL into a scheme, authority indicator, and domain.
First remove Fully Qualified Domain Name terminator (a dot following TLD) (if any) and any path(/), query(?) or fragment(#).
If protocol-relative URL, return nil scheme and domain else return nil for both scheme and domain.
When not protocol-relative, get scheme, authority indicator, and domain. If there is an authority indicator (one
or more '/' characters immediately following the scheme's colon), make sure that there are only 2.
Any URL that does not have news: scheme must have authority indicator (//). TODO: are there other common schemes
like news: that don't use authority indicator?
Strip off any port and path;
]]
local function split_url (url_str)
local scheme, authority, domain;
url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//')
if url_str:match ('^//%S*') then -- if there is what appears to be a protocol-relative URL
domain = url_str:match ('^//(%S*)')
elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name
scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions
if utilities.is_set (authority) then
authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing;
if utilities.is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then
return scheme; -- return scheme only making domain nil which will cause an error message
end
else
if not scheme:match ('^news:') then -- except for news:..., MediaWiki won't link URLs that do not have authority indicator; TODO: a better way to do this test?
return scheme; -- return scheme only making domain nil which will cause an error message
end
end
domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present
end
return scheme, domain;
end
--[[--------------------------< L I N K _ P A R A M _ O K >---------------------------------------------------
checks the content of |title-link=, |series-link=, |author-link=, etc. for properly formatted content: no wikilinks, no URLs
Link parameters are to hold the title of a Wikipedia article, so none of the WP:TITLESPECIALCHARACTERS are allowed:
# < > [ ] | { } _
except the underscore which is used as a space in wiki URLs and # which is used for section links
returns false when the value contains any of these characters.
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid URL (the
|<param>-link= parameter is ok); else false when value appears to be a valid URL (the |<param>-link= parameter is NOT ok).
]]
local function link_param_ok (value)
local scheme, domain;
if value:find ('[<>%[%]|{}]') then -- if any prohibited characters
return false;
end
scheme, domain = split_url (value); -- get scheme or nil and domain or nil from URL;
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid URL
end
--[[--------------------------< L I N K _ T I T L E _ O K >---------------------------------------------------
Use link_param_ok() to validate |<param>-link= value and its matching |<title>= value.
|<title>= may be wiki-linked but not when |<param>-link= has a value. This function emits an error message when
that condition exists
check <link> for inter-language interwiki-link prefix. prefix must be a MediaWiki-recognized language
code and must begin with a colon.
]]
local function link_title_ok (link, lorig, title, torig)
local orig;
if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value
if not link_param_ok (link) then -- check |<param>-link= markup
orig = lorig; -- identify the failing link parameter
elseif title:find ('%[%[') then -- check |title= for wikilink markup
orig = torig; -- identify the failing |title= parameter
elseif link:match ('^%a+:') then -- if the link is what looks like an interwiki
local prefix = link:match ('^(%a+):'):lower(); -- get the interwiki prefix
if cfg.inter_wiki_map[prefix] then -- if prefix is in the map, must have preceding colon
orig = lorig; -- flag as error
end
end
end
if utilities.is_set (orig) then
link = ''; -- unset
utilities.set_message ('err_bad_paramlink', orig); -- URL or wikilink in |title= with |title-link=;
end
return link; -- link if ok, empty string else
end
--[[--------------------------< C H E C K _ U R L >------------------------------------------------------------
Determines whether a URL string appears to be valid.
First we test for space characters. If any are found, return false. Then split the URL into scheme and domain
portions, or for protocol-relative (//example.com) URLs, just the domain. Use is_url() to validate the two
portions of the URL. If both are valid, or for protocol-relative if domain is valid, return true, else false.
Because it is different from a standard URL, and because this module used external_link() to make external links
that work for standard and news: links, we validate newsgroup names here. The specification for a newsgroup name
is at https://tools.ietf.org/html/rfc5536#section-3.1.4
]]
local function check_url( url_str )
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper URL
return false;
end
local scheme, domain;
scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from URL;
if 'news:' == scheme then -- special case for newsgroups
return domain:match('^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$');
end
return is_url (scheme, domain); -- return true if value appears to be a valid URL
end
--[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
non-space characters following the opening bracket appear to be a URL. The test will also find external wikilinks
that use protocol-relative URLs. Also finds bare URLs.
The frontier pattern prevents a match on interwiki-links which are similar to scheme:path URLs. The tests that
find bracketed URLs are required because the parameters that call this test (currently |title=, |chapter=, |work=,
and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]]
is possible as might be [[en://Hus]].
]=]
local function is_parameter_ext_wikilink (value)
local scheme, domain;
if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext. wikilink with scheme and domain: [xxxx://yyyyy.zzz]
scheme, domain = split_url (value:match ('%f[%[]%[(%a%S*:%S+).*%]'));
elseif value:match ('%f[%[]%[//%S+.*%]') then -- if protocol-relative ext. wikilink: [//yyyyy.zzz]
scheme, domain = split_url (value:match ('%f[%[]%[(//%S+).*%]'));
elseif value:match ('%a%S*:%S+') then -- if bare URL with scheme; may have leading or trailing plain text
scheme, domain = split_url (value:match ('(%a%S*:%S+)'));
elseif value:match ('^//%S+') or value:match ('%s//%S+') then -- if protocol-relative bare URL: //yyyyy.zzz; authority indicator (//) must be be preceded nothing or by whitespace
scheme, domain = split_url (value:match ('(//%S+)')); -- what is left should be the domain
else
return false; -- didn't find anything that is obviously a URL
end
return is_url (scheme, domain); -- return true if value appears to be a valid URL
end
--[[--------------------------< I S _ A R C H I V E _ T O D A Y _ U R L >--------------------------------------
archive.today (and .ph, .is, .md, .li, .fo, .vn) are deprecated. See Wikipedia:Requests_for_comment/Archive.is_RFC_5
(Special:Permalink/1339352976)
<val> is a string that may or may not be a url
]]
local function is_archive_today_url (val)
if is_parameter_ext_wikilink (val) then -- is <val> a url?
local tld = val:match ('archive%.(%l+)/'); -- get the tld; real archive.today urls have a '/' after the tld
return tld and cfg.archive_today_tlds_t[tld]; -- return true if <tld> is one of the archive.today tlds; nil else
end
end
--[[--------------------------< H A S _ A R C H I V E _ T O D A Y _ U R L >------------------------------------
blank any parameter that holds one of the archive.today tlds (.today, .ph, .is, .md, .li, .fo, .vn) and also
blank parameters that are dependent on the offending parameter.
input <cite_args_t> is a table of all of this template's parameters This function modifies <cite_args_t>
when |url= or its alias |URL= hold an archive.today url, this function sets the flag <url_was_archive_today>
which is used later to suppress the missing url error message from {{citation}} when it has |website=<summat>
or from the templates {{cite web}}, {{cite podcast}}, {{cite mailing list}} which all require a url.
returns nothing
]]
local function has_archive_today_url (cite_args_t)
local unset_params_t = {}; -- to hold a sequence of parameters to unset from cite_args_t
for p, v in pairs (cite_args_t) do -- look at each parameter in the template
if is_archive_today_url (v:lower()) then -- if it has a parameter with an archive.today url
table.insert (unset_params_t, p); -- add the url-holding parameter name to our list of parameters to unset (may or may not be a legitimate url parameter)
if 'url' == p:lower() then -- if this parameter is |url= or |URL=
url_was_archive_today = true; -- set a flag so that cite web / podcast / mailinglist don't emit a missing url error message
end
if p:match ('archive%-?url') and ('usurped' == cite_args_t['url-status'] or 'unfit' == cite_args_t['url-status']) then -- if |archive-url=archive.today and |url-status=unfit/usurped
url_was_archive_today = true; -- set a flag so that cite web / podcast / mailinglist don't emit a missing url error message
table.insert (unset_params_t, 'url'); -- add the url parameter name to our list of parameters to unset (may or may not be a legitimate url parameter)
table.insert (unset_params_t, 'URL'); -- this one because both are possible
end
if cfg.dependencies_t[p] then -- if this url-holding parameter (<p>) has dependencies
for _, dependent in ipairs (cfg.dependencies_t[p]) do -- loop through the url-holding parameter's dependency sequence
table.insert (unset_params_t, dependent); -- add dependent parameter to the list to be unset
end
end
end
end
if 0 < #unset_params_t then -- when there are parameters to unset
if not is_preview_mode then -- when in preview mode do not suppress any parameters
for _, unset_param in ipairs (unset_params_t) do -- loop through the sequence
cite_args_t[unset_param] = nil; -- and unset the url-holding parameter and its dependent parameters to avoid parameter-requires-other-parameter errors
end
end
utilities.set_message ('maint_deprecated_archive'); -- add a maintenance message
end
end
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message.
]]
local function check_for_url (parameter_list, error_list)
for k, v in pairs (parameter_list) do -- for each parameter in the list
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message
table.insert (error_list, utilities.wrap_style ('parameter', k));
end
end
end
--[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------
Escape sequences for content that will be used for URL descriptions
]]
local function safe_for_url( str )
if str:match( "%[%[.-%]%]" ) ~= nil then
utilities.set_message ('err_wikilink_in_url', {});
end
return str:gsub( '[%[%]\n]', {
['['] = '[',
[']'] = ']',
['\n'] = ' ' } );
end
--[[--------------------------< E X T E R N A L _ L I N K >----------------------------------------------------
Format an external link with error checking
]]
local function external_link (URL, label, source, access)
local domain;
local path;
local base_url;
if not utilities.is_set (label) then
label = URL;
if utilities.is_set (source) then
utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)});
else
error (cfg.messages["bare_url_no_origin"]); -- programmer error; valid parameter name does not have matching meta-parameter
end
end
if not check_url (URL) then
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)});
end
domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path
if path then -- if there is a path portion
path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); -- replace '[' and ']' with their percent-encoded values
URL = table.concat ({domain, path}); -- and reassemble
end
base_url = table.concat ({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL
if utilities.is_set (access) then -- access level (subscription, registration, limited)
base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon
end
return base_url;
end
--[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the
offending parameter name to the error message. Only one error message is emitted regardless of the number of deprecated
parameters in the citation.
added_deprecated_cat is a Boolean declared in page scope variables above
]]
local function deprecated_parameter(name)
if not added_deprecated_cat then
added_deprecated_cat = true; -- note that we've added this category
utilities.set_message ('err_deprecated_params', {name}); -- add error message
end
end
--[=[-------------------------< K E R N _ Q U O T E S >--------------------------------------------------------
Apply kerning to open the space between the quote mark provided by the module and a leading or trailing quote
mark contained in a |title= or |chapter= parameter's value.
This function will positive kern either single or double quotes:
"'Unkerned title with leading and trailing single quote marks'"
" 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example)
Double single quotes (italic or bold wiki-markup) are not kerned.
Replaces Unicode quote marks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter
quote marks regardless of the need for kerning. Unicode quote marks are not replaced in simple [[D]] wikilinks.
Call this function for chapter titles, for website titles, etc.; not for book titles.
]=]
local function kern_quotes (str)
local wl_type, label, link;
wl_type, label, link = utilities.is_wikilink (str); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]
if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks
if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks
str = utilities.substitute (cfg.presentation['kern-left'], str);
str = utilities.substitute (cfg.presentation['kern-right'], str);
elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks
str = utilities.substitute (cfg.presentation['kern-left'], str);
elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks
str = utilities.substitute (cfg.presentation['kern-right'], str);
end
else -- plain text or [[L|D]]; text in label variable
label = mw.ustring.gsub (label, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark)
label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark)
local cap = mw.ustring.match (label, "^([\"\'][^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup)
if utilities.is_set (cap) then
label = utilities.substitute (cfg.presentation['kern-left'], cap);
end
cap = mw.ustring.match (label, "^(.+[^\'][\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup)
if utilities.is_set (cap) then
label = utilities.substitute (cfg.presentation['kern-right'], cap);
end
if 2 == wl_type then
str = utilities.make_wikilink (link, label); -- reassemble the wikilink
else
str = label;
end
end
return str;
end
--[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >----------------------------------------
|script-title= holds title parameters that are not written in Latin-based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should
not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped
in italic markup.
Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate RTL languages from the English left to right.
|script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO 639-1 language code and a colon:
|script-title=ja:*** *** (where * represents a Japanese character)
Spaces between the two-character code and the colon and the colon and the first script character are allowed:
|script-title=ja : *** ***
|script-title=ja: *** ***
|script-title=ja :*** ***
Spaces preceding the prefix are allowed: |script-title = ja:*** ***
The prefix is checked for validity. If it is a valid ISO 639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can
know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute
is not added. At this time there is no error message for this condition.
Supports |script-title=, |script-chapter=, |script-<periodical>=
]]
local function format_script_value (script_value, script_param)
local lang=''; -- initialize to empty string
local name;
if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix
lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script
if not utilities.is_set (lang) then
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing title part']}); -- prefix without 'title'; add error message
return ''; -- script_value was just the prefix so return empty string
end
-- if we get this far we have prefix and script
name = cfg.lang_tag_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize
if utilities.is_set (name) then -- is prefix a proper ISO 639-1 language code?
script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script
-- is prefix one of these language codes?
if utilities.in_array (lang, cfg.script_lang_codes) then
utilities.add_prop_cat ('script', {name, lang})
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['unknown language code']}); -- unknown script-language; add error message
end
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['invalid language code']}); -- invalid language code; add error message
lang = ''; -- invalid so set lang to empty string
end
else
utilities.set_message ('err_script_parameter', {script_param, cfg.err_msg_supl['missing prefix']}); -- no language code prefix; add error message
end
script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL
return script_value;
end
--[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script
value has been wrapped in <bdi> tags.
]]
local function script_concatenate (title, script, script_param)
if utilities.is_set (script) then
script = format_script_value (script, script_param); -- <bdi> tags, lang attribute, categorization, etc.; returns empty string on error
if utilities.is_set (script) then
title = title .. ' ' .. script; -- concatenate title and script title
end
end
return title;
end
--[[--------------------------< W R A P _ M S G >--------------------------------------------------------------
Applies additional message text to various parameter values. Supplied string is wrapped using a message_list
configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken
from citation_config.messages - the reason this function is similar to but separate from wrap_style().
]]
local function wrap_msg (key, str, lower)
if not utilities.is_set ( str ) then
return "";
end
if true == lower then
local msg;
msg = cfg.messages[key]:lower(); -- set the message to lower case before
return utilities.substitute ( msg, str ); -- including template text
else
return utilities.substitute ( cfg.messages[key], str );
end
end
--[[----------------< W I K I S O U R C E _ U R L _ M A K E >-------------------
Makes a Wikisource URL from Wikisource interwiki-link. Returns the URL and appropriate
label; nil else.
str is the value assigned to |chapter= (or aliases) or |title= or |title-link=
]]
local function wikisource_url_make (str)
local wl_type, D, L;
local ws_url, ws_label;
local wikisource_prefix = table.concat ({'https://', cfg.this_wiki_code, '.wikisource.org/wiki/'});
wl_type, D, L = utilities.is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink)
if 0 == wl_type then -- not a wikilink; might be from |title-link=
str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title
});
ws_label = str; -- label for the URL
end
elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]]
str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title
});
ws_label = str; -- label for the URL
end
elseif 2 == wl_type then -- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]])
str = L:match ('^[Ww]ikisource:(.+)') or L:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace
if utilities.is_set (str) then
ws_label = D; -- get ws article name from display portion of interwiki link
ws_url = table.concat ({ -- build a Wikisource URL
wikisource_prefix, -- prefix
str, -- article title without namespace from link portion of wikilink
});
end
end
if ws_url then
ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable URL
ws_url = ws_url:gsub ('%%23', '#'); -- undo percent-encoding of fragment marker
end
return ws_url, ws_label, L or D; -- return proper URL or nil and a label or nil
end
--[[----------------< F O R M A T _ P E R I O D I C A L >-----------------------
Format the three periodical parameters: |script-<periodical>=, |<periodical>=,
and |trans-<periodical>= into a single Periodical meta-parameter.
]]
local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical)
if not utilities.is_set (periodical) then
periodical = ''; -- to be safe for concatenation
else
periodical = utilities.wrap_style ('italic-title', periodical); -- style
end
periodical = script_concatenate (periodical, script_periodical, script_periodical_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
if utilities.is_set (trans_periodical) then
trans_periodical = utilities.wrap_style ('trans-italic-title', trans_periodical);
if utilities.is_set (periodical) then
periodical = periodical .. ' ' .. trans_periodical;
else -- here when trans-periodical without periodical or script-periodical
periodical = trans_periodical;
utilities.set_message ('err_trans_missing_title', {'periodical'});
end
end
return periodical;
end
--[[------------------< F O R M A T _ C H A P T E R _ T I T L E >---------------
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=,
and |chapter-url= into a single chapter meta- parameter (chapter_url_source used
for error messages).
]]
local function format_chapter_title (script_chapter, script_chapter_source, chapter, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access)
local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link
if ws_url then
ws_label = ws_label:gsub ('_', ' '); -- replace underscore separators with space characters
chapter = ws_label;
end
if not utilities.is_set (chapter) then
chapter = ''; -- to be safe for concatenation
else
if false == no_quotes then
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from module provided quote marks
chapter = utilities.wrap_style ('quoted-title', chapter);
end
end
chapter = script_concatenate (chapter, script_chapter, script_chapter_source); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
if utilities.is_set (chapter_url) then
chapter = external_link (chapter_url, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate
elseif ws_url then
chapter = external_link (ws_url, chapter .. ' ', 'ws link in chapter'); -- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this?
chapter = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, chapter});
end
if utilities.is_set (trans_chapter) then
trans_chapter = utilities.wrap_style ('trans-quoted-title', trans_chapter);
if utilities.is_set (chapter) then
chapter = chapter .. ' ' .. trans_chapter;
else -- here when trans_chapter without chapter or script-chapter
chapter = trans_chapter;
utilities.set_message ('err_trans_missing_title', {trans_chapter_source:match ('trans%-?(.+)')}); -- when no chapter, get matching name from trans-<param>
end
end
return chapter;
end
--[[----------------< H A S _ I N V I S I B L E _ C H A R S >-------------------
This function searches a parameter's value for non-printable or invisible characters.
The search stops at the first match.
This function will detect the visible replacement character when it is part of the Wikisource.
Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers
(gallery, math, pre, ref) and identifies them with a slightly different error message.
See also coins_cleanup().
Output of this function is an error message that identifies the character or the
Unicode group, or the stripmarker that was detected along with its position (or,
for multi-byte characters, the position of its first byte) in the parameter value.
]]
local function has_invisible_chars (param, v)
local position; -- position of invisible char or starting position of stripmarker
local capture; -- used by stripmarker detection to hold name of the stripmarker
local stripmarker; -- boolean set true when a stripmarker is found
capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true
if capture == v then -- if same there are no Unicode characters
return;
end
for _, invisible_char in ipairs (cfg.invisible_chars) do
local char_name = invisible_char[1]; -- the character or group name
local pattern = invisible_char[2]; -- the pattern used to find it
position, _, capture = mw.ustring.find (v, pattern); -- see if the parameter value contains characters that match the pattern
if position and (cfg.invisible_defs.zwj == capture) then -- if we found a zero-width joiner character
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts
position = nil; -- unset position
elseif cfg.emoji_t[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}?
position = nil; -- unset position
end
end
if position then
if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition)
('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters
stripmarker = true; -- set a flag
elseif true == stripmarker and cfg.invisible_defs.del == capture then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
position = nil; -- unset; for now, ignore linter warning
else
local err_msg;
if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then
err_msg = utilities.substitute (cfg.messages.invisible_1, {capture, char_name}); -- <capture> here is stripmarker name
else
err_msg = utilities.substitute (cfg.messages.invisible_2, char_name);
end
utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}); -- add error message
return; -- and done with this parameter
end
end
end
end
--[[-------------------< A R G U M E N T _ W R A P P E R >----------------------
Argument wrapper. This function provides support for argument mapping defined
in the configuration file so that multiple names can be transparently aliased to
single internal variable.
]]
local function argument_wrapper ( args )
local origin = {};
return setmetatable({
ORIGIN = function ( self, k )
local dummy = self[k]; -- force the variable to be loaded; for now, ignore linter warning
return origin[k];
end
},
{
__index = function ( tbl, k )
if origin[k] ~= nil then
return nil;
end
local v;
local list = cfg.aliases[k];
if type( list ) == 'table' then
v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' );
if origin[k] == nil then
origin[k] = ''; -- Empty string, not nil
end
elseif list ~= nil then
v, origin[k] = args[list], list;
else
-- maybe let through instead of raising an error?
-- v, origin[k] = args[k], k;
error( cfg.messages['unknown_argument_map'] .. ': ' .. k);
end
-- Empty strings, not nil;
if v == nil then
v = '';
origin[k] = '';
end
-- tbl = rawset( tbl, k, v );
rawset( tbl, k, v );
return v;
end,
});
end
--[[--------------------------< N O W R A P _ D A T E >-------------------------
When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.
When date is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span:
<span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY
DOES NOT yet support MMMM YYYY or any of the date ranges.
]]
local function nowrap_date (date)
local cap;
local cap2;
if date:match("^%d%d%d%d%-%d%d%-%d%d$") then
date = utilities.substitute (cfg.presentation['nowrap1'], date);
elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then
cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$");
date = utilities.substitute (cfg.presentation['nowrap2'], {cap, cap2});
end
return date;
end
--[[--------------------------< S E T _ T I T L E T Y P E >---------------------
This function sets default title types (equivalent to the citation including
|type=<default value>) for those templates that have defaults. Also handles the
special case where it is desirable to omit the title type from the rendered citation
(|type=none).
]]
local function set_titletype (cite_class, title_type)
if utilities.is_set (title_type) then
if 'none' == cfg.keywords_xlate[title_type] then
title_type = ''; -- if |type=none then type parameter not displayed
end
return title_type; -- if |type= has been set to any other value use that value
end
return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation
end
--[[--------------------------< S A F E _ J O I N >-----------------------------
Joins a sequence of strings together while checking for duplicate separation characters.
]]
local function safe_join( tbl, duplicate_char )
local f = {}; -- create a function table appropriate to type of 'duplicate character'
if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions
f.gsub = string.gsub
f.match = string.match
f.sub = string.sub
else -- for multi-byte characters use the ustring library functions
f.gsub = mw.ustring.gsub
f.match = mw.ustring.match
f.sub = mw.ustring.sub
end
local str = ''; -- the output string
for _, value in ipairs( tbl ) do
if value == nil then value = ''; end
if str == '' then -- if output string is empty
str = value; -- assign value to it (first time through the loop)
elseif value ~= '' then
local comp; -- what does 'comp' mean?
if value:sub(1, 1) == '<' then -- special case of values enclosed in spans and other markup.
comp = value:gsub( "%b<>", "" ); -- remove HTML markup (<span>string</span> -> string)
else
comp = value;
end
-- typically duplicate_char is sepc
if f.sub(comp, 1, 1) == duplicate_char then -- is first character same as duplicate_char? why test first character?
-- Because individual string segments often (always?) begin with terminal punct for the
-- preceding segment: 'First element' .. 'sepc next element' .. etc.?
local trim = false;
local end_chr = f.sub(str, -1, -1); -- get the last character of the output string
-- str = str .. "<HERE(enchr=" .. end_chr .. ")" -- debug stuff?
if end_chr == duplicate_char then -- if same as separator
str = f.sub(str, 1, -2); -- remove it
elseif end_chr == "'" then -- if it might be wiki-markup
if f.sub(str, -3, -1) == duplicate_char .. "''" then -- if last three chars of str are sepc''
str = f.sub(str, 1, -4) .. "''"; -- remove them and add back ''
elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]''
trim = true; -- why? why do this and next differently from previous?
elseif f.sub(str, -4, -1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]''
trim = true; -- same question
end
elseif end_chr == "]" then -- if it might be wiki-markup
if f.sub(str, -3, -1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink
trim = true;
elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link
trim = true;
elseif f.sub(str, -2, -1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link
trim = true;
elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title.
trim = true;
end
elseif end_chr == " " then -- if last char of output string is a space
if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space>
str = f.sub(str, 1, -3); -- remove them both
end
end
if trim then
if value ~= comp then -- value does not equal comp when value contains HTML markup
local dup2 = duplicate_char;
if f.match(dup2, "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it
value = f.gsub(value, "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows HTML markup
else
value = f.sub(value, 2, -1 ); -- remove duplicate_char when it is first character
end
end
end
str = str .. value; -- add it to the output string
end
end
return str;
end
--[[--------------------------< I S _ S U F F I X >-----------------------------
returns true if suffix is properly formed Jr, Sr, or ordinal in the range 1–9.
Puncutation not allowed.
]]
local function is_suffix (suffix)
if utilities.in_array (suffix, {'Jr', 'Sr', 'Jnr', 'Snr', '1st', '2nd', '3rd'}) or suffix:match ('^%dth$') then
return true;
end
return false;
end
--[[--------------------< I S _ G O O D _ V A N C _ N A M E >-------------------
For Vancouver style, author/editor names are supposed to be rendered in Latin
(read ASCII) characters. When a name uses characters that contain diacritical
marks, those characters are to be converted to the corresponding Latin
character. When a name is written using a non-Latin alphabet or logogram, that
name is to be transliterated into Latin characters. The module doesn't do this
so editors may/must.
This test allows |first= and |last= names to contain any of the letters defined
in the four Unicode Latin character sets
[http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A
[http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF
[http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F
[http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F
|lastn= also allowed to contain hyphens, spaces, and apostrophes.
(http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
|firstn= also allowed to contain hyphens, spaces, apostrophes, and periods
This original test:
if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$")
or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]+[2-6%a]*$") then
was written outside of the code editor and pasted here because the code editor
gets confused between character insertion point and cursor position. The test has
been rewritten to use decimal character escape sequence for the individual bytes
of the Unicode characters so that it is not necessary to use an external editor
to maintain this code.
\195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls)
\195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls)
\195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A & B)
\199\132-\201\143 – DŽ-ɏ (U+01C4-U+024F – Latin extended B)
]]
local function is_good_vanc_name (last, first, suffix, position)
if not suffix then
if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix
first = first:match ('(.-)[,%s]+'); -- get name/initials
suffix = first:match ('[,%s]+(.+)$'); -- get generational suffix
end
end
if utilities.is_set (suffix) then
if not is_suffix (suffix) then
add_vanc_error (cfg.err_msg_supl.suffix, position);
return false; -- not a name with an appropriate suffix
end
end
if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%']*$") or
nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191%-%s%'%.]*$") then
add_vanc_error (cfg.err_msg_supl['non-Latin char'], position);
return false; -- not a string of Latin characters; Vancouver requires Romanization
end;
return true;
end
--[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------
Attempts to convert names to initials in support of |name-list-style=vanc.
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period.
See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/.
Vancouver style requires family rank designations (Jr, II, III, etc.) to be rendered
as Jr, 2nd, 3rd, etc. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/.
This code only accepts and understands generational suffix in the Vancouver format
because Roman numerals look like, and can be mistaken for, initials.
This function uses ustring functions because firstname initials may be any of the
Unicode Latin characters accepted by is_good_vanc_name ().
]]
local function reduce_to_initials (first, position)
if first:find (',', 1, true) then
return first; -- commas not allowed; abandon
end
local name, suffix = mw.ustring.match (first, "^(%u+) ([%dJS][%drndth]+)$");
if not name then -- if not initials and a suffix
name = mw.ustring.match (first, "^(%u+)$"); -- is it just initials?
end
if name then -- if first is initials with or without suffix
if 3 > mw.ustring.len (name) then -- if one or two initials
if suffix then -- if there is a suffix
if is_suffix (suffix) then -- is it legitimate?
return first; -- one or two initials and a valid suffix so nothing to do
else
add_vanc_error (cfg.err_msg_supl.suffix, position); -- one or two initials with invalid suffix so error message
return first; -- and return first unmolested
end
else
return first; -- one or two initials without suffix; nothing to do
end
end
end -- if here then name has 3 or more uppercase letters so treat them as a word
local initials_t = {}; -- table to hold initials
local i = 1; -- counter for number of initials
local names_t = mw.text.split (first, '[%s%-]+'); -- split into a sequence of names and possible suffix
while names_t[i] do -- loop through the sequence
if 1 < i and names_t[i]:match ('[%dJS][%drndth]+%.?$') then -- if not the first name, and looks like a suffix (may have trailing dot)
names_t[i] = names_t[i]:gsub ('%.', ''); -- remove terminal dot if present
if is_suffix (names_t[i]) then -- if a legitimate suffix
table.insert (initials_t, ' ' .. names_t[i]); -- add a separator space, insert at end of initials sequence
break; -- and done because suffix must fall at the end of a name
end -- no error message if not a suffix; possibly because of Romanization
end
if 3 > i then
table.insert (initials_t, mw.ustring.sub (names_t[i], 1, 1)); -- insert the initial at end of initials sequence
end
i = i + 1; -- bump the counter
end
return table.concat (initials_t); -- Vancouver format does not include spaces.
end
--[[--------------------------< I N T E R W I K I _ P R E F I X E N _ G E T >----------------------------------
extract interwiki prefixen from <value>. Returns two one or two values:
false – no prefixen
nil – prefix exists but not recognized
project prefix, language prefix – when value has either of:
:<project>:<language>:<article>
:<language>:<project>:<article>
project prefix, nil – when <value> has only a known single-letter prefix
nil, language prefix – when <value> has only a known language prefix
accepts single-letter project prefixen: 'd' (wikidata), 's' (wikisource), and 'w' (wikipedia) prefixes; at this
writing, the other single-letter prefixen (b (wikibook), c (commons), m (meta), n (wikinews), q (wikiquote), and
v (wikiversity)) are not supported.
]]
local function interwiki_prefixen_get (value, is_link)
if not value:find (':%l+:') then -- if no prefix
return false; -- abandon; boolean here to distinguish from nil fail returns later
end
local prefix_patterns_linked_t = { -- sequence of valid interwiki and inter project prefixen
'^%[%[:([dsw]):(%l%l+):', -- wikilinked; project and language prefixes
'^%[%[:(%l%l+):([dsw]):', -- wikilinked; language and project prefixes
'^%[%[:([dsw]):', -- wikilinked; project prefix
'^%[%[:(%l%l+):', -- wikilinked; language prefix
}
local prefix_patterns_unlinked_t = { -- sequence of valid interwiki and inter project prefixen
'^:([dsw]):(%l%l+):', -- project and language prefixes
'^:(%l%l+):([dsw]):', -- language and project prefixes
'^:([dsw]):', -- project prefix
'^:(%l%l+):', -- language prefix
}
local cap1, cap2;
for _, pattern in ipairs ((is_link and prefix_patterns_linked_t) or prefix_patterns_unlinked_t) do
cap1, cap2 = value:match (pattern);
if cap1 then
break; -- found a match so stop looking
end
end
if cap1 and cap2 then -- when both then :project:language: or :language:project: (both forms allowed)
if 1 == #cap1 then -- length == 1 then :project:language:
if cfg.inter_wiki_map[cap2] then -- is language prefix in the interwiki map?
return cap1, cap2; -- return interwiki project and interwiki language
end
else -- here when :language:project:
if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map?
return cap2, cap1; -- return interwiki project and interwiki language
end
end
return nil; -- unknown interwiki language
elseif not (cap1 or cap2) then -- both are nil?
return nil; -- we got something that looks like a project prefix but isn't; return fail
elseif 1 == #cap1 then -- here when one capture
return cap1, nil; -- length is 1 so return project, nil language
else -- here when one capture and its length it more than 1
if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map?
return nil, cap1; -- return nil project, language
end
end
end
--[[--------------------------< L I S T _ P E O P L E >--------------------------
Formats a list of people (authors, contributors, editors, interviewers, translators)
names in the list will be linked when
|<name>-link= has a value
|<name>-mask- does NOT have a value; masked names are presumed to have been
rendered previously so should have been linked there
when |<name>-mask=0, the associated name is not rendered
]]
local function list_people (control, people, etal)
local sep;
local namesep;
local format = control.format;
local maximum = control.maximum;
local name_list = {};
if 'vanc' == format then -- Vancouver-like name styling?
sep = cfg.presentation['sep_nl_vanc']; -- name-list separator between names is a comma
namesep = cfg.presentation['sep_name_vanc']; -- last/first separator is a space
else
sep = cfg.presentation['sep_nl']; -- name-list separator between names is a semicolon
namesep = cfg.presentation['sep_name']; -- last/first separator is <comma><space>
end
if sep:sub (-1, -1) ~= " " then sep = sep .. " " end
if utilities.is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for other names
for i, person in ipairs (people) do
if utilities.is_set (person.last) then
local mask = person.mask;
local one;
local sep_one = sep;
if utilities.is_set (maximum) and i > maximum then
etal = true;
break;
end
if mask then
local n = tonumber (mask); -- convert to a number if it can be converted; nil else
if n then
one = 0 ~= n and string.rep("—", n) or nil; -- make a string of (n > 0) mdashes, nil else, to replace name
person.link = nil; -- don't create link to name if name is replaces with mdash string or has been set nil
else
one = mask; -- replace name with mask text (must include name-list separator)
sep_one = " "; -- modify name-list separator
end
else
one = person.last; -- get surname
local first = person.first -- get given name
if utilities.is_set (first) then
if ("vanc" == format) then -- if Vancouver format
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
if not person.corporate and is_good_vanc_name (one, first, nil, i) then -- and name is all Latin characters; corporate authors not tested
first = reduce_to_initials (first, i); -- attempt to convert first name(s) to initials
end
end
one = one .. namesep .. first;
end
end
if utilities.is_set (person.link) then
one = utilities.make_wikilink (person.link, one); -- link author/editor
end
if one then -- if <one> has a value (name, mdash replacement, or mask text replacement)
local proj, tag = interwiki_prefixen_get (one, true); -- get the interwiki prefixen if present
if 'w' == proj and ('Wikipedia' == mw.site.namespaces.Project['name']) then
proj = nil; -- for stuff like :w:de:<article>, :w is unnecessary TODO: maint cat?
end
if proj then
local proj_name = ({['d'] = cfg.messages.wikidata, ['s'] = cfg.messages.wikisource, ['w'] = cfg.messages.wikipedia})[proj]; -- :w (wikipedia) for linking from a non-wikipedia project
if proj_name then
one = one .. utilities.wrap_style ('interproj', proj_name); -- add resized leading space, brackets, static text, language name
utilities.add_prop_cat ('interproj-linked-name', proj); -- categorize it; <proj> is sort key
tag = nil; -- unset; don't do both project and language
end
end
if tag == cfg.this_wiki_code then
tag = nil; -- stuff like :en:<article> at en.wiki is pointless TODO: maint cat?
end
if tag then
local lang = cfg.lang_tag_remap[tag] or cfg.mw_languages_by_tag_t[tag];
if lang then -- error messaging done in extract_names() where we know parameter names
one = one .. utilities.wrap_style ('interwiki', lang); -- add resized leading space, brackets, static text, language name
utilities.add_prop_cat ('interwiki-linked-name', tag); -- categorize it; <tag> is sort key
end
end
table.insert (name_list, one); -- add it to the list of names
table.insert (name_list, sep_one); -- add the proper name-list separator
end
end
end
local count = #name_list / 2; -- (number of names + number of separators) divided by 2
if 0 < count then
if 1 < count and not etal then
if 'amp' == format then
name_list[#name_list-2] = " & "; -- replace last separator with ampersand text
elseif 'and' == format then
if 2 == count then
name_list[#name_list-2] = cfg.presentation.sep_nl_and; -- replace last separator with 'and' text
else
name_list[#name_list-2] = cfg.presentation.sep_nl_end; -- replace last separator with '(sep) and' text
end
end
end
name_list[#name_list] = nil; -- erase the last separator
end
local result = table.concat (name_list); -- construct list
if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
result = result .. sep .. cfg.messages['et al']; -- we've got a last-first list and etal so add et al.
end
return result, count; -- return name-list string and count of number of names (count used for editor names only)
end
--[[--------------------< M A K E _ C I T E R E F _ I D >-----------------------
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise
returns an empty string.
namelist is one of the contributor-, author-, or editor-name lists chosen in that
order. year is Year or anchor_year.
]]
local function make_citeref_id (namelist, year)
local names={}; -- a table for the one to four names and year
for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names
names[i] = v.last
if i == 4 then break end -- if four then done
end
table.insert (names, year); -- add the year at the end
local id = table.concat(names); -- concatenate names and year for CITEREF id
if utilities.is_set (id) then -- if concatenation is not an empty string
return "CITEREF" .. id; -- add the CITEREF portion
else
return ''; -- return an empty string; no reason to include CITEREF id in this citation
end
end
--[[--------------------------< C I T E _ C L A S S _A T T R I B U T E _M A K E >------------------------------
construct <cite> tag class attribute for this citation.
<cite_class> – config.CitationClass from calling template
<mode> – value from |mode= parameter
]]
local function cite_class_attribute_make (cite_class, mode)
local class_t = {};
table.insert (class_t, 'citation'); -- required for blue highlight
if 'citation' ~= cite_class then
table.insert (class_t, cite_class); -- identify this template for user css
table.insert (class_t, utilities.is_set (mode) and mode or 'cs1'); -- identify the citation style for user css or javascript
else
table.insert (class_t, utilities.is_set (mode) and mode or 'cs2'); -- identify the citation style for user css or javascript
end
for _, prop_key in ipairs (z.prop_keys_t) do
table.insert (class_t, prop_key); -- identify various properties for user css or javascript
end
return table.concat (class_t, ' '); -- make a big string and done
end
--[[---------------------< N A M E _ H A S _ E T A L >--------------------------
Evaluates the content of name parameters (author, editor, etc.) for variations on
the theme of et al. If found, the et al. is removed, a flag is set to true and
the function returns the modified name and the flag.
This function never sets the flag to false but returns its previous state because
it may have been set by previous passes through this function or by the associated
|display-<names>=etal parameter
]]
local function name_has_etal (name, etal, nocat, param)
if utilities.is_set (name) then -- name can be nil in which case just return
local patterns = cfg.et_al_patterns; -- get patterns from configuration
for _, pattern in ipairs (patterns) do -- loop through all of the patterns
if name:match (pattern) then -- if this 'et al' pattern is found in name
name = name:gsub (pattern, ''); -- remove the offending text
etal = true; -- set flag (may have been set previously here or by |display-<names>=etal)
if not nocat then -- no categorization for |vauthors=
utilities.set_message ('err_etal', {param}); -- and set an error if not added
end
end
end
end
return name, etal;
end
--[[---------------------< N A M E _ I S _ N U M E R I C >----------------------
Add an error message and category when <name> parameter value does not contain letters.
Add a maintenance category when <name> parameter value has numeric characters mixed with characters that are
not numeric characters; could be letters and/or punctuation characters.
This function will only emit one error and one maint message for the current template. Does not emit both error
and maint messages/categories for the same parameter value.
returns nothing
]]
local function name_is_numeric (name, name_alias, list_name)
local patterns = {
'^%D+%d', -- <name> must have digits preceded by other characters
'^%D*%d+%D+', -- <name> must have digits followed by other characters
}
if not added_numeric_name_errs and mw.ustring.match (name, '^[%A]+$') then -- if we have not already set an error message and <name> does not have any alpha characters
utilities.set_message ('err_numeric_names', name_alias); -- add an error message
added_numeric_name_errs = true; -- set the flag so we emit only one error message
return; -- when here no point in further testing; abandon
end
if not added_numeric_name_maint then -- if we have already set a maint message
for _, pattern in ipairs (patterns) do -- spin through list of patterns
if mw.ustring.match (name, pattern) then -- digits preceded or followed by anything but digits; %D+ includes punctuation
utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template
added_numeric_name_maint = true; -- set the flag so we emit only one maint message
return; -- when here no point in further testing; abandon
end
end
end
end
--[[-----------------< N A M E _ H A S _ M U L T _ N A M E S >------------------
Evaluates the content of last/surname (authors etc.) parameters for multiple names.
Multiple names are indicated if there is more than one comma or any "unescaped"
semicolons. Escaped semicolons are ones used as part of selected HTML entities.
If the condition is met, the function adds the multiple name maintenance category.
Same test for first except that commas should not appear in given names (MOS:JR says
that the generational suffix does not take a separator character). Titles, degrees,
postnominals, affiliations, all normally comma separated don't belong in a citation.
<name> – name parameter value
<list_name> – AuthorList, EditorList, etc
<limit> – number of allowed commas; 1 (default) for surnames; 0 for given names
returns nothing
]]
local function name_has_mult_names (name, list_name, limit)
local _, commas, semicolons, nbsps;
limit = limit and limit or 1;
if utilities.is_set (name) then
_, commas = name:gsub (',', ''); -- count the number of commas
_, semicolons = name:gsub (';', ''); -- count the number of semicolons
-- nbsps probably should be its own separate count rather than merged in
-- some way with semicolons because Lua patterns do not support the
-- grouping operator that regex does, which means there is no way to add
-- more entities to escape except by adding more counts with the new
-- entities
_, nbsps = name:gsub (' ',''); -- count nbsps
-- There is exactly 1 semicolon per entity, so subtract nbsps
-- from semicolons to 'escape' them. If additional entities are added,
-- they also can be subtracted.
if limit < commas or 0 < (semicolons - nbsps) then
utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message
end
end
end
--[=[-------------------------< I S _ G E N E R I C >----------------------------------------------------------
Compares values assigned to various parameters according to the string provided as <item> in the function call.
<item> can have on of two values:
'generic_names' – for name-holding parameters: |last=, |first=, |editor-last=, etc
'generic_titles' – for |title=
There are two types of generic tests. The 'accept' tests look for a pattern that should not be rejected by the
'reject' test. For example,
|author=[[John Smith (author)|Smith, John]]
would be rejected by the 'author' reject test. But piped wikilinks with 'author' disambiguation should not be
rejected so the 'accept' test prevents that from happening. Accept tests are always performed before reject
tests.
Each of the 'accept' and 'reject' sequence tables hold tables for en.wiki (['en']) and local.wiki (['local'])
that each can hold a test sequence table The sequence table holds, at index [1], a test pattern, and, at index
[2], a boolean control value. The control value tells string.find() or mw.ustring.find() to do plain-text search (true)
or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so
that we don't run out of processing time on very large articles.
Returns
true when a reject test finds the pattern or string
false when an accept test finds the pattern or string
nil else
]=]
local function is_generic (item, value)
local str_lower = { -- use string.lower() for en.wiki (['en']) and use mw.ustring.lower() or local.wiki (['local'])
['en'] = string.lower,
['local'] = mw.ustring.lower,
}
local str_find = { -- use string.find() for en.wiki (['en']) and use mw.ustring.find() or local.wiki (['local'])
['en'] = string.find,
['local'] = mw.ustring.find,
}
local function test (val, test_t, wiki) -- local function to do the testing; <wiki> selects lower() and find() functions
val = test_t[2] and str_lower[wiki](value) or val; -- when <test_t[2]> set to 'true', plaintext search using lowercase value
return str_find[wiki] (val, test_t[1], 1, test_t[2]); -- return nil when not found or matched
end
local test_types_t = {'accept', 'reject'}; -- test accept patterns first, then reject patterns
local wikis_t = {'en', 'local'}; -- do tests for each of these keys; en.wiki first, local.wiki second
for _, test_type in ipairs (test_types_t) do -- for each test type
for _, generic_value in pairs (cfg.special_case_translation[item][test_type]) do -- spin through the list of generic value fragments to accept or reject
for _, wiki in ipairs (wikis_t) do
if generic_value[wiki] then
if test (value, generic_value[wiki], wiki) then -- go do the test
return ('reject' == test_type); -- param value rejected, return true; false else
end
end
end
end
end
end
--[[--------------------------< N A M E _ I S _ G E N E R I C >------------------------------------------------
calls is_generic() to determine if <name> is a 'generic name' listed in cfg.generic_names; <name_alias> is the
parameter name used in error messaging
]]
local function name_is_generic (name, name_alias)
if not added_generic_name_errs and is_generic ('generic_names', name) then
utilities.set_message ('err_generic_name', name_alias); -- set an error message
added_generic_name_errs = true;
end
end
--[[--------------------------< N A M E _ C H E C K S >--------------------------------------------------------
This function calls various name checking functions used to validate the content of the various name-holding parameters.
]]
local function name_checks (last, first, list_name, last_alias, first_alias)
local accept_name;
if utilities.is_set (last) then
last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last>
if not accept_name then -- <last> not wrapped in accept-as-written markup
name_has_mult_names (last, list_name); -- check for multiple names in the parameter
name_is_numeric (last, last_alias, list_name); -- check for names that have no letters or are a mix of digits and other characters
name_is_generic (last, last_alias); -- check for names found in the generic names list
end
end
if utilities.is_set (first) then
first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first>
if not accept_name then -- <first> not wrapped in accept-as-written markup
name_has_mult_names (first, list_name, 0); -- check for multiple names in the parameter; 0 is number of allowed commas in a given name
name_is_numeric (first, first_alias, list_name); -- check for names that have no letters or are a mix of digits and other characters
name_is_generic (first, first_alias); -- check for names found in the generic names list
end
local wl_type, D = utilities.is_wikilink (first);
if 0 ~= wl_type then
first = D;
utilities.set_message ('err_bad_paramlink', first_alias);
end
end
return last, first; -- done
end
--[[----------------------< E X T R A C T _ N A M E S >-------------------------
Gets name list from the input arguments
Searches through args in sequential order to find |lastn= and |firstn= parameters
(or their aliases), and their matching link and mask parameters. Stops searching
when both |lastn= and |firstn= are not found in args after two sequential attempts:
found |last1=, |last2=, and |last3= but doesn't find |last4= and |last5= then the
search is done.
This function emits an error message when there is a |firstn= without a matching
|lastn=. When there are 'holes' in the list of last names, |last1= and |last3=
are present but |last2= is missing, an error message is emitted. |lastn= is not
required to have a matching |firstn=.
When an author or editor parameter contains some form of 'et al.', the 'et al.'
is stripped from the parameter and a flag (etal) returned that will cause list_people()
to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps
'et al.' out of the template's metadata. When this occurs, an error is emitted.
]]
local function extract_names(args, list_name)
local names = {}; -- table of names
local last; -- individual name components
local first;
local link;
local mask;
local i = 1; -- loop counter/indexer
local n = 1; -- output table indexer
local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors)
local etal = false; -- return value set to true when we find some form of et al. in an author parameter
local last_alias, first_alias, link_alias; -- selected parameter aliases used in error messaging
while true do
last, last_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'err_redundant_parameters', i ); -- search through args for name components beginning at 1
first, first_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'err_redundant_parameters', i );
link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i );
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i );
if last then -- error check |lastn= alias for unknown interwiki link prefix; done here because this is where we have the parameter name
local project, language = interwiki_prefixen_get (last, true); -- true because we expect interwiki links in |lastn= to be wikilinked
if nil == project and nil == language then -- when both are nil
utilities.set_message ('err_bad_paramlink', last_alias); -- not known, emit an error message -- TODO: err_bad_interwiki?
last = utilities.remove_wiki_link (last); -- remove wikilink markup; show display value only
end
end
if link then -- error check |linkn= alias for unknown interwiki link prefix
local project, language = interwiki_prefixen_get (link, false); -- false because wiki links in |author-linkn= is an error
if nil == project and nil == language then -- when both are nil
utilities.set_message ('err_bad_paramlink', link_alias); -- not known, emit an error message -- TODO: err_bad_interwiki?
link = nil; -- unset so we don't link
link_alias = nil;
end
end
last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al.
first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al.
last, first = name_checks (last, first, list_name, last_alias, first_alias); -- multiple names, extraneous annotation, etc. checks
if first and not last then -- if there is a firstn without a matching lastn
local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias
utilities.set_message ('err_first_missing_last', {
first_alias, -- param name of alias missing its mate
first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form
}); -- add this error message
elseif not first and not last then -- if both firstn and lastn aren't found, are we done?
count = count + 1; -- number of times we haven't found last and first
if 2 <= count then -- two missing names and we give up
break; -- normal exit or there is a two-name hole in the list; can't tell which
end
else -- we have last with or without a first
link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup
if first then
link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup
end
names[n] = {last = last, first = first, link = link, mask = mask, corporate = false}; -- add this name to our names list (corporate for |vauthors= only)
n = n + 1; -- point to next location in the names table
if 1 == count then -- if the previous name was missing
utilities.set_message ('err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}); -- add this error message
end
count = 0; -- reset the counter, we're looking for two consecutive missing names
end
i = i + 1; -- point to next args location
end
return names, etal; -- all done, return our list of names and the etal flag
end
--[[--------------------------< N A M E _ T A G _ G E T >------------------------------------------------------
attempt to decode |language=<lang_param> and return language name and matching tag; nil else.
This function looks for:
<lang_param> as a tag in cfg.lang_tag_remap{}
<lang_param> as a name in cfg.lang_name_remap{}
<lang_param> as a name in cfg.mw_languages_by_name_t
<lang_param> as a tag in cfg.mw_languages_by_tag_t
when those fail, presume that <lang_param> is an IETF-like tag that MediaWiki does not recognize. Strip all
script, region, variant, whatever subtags from <lang_param> to leave just a two or three character language tag
and look for the new <lang_param> in cfg.mw_languages_by_tag_t{}
on success, returns name (in properly capitalized form) and matching tag (in lowercase); on failure returns nil
]]
local function name_tag_get (lang_param)
local lang_param_lc = mw.ustring.lower (lang_param); -- use lowercase as an index into the various tables
local name;
local tag;
name = cfg.lang_tag_remap[lang_param_lc]; -- assume <lang_param_lc> is a tag; attempt to get remapped language name
if name then -- when <name>, <lang_param> is a tag for a remapped language name
if cfg.lang_name_remap[name:lower()][2] ~= lang_param_lc then
utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added
return name, cfg.lang_name_remap[name:lower()][2]; -- so return name and tag from lang_name_remap[name]; special case to xlate sr-ec and sr-el to sr-cyrl and sr-latn
end
return name, lang_param_lc; -- so return <name> from remap and <lang_param_lc>
end
tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags
name = cfg.lang_tag_remap[tag]; -- attempt to get remapped language name with language subtag only
if name then -- when <name>, <tag> is a tag for a remapped language name
return name, tag; -- so return <name> from remap and <tag>
end
if cfg.lang_name_remap[lang_param_lc] then -- not a remapped tag, assume <lang_param_lc> is a name; attempt to get remapped language tag
return cfg.lang_name_remap[lang_param_lc][1], cfg.lang_name_remap[lang_param_lc][2]; -- for this <lang_param_lc>, return a (possibly) new name and appropriate tag
end
name = cfg.mw_languages_by_tag_t[lang_param_lc]; -- assume that <lang_param_lc> is a tag; attempt to get its matching language name
if name then
return name, lang_param_lc; -- <lang_param_lc> is a tag so return it and <name>
end
tag = cfg.mw_languages_by_name_t[lang_param_lc]; -- assume that <lang_param_lc> is a language name; attempt to get its matching tag
if tag then
return cfg.mw_languages_by_tag_t[tag], tag; -- <lang_param_lc> is a name so return the name from the table and <tag>
end
tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- is <lang_param_lc> an IETF-like tag that MediaWiki doesn't recognize? <tag> gets the language subtag; nil else
if tag then
name = cfg.mw_languages_by_tag_t[tag]; -- attempt to get a language name using the shortened <tag>
if name then
return name, tag; -- <lang_param_lc> is an unrecognized IETF-like tag so return <name> and language subtag
end
end
end
--[[-------------------< L A N G U A G E _ P A R A M E T E R >------------------
Gets language name from a provided two- or three-character ISO 639 code. If a code
is recognized by MediaWiki, use the returned name; if not, then use the value that
was provided with the language parameter.
When |language= contains a recognized language (either code or name), the page is
assigned to the category for that code: Category:Norwegian-language sources (no).
For valid three-character code languages, the page is assigned to the single category
for '639-2' codes: Category:CS1 ISO 639-2 language sources.
Languages that are the same as the local wiki are not categorized. MediaWiki does
not recognize three-character equivalents of two-character codes: code 'ar' is
recognized but code 'ara' is not.
This function supports multiple languages in the form |language=nb, French, th
where the language names or codes are separated from each other by commas with
optional space characters.
]]
local function language_parameter (lang)
local tag; -- some form of IETF-like language tag; language subtag with optional region, sript, vatiant, etc subtags
local lang_subtag; -- ve populates |language= with mostly unecessary region subtags that MediaWiki does not recognize; this is the base language subtag
local name; -- the language name
local language_list = {}; -- table of language names to be rendered
local names_t = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list
for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag; for now, ignore linter warning
name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang>; <name> has proper capitalization; <tag> is lowercase
if utilities.is_set (tag) then
lang_subtag = tag:gsub ('^(%a%a%a?)%-.*', '%1'); -- for categorization, strip any IETF-like tags from language tag
if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language
if 2 == lang_subtag:len() then -- and is a two-character tag
utilities.add_prop_cat ('foreign-lang-source', {name, tag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization
else -- or is a recognized language (but has a three-character tag)
utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template?
end
elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled
utilities.add_prop_cat ('local-lang-source', {name, lang_subtag}); -- categorize it
end
else
name = lang; -- return whatever <lang> has so that we show something
utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added
end
table.insert (language_list, name);
end
name = utilities.make_sep_list (#language_list, language_list);
if (1 == #language_list) and (lang_subtag == cfg.this_wiki_code) then -- when only one language, find lang name in this wiki lang name; for |language=en-us, 'English' in 'American English'
return ''; -- if one language and that language is this wiki's return an empty string (no annotation)
end
return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)'
--[[ TODO: should only return blank or name rather than full list
so we can clean up the bunched parenthetical elements Language, Type, Format
]]
end
--[[-----------------------< S E T _ C S _ S T Y L E >--------------------------
Gets the default CS style configuration for the given mode.
Returns default separator and either postscript as passed in or the default.
In CS1, the default postscript and separator are '.'.
In CS2, the default postscript is the empty string and the default separator is ','.
]]
local function set_cs_style (postscript, mode)
if utilities.is_set(postscript) then
-- emit a maintenance message if user postscript is the default cs1 postscript
-- we catch the opposite case for cs2 in set_style
if mode == 'cs1' and postscript == cfg.presentation['ps_' .. mode] then
utilities.set_message ('maint_postscript');
end
else
postscript = cfg.presentation['ps_' .. mode];
end
return cfg.presentation['sep_' .. mode], postscript;
end
--[[--------------------------< S E T _ S T Y L E >-----------------------------
Sets the separator and postscript styles. Checks the |mode= first and the
#invoke CitationClass second. Removes the postscript if postscript == none.
]]
local function set_style (mode, postscript, cite_class)
local sep;
if 'cs2' == mode then
sep, postscript = set_cs_style (postscript, 'cs2');
elseif 'cs1' == mode then
sep, postscript = set_cs_style (postscript, 'cs1');
elseif 'citation' == cite_class then
sep, postscript = set_cs_style (postscript, 'cs2');
else
sep, postscript = set_cs_style (postscript, 'cs1');
end
if cfg.keywords_xlate[postscript:lower()] == 'none' then
-- emit a maintenance message if user postscript is the default cs2 postscript
-- we catch the opposite case for cs1 in set_cs_style
if 'cs2' == mode or ('cs1' ~= mode and 'citation' == cite_class) then -- {{citation |title=Title |mode=cs1 |postscript=none}} should not emit maint message
utilities.set_message ('maint_postscript');
end
postscript = '';
end
return sep, postscript
end
--[=[-------------------------< I S _ P D F >-----------------------------------
Determines if a URL has the file extension that is one of the PDF file extensions
used by [[MediaWiki:Common.css]] when applying the PDF icon to external links.
returns true if file extension is one of the recognized extensions, else false
]=]
local function is_pdf (url)
return url:match ('%.pdf$') or url:match ('%.PDF$') or
url:match ('%.pdf[%?#]') or url:match ('%.PDF[%?#]') or
url:match ('%.PDF#') or url:match ('%.pdf#');
end
--[[--------------------------< S T Y L E _ F O R M A T >-----------------------
Applies CSS style to |format=, |chapter-format=, etc. Also emits an error message
if the format parameter does not have a matching URL parameter. If the format parameter
is not set and the URL contains a file extension that is recognized as a PDF document
by MediaWiki's commons.css, this code will set the format parameter to (PDF) with
the appropriate styling.
]]
local function style_format (format, url, fmt_param, url_param)
if utilities.is_set (format) then
format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize
if not utilities.is_set (url) then
utilities.set_message ('err_format_missing_url', {fmt_param, url_param}); -- add an error message
end
elseif is_pdf (url) then -- format is not set so if URL is a PDF file then
format = utilities.wrap_style ('format', 'PDF'); -- set format to PDF
else
format = ''; -- empty string for concatenation
end
return format;
end
--[[---------------------< G E T _ D I S P L A Y _ N A M E S >------------------
Returns a number that defines the number of names displayed for author and editor
name lists and a Boolean flag to indicate when et al. should be appended to the name list.
When the value assigned to |display-xxxxors= is a number greater than or equal to zero,
return the number and the previous state of the 'etal' flag (false by default
but may have been set to true if the name list contains some variant of the text 'et al.').
When the value assigned to |display-xxxxors= is the keyword 'etal', return a number
that is one greater than the number of authors in the list and set the 'etal' flag true.
This will cause the list_people() to display all of the names in the name list followed by 'et al.'
In all other cases, returns nil and the previous state of the 'etal' flag.
inputs:
max: A['DisplayAuthors'] or A['DisplayEditors'], etc; a number or some flavor of etal
count: #a or #e
list_name: 'authors' or 'editors'
etal: author_etal or editor_etal
This function sets an error message when |display-xxxxors= value greater than or equal to number of names but
not when <max> comes from {{cs1 config}} global settings. When using global settings, <param> is set to the
keyword 'cs1 config' which is used to supress the normal error. Error is suppressed because it is to be expected
that some citations in an article will have the same or fewer names that the limit specified in {{cs1 config}}.
]]
local function get_display_names (max, count, etal, param)
if utilities.is_set (max) then
if 'etal' == cfg.keywords_xlate[max:lower():gsub("[ '%.]", '')] then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
max = count + 1; -- number of authors + 1 so display all author name plus et al.
etal = true; -- overrides value set by extract_names()
elseif max:match ('^%d+$') then -- if is a string of numbers
max = tonumber (max); -- make it a number
if (max >= count) and ('cs1 config' ~= param) then -- error when local |display-xxxxors= value greater than or equal to number of names; not an error when using global setting
utilities.set_message ('err_disp_name', {param, max}); -- add error message
max = nil;
end
else -- not a valid keyword or number
utilities.set_message ('err_disp_name', {param, max}); -- add error message
max = nil; -- unset; as if |display-xxxxors= had not been set
end
end
return max, etal;
end
--[[----------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >---------------
Adds error if |page=, |pages=, |quote-page=, |quote-pages= has what appears to be
some form of p. or pp. abbreviation in the first characters of the parameter content.
check page for extraneous p, p., pp, pp., pg, pg. at start of parameter value:
good pattern: '^P[^%.P%l]' matches when page begins PX or P# but not Px
where x and X are letters and # is a digit
bad pattern: '^[Pp][PpGg]' matches when page begins pp, pP, Pp, PP, pg, pG, Pg, PG
]]
local function extra_text_in_page_check (val, name)
if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns
if val:match (pattern) then -- when a match, error so
utilities.set_message ('err_extra_text_pages', name); -- add error message
return; -- and done
end
end
end
end
--[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------
Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. Applies to
both; this function looks for issue text in both |issue= and |volume= and looks for volume-like text in |voluem=
and |issue=.
For |volume=:
'V.', or 'Vol.' (with or without the dot) abbreviations or 'Volume' in the first characters of the parameter
content (all case insensitive). 'V' and 'v' (without the dot) are presumed to be roman numerals so
are allowed.
For |issue=:
'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the
parameter content (all case insensitive); numero styling: 'n°' with degree sign U+00B0, and № precomposed
numero sign U+2116.
Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or
whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module.
<val> is |volume= or |issue= parameter value
<name> is |volume= or |issue= parameter name for error message
<selector> is 'v' for |volume=, 'i' for |issue=
sets error message on failure; returns nothing
]]
local function extra_text_in_vol_iss_check (val, name, selector)
if not utilities.is_set (val) then
return;
end
local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue';
local accept_val; -- for now, ignore linter warning
val, accept_val = utilities.has_accept_as_written (val);
--if accept_val then -- if uncomment this, |volume=((vol. 1)) suppresses error
-- return;
--end
--val = mw.text.unstripNoWiki (val); -- if uncomment this, |volume=<nowiki>vol. 1</nowiki> shows error
val = val:lower(); -- force parameter value to lower case
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.vi_patterns_t) do -- spin through the sequence table of patterns
if val:match (pattern) then -- when a match, error so
utilities.set_message (handler, name); -- add error message
return; -- and done
end
end
end
--[=[-------------------------< G E T _ V _ N A M E _ T A B L E >----------------------------------------------
split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled
parentheses to also have commas; in the old version of the code, the doubled parentheses were included in the
rendered citation and in the metadata. Individual author names may be wikilinked
|vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.))
]=]
local function get_v_name_table (vparam, output_table, output_link_table)
local _, accept = utilities.has_accept_as_written (vparam);
if accept then
utilities.add_prop_cat ('vanc-accept'); -- add properties category
end
local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas
local wl_type, label, link; -- wl_type not used here; just a placeholder
local i = 1;
while name_table[i] do
if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses
local name = name_table[i];
i = i + 1; -- bump indexer to next segment
while name_table[i] do
name = name .. ', ' .. name_table[i]; -- concatenate with previous segments
if name_table[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses
break; -- and done reassembling so
end
i = i + 1; -- bump indexer
end
table.insert (output_table, name); -- and add corporate name to the output table
table.insert (output_link_table, ''); -- no wikilink
else
wl_type, label, link = utilities.is_wikilink (name_table[i]); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]
table.insert (output_table, label); -- add this name
if 1 == wl_type then
table.insert (output_link_table, label); -- simple wikilink [[D]]
else
table.insert (output_link_table, link); -- no wikilink or [[L|D]]; add this link if there is one, else empty string
end
end
i = i + 1;
end
return output_table;
end
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >--------------------------------
This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and
|xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does.
Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
tests, are wrapped in doubled parentheses ((corporate name)) to suppress the format tests.
Supports generational suffixes Jr, 2nd, 3rd, 4th–6th.
This function sets the Vancouver error when a required comma is missing and when there is a space between an author's initials.
]]
local function parse_vauthors_veditors (args, vparam, list_name)
local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn=
local v_name_table = {};
local v_link_table = {}; -- when name is wikilinked, targets go in this table
local etal = false; -- return value set to true when we find some form of et al. vauthors parameter
local last, first, link, mask, suffix;
local corporate = false;
vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period)
v_name_table = get_v_name_table (vparam, v_name_table, v_link_table); -- names are separated by commas
for i, v_name in ipairs(v_name_table) do
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
local accept_name;
v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name>
if accept_name then
last = v_name;
corporate = true; -- flag used in list_people()
elseif string.find(v_name, "%s") then
if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters;
add_vanc_error (cfg.err_msg_supl.punctuation, i);
end
local lastfirst_t = mw.text.split(v_name, "%s+");
first = table.remove (lastfirst_t); -- removes and returns value of last element in table which should be initials or generational suffix
if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters
suffix = first; -- not initials so assume that whatever we got is a generational suffix
first = table.remove (lastfirst_t); -- get what should be the initials from the table
end
last = table.concat (lastfirst_t, ' '); -- returns a string that is the concatenation of all other names that are not initials and generational suffix
if not utilities.is_set (last) then
first = ''; -- unset
last = v_name; -- last empty because something wrong with first
add_vanc_error (cfg.err_msg_supl.name, i);
end
if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then
add_vanc_error (cfg.err_msg_supl['missing comma'], i); -- matches last II last; the case when a comma is missing
end
if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test
add_vanc_error (cfg.err_msg_supl.initials, i); -- matches a space between two initials
end
else
last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this?
end
if utilities.is_set (first) then
if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else
add_vanc_error (cfg.err_msg_supl.initials, i); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials
end
is_good_vanc_name (last, first, suffix, i); -- check first and last before restoring the suffix which may have a non-Latin digit
if utilities.is_set (suffix) then
first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials
suffix = ''; -- unset so we don't add this suffix to all subsequent names
end
else
if not corporate then
is_good_vanc_name (last, '', nil, i);
end
end
link = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ) or v_link_table[i];
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i );
names[i] = {last = last, first = first, link = link, mask = mask, corporate = corporate}; -- add this assembled name to our names list
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E >------------------------
Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or
select one of |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list.
Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest;
|editorn= (and aliases) highest and |veditors= lowest (support for |editors= withdrawn)
When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second
test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better
way to do this, I just haven't discovered what that way is.
Emits an error message when more than one xxxxor name source is provided.
In this function, vxxxxors = vauthors or veditors; xxxxors = authors as appropriate.
]]
local function select_author_editor_source (vxxxxors, xxxxors, args, list_name)
local lastfirst = false;
if utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice in case we have a |first1= without a |last1=; this ...
utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors=
utilities.select_one ( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) or
utilities.select_one ( args, cfg.aliases[list_name .. '-First'], 'none', 2 ) then
lastfirst = true;
end
if (utilities.is_set (vxxxxors) and true == lastfirst) or -- these are the three error conditions
(utilities.is_set (vxxxxors) and utilities.is_set (xxxxors)) or
(true == lastfirst and utilities.is_set (xxxxors)) then
utilities.set_message ('err_redundant_parameters',
utilities.substitute (cfg.special_case_translation.name_list_params,
('AuthorList' == list_name) and cfg.special_case_translation.author or cfg.special_case_translation.editor)); -- add error message
end
if true == lastfirst then return 1 end; -- return a number indicating which author name source to use
if utilities.is_set (vxxxxors) then return 2 end;
if utilities.is_set (xxxxors) then return 3 end;
return 1; -- no authors so return 1; this allows missing author name test to run in case there is a first without last
end
--[[--------------------------< I S _ V A L I D _ P A R A M E T E R _ V A L U E >------------------------------
This function is used to validate a parameter's assigned value for those parameters that have only a limited number
of allowable values (yes, y, true, live, dead, etc.). When the parameter value has not been assigned a value (missing
or empty in the source template) the function returns the value specified by ret_val. If the parameter value is one
of the list of allowed values returns the translated value; else, emits an error message and returns the value
specified by ret_val.
TODO: explain <invert>
]]
local function is_valid_parameter_value (value, name, possible, ret_val, invert)
if not utilities.is_set (value) then
return ret_val; -- an empty parameter is ok
end
if (not invert and utilities.in_array (value, possible)) then -- normal; <value> is in <possible> table
return cfg.keywords_xlate[value]; -- return translation of parameter keyword
elseif invert and not utilities.in_array (value, possible) then -- invert; <value> is not in <possible> table
return value; -- return <value> as it is
else
utilities.set_message ('err_invalid_param_val', {name, value}); -- not an allowed value so add error message
return ret_val;
end
end
--[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >----------------------------------------
This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space
when the last character is not a sepc character or when the last three characters are not sepc followed by two
closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a
single space character.
]]
local function terminate_name_list (name_list, sepc)
if (string.sub (name_list, -3, -1) == sepc .. '. ') then -- if already properly terminated
return name_list; -- just return the name list
elseif (string.sub (name_list, -1, -1) == sepc) or (string.sub (name_list, -3, -1) == sepc .. ']]') then -- if last name in list ends with sepc char
return name_list .. " "; -- don't add another
else
return name_list .. sepc .. ' '; -- otherwise terminate the name list
end
end
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >-----------------------------------------
returns the concatenation of the formatted volume and issue (or journal article number) parameters as a single
string; or formatted volume or formatted issue, or an empty string if neither are set.
]]
local function format_volume_issue (volume, issue, article, cite_class, origin, sepc, lower)
if not utilities.is_set (volume) and not utilities.is_set (issue) and not utilities.is_set (article) then
return '';
end
-- same condition as in format_pages_sheets()
local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin);
local is_numeric_vol = volume and (volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$')); -- is only uppercase roman numerals or only digits?
local is_long_vol = volume and (4 < mw.ustring.len(volume)); -- is |volume= value longer than 4 characters?
if volume and (not is_numeric_vol and is_long_vol) then -- when not all digits or Roman numerals, is |volume= longer than 4 characters?
utilities.add_prop_cat ('long-vol'); -- yes, add properties cat
end
if is_journal then -- journal-style formatting
local vol = '';
if utilities.is_set (volume) then
if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals?
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, volume}); -- render in bold face
elseif is_long_vol then -- not all digits or Roman numerals; longer than 4 characters?
vol = utilities.substitute (cfg.messages['j-vol'], {sepc, utilities.hyphen_to_dash (volume)}); -- not bold
else -- four or fewer characters
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, utilities.hyphen_to_dash (volume)}); -- bold
end
end
vol = vol .. (utilities.is_set (issue) and utilities.substitute (cfg.messages['j-issue'], issue) or '')
vol = vol .. (utilities.is_set (article) and utilities.substitute (cfg.messages['j-article-num'], article) or '')
return vol;
end
if 'podcast' == cite_class and utilities.is_set (issue) then
return wrap_msg ('issue', {sepc, issue}, lower);
end
if 'conference' == cite_class and utilities.is_set (article) then -- |article-number= supported only in journal and conference cites
if utilities.is_set (volume) and utilities.is_set (article) then -- both volume and article number
return wrap_msg ('vol-art', {sepc, utilities.hyphen_to_dash (volume), article}, lower);
elseif utilities.is_set (article) then -- article number alone; when volume alone, handled below
return wrap_msg ('art', {sepc, article}, lower);
end
end
-- all other types of citation
if utilities.is_set (volume) and utilities.is_set (issue) then
return wrap_msg ('vol-no', {sepc, utilities.hyphen_to_dash (volume), issue}, lower);
elseif utilities.is_set (volume) then
return wrap_msg ('vol', {sepc, utilities.hyphen_to_dash (volume)}, lower);
else
return wrap_msg ('issue', {sepc, issue}, lower);
end
end
--[[-------------------------< F O R M A T _ P A G E S _ S H E E T S >-----------------------------------------
adds static text to one of |page(s)= or |sheet(s)= values and returns it with all of the others set to empty strings.
The return order is:
page, pages, sheet, sheets
Singular has priority over plural when both are provided.
]]
local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower)
if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators
if utilities.is_set (sheet) then
if 'journal' == origin then
return '', '', wrap_msg ('j-sheet', sheet, lower), '';
else
return '', '', wrap_msg ('sheet', {sepc, sheet}, lower), '';
end
elseif utilities.is_set (sheets) then
if 'journal' == origin then
return '', '', '', wrap_msg ('j-sheets', sheets, lower);
else
return '', '', '', wrap_msg ('sheets', {sepc, sheets}, lower);
end
end
end
local is_journal = 'journal' == cite_class or (utilities.in_array (cite_class, {'citation', 'map', 'interview'}) and 'journal' == origin);
if utilities.is_set (page) then
if is_journal then
return utilities.substitute (cfg.messages['j-page(s)'], page), '', '', '';
elseif not nopp then
return utilities.substitute (cfg.messages['p-prefix'], {sepc, page}), '', '', '';
else
return utilities.substitute (cfg.messages['nopp'], {sepc, page}), '', '', '';
end
elseif utilities.is_set (pages) then
if is_journal then
return utilities.substitute (cfg.messages['j-page(s)'], pages), '', '', '';
elseif tonumber(pages) ~= nil and not nopp then -- if pages is only digits, assume a single page number
return '', utilities.substitute (cfg.messages['p-prefix'], {sepc, pages}), '', '';
elseif not nopp then
return '', utilities.substitute (cfg.messages['pp-prefix'], {sepc, pages}), '', '';
else
return '', utilities.substitute (cfg.messages['nopp'], {sepc, pages}), '', '';
end
end
return '', '', '', ''; -- return empty strings
end
--[[--------------------------< I N S O U R C E _ L O C _ G E T >----------------------------------------------
returns one of the in-source locators: page, pages, or at.
If any of these are interwiki links to Wikisource, returns the label portion of the interwiki-link as plain text
for use in COinS. This COinS thing is done because here we convert an interwiki-link to an external link and
add an icon span around that; get_coins_pages() doesn't know about the span. TODO: should it?
TODO: add support for sheet and sheets?; streamline;
TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned
to a new name)?
]]
local function insource_loc_get (page, page_orig, pages, pages_orig, at)
local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?)
if utilities.is_set (page) then
if utilities.is_set (pages) or utilities.is_set (at) then
pages = ''; -- unset the others
at = '';
end
extra_text_in_page_check (page, page_orig); -- emit error message when |page= value begins with what looks like p., pp., etc.
ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label
if ws_url then
page = external_link (ws_url, ws_label .. ' ', 'ws link in page'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
page = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, page});
coins_pages = ws_label;
end
elseif utilities.is_set (pages) then
if utilities.is_set (at) then
at = ''; -- unset
end
extra_text_in_page_check (pages, pages_orig); -- emit error message when |page= value begins with what looks like p., pp., etc.
ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label
if ws_url then
pages = external_link (ws_url, ws_label .. ' ', 'ws link in pages'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
pages = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, pages});
coins_pages = ws_label;
end
elseif utilities.is_set (at) then
ws_url, ws_label, L = wikisource_url_make (at); -- make ws URL from |at= interwiki link; link portion L becomes tooltip label
if ws_url then
at = external_link (ws_url, ws_label .. ' ', 'ws link in at'); -- space char after label to move icon away from in-source text; TODO: a better way to do this?
at = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, at});
coins_pages = ws_label;
end
end
return page, pages, at, coins_pages;
end
--[[--------------------------< I S _ U N I Q U E _ A R C H I V E _ U R L >------------------------------------
add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value
]]
local function is_unique_archive_url (archive, url, c_url, source, date)
if utilities.is_set (archive) then
if archive == url or archive == c_url then
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); -- add error message
return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url=
end
end
return archive, date;
end
--[=[-------------------------< A R C H I V E _ U R L _ C H E C K >--------------------------------------------
Check archive.org URLs to make sure they at least look like they are pointing at valid archives and not to the
save snapshot URL or to calendar pages. When the archive URL is 'https://web.archive.org/save/' (or http://...)
archive.org saves a snapshot of the target page in the URL. That is something that Wikipedia should not allow
unwitting readers to do.
When the archive.org URL does not have a complete timestamp, archive.org chooses a snapshot according to its own
algorithm or provides a calendar 'search' result. [[WP:ELNO]] discourages links to search results.
This function looks at the value assigned to |archive-url= and returns empty strings for |archive-url= and
|archive-date= and an error message when:
|archive-url= holds an archive.org save command URL
|archive-url= is an archive.org URL that does not have a complete timestamp (YYYYMMDDhhmmss 14 digits) in the
correct place
otherwise returns |archive-url= and |archive-date=
There are two mostly compatible archive.org URLs:
//web.archive.org/<timestamp>... -- the old form
//web.archive.org/web/<timestamp>... -- the new form
The old form does not support or map to the new form when it contains a display flag. There are four identified flags
('id_', 'js_', 'cs_', 'im_') but since archive.org ignores others following the same form (two letters and an underscore)
we don't check for these specific flags but we do check the form.
This function supports a preview mode. When the article is rendered in preview mode, this function may return a modified
archive URL:
for save command errors, return undated wildcard (/*/)
for timestamp errors when the timestamp has a wildcard, return the URL unmodified
for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/)
A secondary function is to return an archive-url timestamp from those archive urls that have them. The timestamp
is used by validation.archive_date_check() to see if the value in |archive-date= matches the timestamp in the
archive url.
]=]
local function archive_url_check (url, date)
local err_msg; -- start with the error message empty
local path, timestamp, flag; -- portions of the archive.org URL
local function is_ts_date_valid (ts, origin_date) -- local function to validate archive url taimestamp date; time ignored
local y, m, d = ts:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- split into parts
if y and validation.is_valid_date (y, m, d) and (tonumber (y) >= 1996) then
return true, tonumber (y) >= origin_date; -- <origin_date> is 1996 for archive.org
end
end
if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL
return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate
end
if url:match('//web%.archive%.org/save/') then -- if a save command URL, we don't want to allow saving of the target page
err_msg = cfg.err_msg_supl.save;
url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL
elseif url:match('//liveweb%.archive%.org/') then
err_msg = cfg.err_msg_supl.liveweb;
else
path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation
if not path then -- malformed in some way; pattern did not match
err_msg = cfg.err_msg_supl.timestamp;
elseif 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here
err_msg = cfg.err_msg_supl.timestamp;
if '*' ~= flag then
local replacement = timestamp:match ('^%d%d%d%d%d%d') or timestamp:match ('^%d%d%d%d'); -- get the first 6 (YYYYMM) or first 4 digits (YYYY)
if replacement then -- nil if there aren't at least 4 digits (year)
replacement = replacement .. string.rep ('0', 14 - replacement:len()); -- year or yearmo (4 or 6 digits) zero-fill to make 14-digit timestamp
url=url:gsub ('(//web%.archive%.org/[^%d]*)%d[^/]*', '%1' .. replacement .. '*', 1) -- for preview, modify ts to 14 digits plus splat for calendar display
end
end
elseif not is_ts_date_valid (timestamp, 1996) then -- is ymd portion of timestamp a valid date?
err_msg = cfg.err_msg_supl.timestamp;
timestamp = nil; -- unset because invalid
elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element
err_msg = cfg.err_msg_supl.path;
elseif utilities.is_set (flag) and not utilities.is_set (path) then -- flag not allowed with the old form URL (without the 'web/' path element)
err_msg = cfg.err_msg_supl.flag;
elseif utilities.is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element)
err_msg = cfg.err_msg_supl.flag;
else
return url, date, timestamp; -- return ArchiveURL, ArchiveDate, and timestamp from |archive-url=
end
end
-- if here, something not right so
utilities.set_message ('err_archive_url', {err_msg}); -- add error message and
if is_preview_mode then
return url, date, timestamp; -- preview mode so return ArchiveURL, ArchiveDate, and timestamp from |archive-url=
else
return '', ''; -- return empty strings for ArchiveURL and ArchiveDate
end
end
--[[--------------------------< P L A C E _ C H E C K >--------------------------------------------------------
check |place=, |publication-place=, |location= to see if these params include digits. This function added because
many editors misuse location to specify the in-source location (|page(s)= and |at= are supposed to do that)
returns the original parameter value without modification; added maint cat when parameter value contains digits
]]
local function place_check (param_val)
if not utilities.is_set (param_val) then -- parameter empty or omitted
return param_val; -- return that empty state
end
if mw.ustring.find (param_val, '%d') then -- not empty, are there digits in the parameter value
utilities.set_message ('maint_location'); -- yep, add maint cat
end
return param_val; -- and done
end
--[[--------------------------< I S _ A R C H I V E D _ C O P Y >----------------------------------------------
compares |title= to 'Archived copy' (placeholder added by bots that can't find proper title); if matches, return true; nil else
]]
local function is_archived_copy (title)
title = mw.ustring.lower(title); -- switch title to lower case
if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy'
return true;
elseif cfg.special_case_translation.archived_copy['local'] then
if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script
return true;
end
end
end
--[[--------------------------< D I S P L A Y _ N A M E S _ S E L E C T >--------------------------------------
for any of the |display-authors=, |display-editors=, etc parameters, select either the local or global setting.
When both are present, look at <local_display_names> value. When the value is some sort of 'et al.'string,
special handling is required.
When {{cs1 config}} has |display-<namelist>= AND this template has |display-<namelist>=etal AND:
the number of names specified by <number_of_names> is:
greater than the number specified in the global |display-<namelist>= parameter (<global_display_names>)
use global |display-<namelist>= parameter value
set overridden maint category
less than or equal to the number specified in the global |display-<namelist>= parameter
use local |display-<namelist>= parameter value
The purpose of this function is to prevent categorizing a template that has fewer names than the global setting
to keep the etal annotation specified by <local_display_names>.
]]
local function display_names_select (global_display_names, local_display_names, param_name, number_of_names)
if global_display_names and utilities.is_set (local_display_names) then -- when both
if 'etal' == local_display_names:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
number_of_names = tonumber (number_of_names); -- convert these to numbers for comparison
local global_display_names_num = tonumber (global_display_names); -- <global_display_names> not set when parameter value is not digits
if number_of_names > global_display_names_num then -- template has more names than global config allows to be displayed?
utilities.set_message ('maint_overridden_setting'); -- set a maint message because global is overriding local |display-<namelist>=etal
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
else
return local_display_names, param_name; -- return local because fewer names so let <local_display_names> control
end
end
-- here when <global_display_names> and <local_display_names> both numbers; <global_display_names> controls
utilities.set_message ('maint_overridden_setting'); -- set a maint message
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
end
-- here when only one of <global_display_names> or <local_display_names> set
if global_display_names then
return global_display_names, 'cs1 config'; -- return global with spoof parameter name (for get_display_names())
else
return local_display_names, param_name; -- return local
end
end
--[[--------------------------< M O D E _ S E T >--------------------------------------------------------------
fetch global mode setting from {{cs1 config}} (if present) or from |mode= (if present); global setting overrides
local |mode= parameter value. When both are present, emit maintenance message
]]
local function mode_set (Mode, Mode_origin)
local mode;
if cfg.global_cs1_config_t['Mode'] then -- global setting in {{cs1 config}}; nil when empty or assigned value invalid
mode = is_valid_parameter_value (cfg.global_cs1_config_t['Mode'], 'cs1 config: mode', cfg.keywords_lists['mode'], ''); -- error messaging 'param' here is a hoax
else
mode = is_valid_parameter_value (Mode, Mode_origin, cfg.keywords_lists['mode'], '');
end
if cfg.global_cs1_config_t['Mode'] and utilities.is_set (Mode) then -- when template has |mode=<something> which global setting has overridden
utilities.set_message ('maint_overridden_setting'); -- set a maint message
end
return mode;
end
--[[--------------------------< Q U O T E _ M A K E >----------------------------------------------------------
create quotation from |quote=, |trans-quote=, and/or script-quote= with or without |quote-page= or |quote-pages=
when any of those three quote parameters are set, this function unsets <PostScript>. When none of those parameters
are set, |quote-page= and |quote-pages= are unset to nil so that they are not included in the template's metadata
]]
local function quote_make (quote, trans_quote, script_quote, quote_page, quote_pages, nopp, sepc, postscript)
if utilities.is_set (quote) or utilities.is_set (trans_quote) or utilities.is_set (script_quote) then
if utilities.is_set (quote) then
if quote:sub(1, 1) == '"' and quote:sub(-1, -1) == '"' then -- if first and last characters of quote are quote marks
quote = quote:sub(2, -2); -- strip them off
end
end
quote = kern_quotes (quote); -- kern if needed
quote = utilities.wrap_style ('quoted-text', quote ); -- wrap in <q>...</q> tags
if utilities.is_set (script_quote) then
quote = script_concatenate (quote, script_quote, 'script-quote'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after quote is wrapped
end
if utilities.is_set (trans_quote) then
if trans_quote:sub(1, 1) == '"' and trans_quote:sub(-1, -1) == '"' then -- if first and last characters of |trans-quote are quote marks
trans_quote = trans_quote:sub(2, -2); -- strip them off
end
quote = quote .. " " .. utilities.wrap_style ('trans-quoted-title', trans_quote );
end
if utilities.is_set (quote_page) or utilities.is_set (quote_pages) then -- add page prefix
local quote_prefix = '';
if utilities.is_set (quote_page) then
extra_text_in_page_check (quote_page, 'quote-page'); -- add to maint cat if |quote-page= value begins with what looks like p., pp., etc.
if not nopp then
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, quote_page});
else
quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, quote_page});
end
elseif utilities.is_set (quote_pages) then
extra_text_in_page_check (quote_pages, 'quote-pages'); -- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc.
if tonumber(quote_pages) ~= nil and not nopp then -- if only digits, assume single page
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, quote_pages});
elseif not nopp then
quote_prefix = utilities.substitute (cfg.messages['pp-prefix'], {sepc, quote_pages});
else
quote_prefix = utilities.substitute (cfg.messages['nopp'], {sepc, quote_pages});
end
end
quote = quote_prefix .. ": " .. quote;
else
quote = sepc .. " " .. quote;
end
postscript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set
elseif utilities.is_set (quote_page) or utilities.is_set (quote_pages) then
quote_page = nil; -- unset; these require |quote=; TODO: error message?
quote_pages = nil;
end
return quote, quote_page, quote_pages, postscript;
end
--[[--------------------------< C H E C K _ P U B L I S H E R _ N A M E >--------------------------------------
look for variations of '<text>: <text>' that might be '<location>: <publisher>' in |publisher= parameter value.
when found, emit a maintenance message; return nil else
<publisher> is the value assigned to |publisher= or |institution=
]]
local function check_publisher_name (publisher)
local patterns_t = {
'^[%w%s]+%s*:%s*[%w%s]+$', -- plain text <location>: <publisher>
'^%[+[%w%s:|]+%]+%s*:%s*[%w%s]+$', -- partially wikilinked [[<location>]]: <publisher>
'^[%w%s]+%s*:%s*%[+[%w%s:|]+%]+$', -- partially wikilinked <location>: [[<publisher>]]
'^%[+[%w%s:|]+%]+%s*:%s*%[+[%w%s:|]+%]+$', -- wikilinked [[<location>]]: [[<publisher>]]
}
for _, pattern in ipairs (patterns_t) do -- spin through the patterns_t sequence
if mw.ustring.match (publisher, pattern) then -- does this pattern match?
utilities.set_message ('maint_publisher_location'); -- set a maint message
return; -- and done
end
end
end
--[[--------------------------< I S _ P A G E _ A R T _ N U M >------------------------------------------------
compare the trailing (rightmost) characters of the |doi= value against the whole value assigned to |page(s)=.
return boolean true when:
|page(s)= has exactly 8 digits and a dot between the fourth and fifth digits matches the trailing 9 characters
of the |doi= value: |page=12345678 → |page=1234.5678 matches |doi=10.xxxx/yyyy1234.5678
|page(s)= is 5 or more characters and matches |doi= values's trailing characters
|page(s)= begins with a lowercase 'e' and |page(s)= without the 'e' matches |doi= values's trailing
characters: |page=e12345 → |page=12345 matches |doi=10.xxxx/yyyy12345
|page(s)= begins with a uppercase 'CD' followed by (typically) six digits matches |doi= values that ends with
'CDxxxxxx.pubx' (where 'x' is any single digit)
return nil when |page(s)= values:
are ranges separated by underscore, hyphen, emdash, endash, figure dash, or minus character
are comma- or semicolon-separated lists of pages
have external urls (has text 'http')
are digit-only values less than 10000
do not match |doi= values's trailing characters
]]
local function is_page_art_num (page, doi)
if not (utilities.is_set (page) and utilities.is_set (doi)) then -- both required
return; -- abandon; nothing to do
end
if page:match ('[,;_−–—‒%-]') then -- when |page(s)= might be a page range or a separated list of pages
return; -- abandon
end
page = page:lower(); -- because doi names are case insensitive
doi = doi:lower(); -- force these to lowercase for testing
if page:match ('http') then -- when |page(s)= appears to hold a url
return; -- abandon
end
if tonumber (page) then -- is |page(s)= digits only
if 10000 > tonumber (page) then -- when |page(s)= less than 10000
return; -- abandon
end
if doi:match (page .. '$') then -- digits only page number match the last digits in |doi=?
return true;
end
if 8 == page:len() then -- special case when |page(s)= is exactly 8 digits
local dot_page = page:gsub ('(%d%d%d%d)(%d%d%d%d)', '%1.%2'); -- make a |page=xxxx.yyyy version commonly used in |doi=
if doi:match (dot_page .. '$') then -- 8-digit dotted page number match the last characters in |doi=?
return true;
end
end
else -- here when |page(s)= is alpha-numeric
if 4 < page:len() then -- when |page(s)= is five or more characters
if doi:match (page .. '$') then -- alpha-numeric page match the last characters in |doi=?
return true;
end
local epage = page:match ('^e([%w]+)$'); -- if first character of |page= is 'e', remove it
if epage and doi:match (epage .. '$') then -- page number match the last characters in |doi=?
return true;
end
local cdpage = page:match ('^cd%d+$'); -- if first characters of |page= are 'CD' and last characters are digits (typically 6 digits)
if cdpage and doi:match (cdpage .. '%.pub%d$') then -- page number matches doi 'CDxxxxxx.pubx' where 'x' is a digit
return true;
end
end
end
end
--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------
This is the main function doing the majority of the citation formatting.
]]
local function citation0( config, args )
--[[
Load Input Parameters
The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.
]]
local A = argument_wrapper ( args );
-- Pick out the relevant fields from the arguments. Different citation templates
-- define different field names for the same underlying things.
local author_etal;
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors=
local Authors;
local NameListStyle;
if cfg.global_cs1_config_t['NameListStyle'] then -- global setting in {{cs1 config}} overrides local |name-list-style= parameter value; nil when empty or assigned value invalid
NameListStyle = is_valid_parameter_value (cfg.global_cs1_config_t['NameListStyle'], 'cs1 config: name-list-style', cfg.keywords_lists['name-list-style'], ''); -- error messaging 'param' here is a hoax
else
NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], '');
end
if cfg.global_cs1_config_t['NameListStyle'] and utilities.is_set (A['NameListStyle']) then -- when template has |name-list-style=<something> which global setting has overridden
utilities.set_message ('maint_overridden_setting'); -- set a maint message
end
local Collaboration = A['Collaboration'];
do -- to limit scope of selected
local selected = select_author_editor_source (A['Vauthors'], A['Authors'], args, 'AuthorList');
if 1 == selected then
a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn=
elseif 2 == selected then
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be
a, author_etal = parse_vauthors_veditors (args, A['Vauthors'], 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn=
elseif 3 == selected then
Authors = A['Authors']; -- use content of |people= or |credits=; |authors= is deprecated; TODO: constrain |people= and |credits= to cite av media, episode, serial?
end
if utilities.is_set (Collaboration) then
author_etal = true; -- so that |display-authors=etal not required
end
end
local editor_etal;
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors=
do -- to limit scope of selected
local selected = select_author_editor_source (A['Veditors'], nil, args, 'EditorList'); -- support for |editors= withdrawn
if 1 == selected then
e, editor_etal = extract_names (args, 'EditorList'); -- fetch editor list from |editorn= / |editor-lastn= / |editor-firstn=, |editor-linkn=, and |editor-maskn=
elseif 2 == selected then
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be
e, editor_etal = parse_vauthors_veditors (args, args.veditors, 'EditorList'); -- fetch editor list from |veditors=, |editor-linkn=, and |editor-maskn=
end
end
local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= and |script-chapter= aliases
local Chapter_origin = A:ORIGIN ('Chapter');
local ScriptChapter = A['ScriptChapter'];
local ScriptChapter_origin = A:ORIGIN ('ScriptChapter');
local Contribution; -- because contribution is required for contributor(s)
if 'contribution' == Chapter_origin then -- is there a |contribution= parameter?
Contribution = Chapter; -- get the name of the contribution
elseif 'script-contribution' == ScriptChapter_origin then -- no, so is there a |script-contribution= parameter?
Contribution = ScriptChapter; -- get the name of the contribution
end
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (A['Periodical']) then -- |contributor= and |contribution= only supported in book cites
c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn=
if 0 < #c then
if not utilities.is_set (Contribution) then -- |contributor= requires |contribution=
utilities.set_message ('err_contributor_missing_required_param', 'contribution'); -- add missing contribution error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
if 0 == #a then -- |contributor= requires |author=
utilities.set_message ('err_contributor_missing_required_param', 'author'); -- add missing author error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
end
else -- if not a book cite
if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters?
utilities.set_message ('err_contributor_ignored'); -- add contributor ignored error message
end
Contribution = nil; -- unset
end
local Title = A['Title'];
local TitleLink = A['TitleLink'];
local auto_select = ''; -- default is auto
local accept_link;
TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup
if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords
auto_select = TitleLink; -- remember selection for later
TitleLink = ''; -- treat as if |title-link= would have been empty
end
TitleLink = link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wiki-markup in |title-link= or wiki-markup in |title= when |title-link= is set
local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used
if 'map' == config.CitationClass and 'section' == Chapter_origin then
Section = A['Chapter']; -- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}}
Chapter = ''; -- unset for now; will be reset later from |map= if present
end
local Periodical = A['Periodical'];
local Periodical_origin = A:ORIGIN('Periodical');
local ScriptPeriodical = A['ScriptPeriodical'];
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical');
local TransPeriodical = A['TransPeriodical'];
local TransPeriodical_origin = A:ORIGIN ('TransPeriodical');
if (utilities.in_array (config.CitationClass, {'book', 'encyclopaedia'}) and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical))) then
local param;
if utilities.is_set (Periodical) then -- get a parameter name from one of these periodical related meta-parameters
Periodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = Periodical_origin -- get parameter name for error messaging
elseif utilities.is_set (TransPeriodical) then
TransPeriodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = TransPeriodical_origin; -- get parameter name for error messaging
elseif utilities.is_set (ScriptPeriodical) then
ScriptPeriodical = ''; -- unset because not valid {{cite book}} or {{cite encyclopedia}} parameters
param = ScriptPeriodical_origin; -- get parameter name for error messaging
end
if utilities.is_set (param) then -- if we found one
utilities.set_message ('err_periodical_ignored', {param}); -- emit an error message
end
end
if utilities.is_set (Periodical) then
local i;
Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated
if i then -- non-zero when markup was stripped so emit an error message
utilities.set_message ('err_apostrophe_markup', {Periodical_origin});
end
end
if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}}
if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'mailinglist')});
end
Periodical = A ['MailingList']; -- error or no, set Periodical to |mailinglist= value because this template is {{cite mailing list}}
Periodical_origin = A:ORIGIN('MailingList');
end
-- web and news not tested for now because of
-- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors?
if not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter
-- local p = {['journal'] = 'journal', ['magazine'] = 'magazine', ['news'] = 'newspaper', ['web'] = 'website'}; -- for error message
local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message
if p[config.CitationClass] then
utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]});
end
end
local Volume;
if 'citation' == config.CitationClass then
if utilities.is_set (Periodical) then
if not utilities.in_array (Periodical_origin, cfg.citation_no_volume_t) then -- {{citation}} does not render |volume= when these parameters are used
Volume = A['Volume']; -- but does for all other 'periodicals'
end
elseif utilities.is_set (ScriptPeriodical) then
if 'script-website' ~= ScriptPeriodical_origin then -- {{citation}} does not render volume for |script-website=
Volume = A['Volume']; -- but does for all other 'periodicals'
end
else
Volume = A['Volume']; -- and does for non-'periodical' cites
end
elseif utilities.in_array (config.CitationClass, cfg.templates_using_volume) then -- render |volume= for cs1 according to the configuration settings
Volume = A['Volume'];
end
extra_text_in_vol_iss_check (Volume, A:ORIGIN ('Volume'), 'v');
local Issue;
if 'citation' == config.CitationClass then
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, cfg.citation_issue_t) then -- {{citation}} may render |issue= when these parameters are used
Issue = A['Issue'];
end
elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table
if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then
Issue = A['Issue'];
end
end
local ArticleNumber;
if utilities.in_array (config.CitationClass, {'journal', 'conference'}) or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then
ArticleNumber = A['ArticleNumber'];
end
extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i');
Issue = utilities.hyphen_to_dash (Issue);
local Page;
local Pages;
local At;
local QuotePage;
local QuotePages;
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then -- TODO: rewrite to emit ignored parameter error message?
Page = A['Page'];
Pages = utilities.hyphen_to_dash (A['Pages']);
At = A['At'];
QuotePage = A['QuotePage'];
QuotePages = utilities.hyphen_to_dash (A['QuotePages']);
end
local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil);
local Mode = mode_set (A['Mode'], A:ORIGIN('Mode'));
-- separator character and postscript
local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass);
local Quote;
Quote, QuotePage, QuotePages, PostScript = quote_make (A['Quote'], A['TransQuote'], A['ScriptQuote'], QuotePage, QuotePages, NoPP, sepc, PostScript);
local Edition = A['Edition'];
local PublicationPlace = place_check (A['PublicationPlace'], A:ORIGIN('PublicationPlace'));
local Place = place_check (A['Place'], A:ORIGIN('Place'));
local PublisherName = A['PublisherName'];
local PublisherName_origin = A:ORIGIN('PublisherName');
if utilities.is_set (PublisherName) and (cfg.keywords_xlate['none'] ~= PublisherName) then
local i;
PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized
if i and (0 < i) then -- non-zero when markup was stripped so emit an error message
utilities.set_message ('err_apostrophe_markup', {PublisherName_origin});
end
end
if ('document' == config.CitationClass) and not utilities.is_set (PublisherName) then
utilities.set_message ('err_missing_publisher', {config.CitationClass, 'publisher'});
end
local Newsgroup = A['Newsgroup']; -- TODO: strip apostrophe markup?
local Newsgroup_origin = A:ORIGIN('Newsgroup');
if 'newsgroup' == config.CitationClass then
if utilities.is_set (PublisherName) and (cfg.keywords_xlate['none'] ~= PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup
utilities.set_message ('err_parameter_ignored', {PublisherName_origin});
end
PublisherName = nil; -- ensure that this parameter is unset for the time being; will be used again after COinS
end
if 'book' == config.CitationClass or 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and not utilities.is_set (Periodical)) then
local accept;
PublisherName, accept = utilities.has_accept_as_written (PublisherName); -- check for and remove accept-as-written markup from |publisher= wrapped
if not accept then -- when no accept-as-written markup
check_publisher_name (PublisherName); -- emit maint message when |publisher= might be prefixed with publisher's location
end
end
local URL = A['URL']; -- TODO: better way to do this for URL, ChapterURL, and MapURL?
local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then
UrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', 'url');
end
local ChapterURL = A['ChapterURL'];
local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then
ChapterUrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')});
end
local MapUrlAccess = is_valid_parameter_value (A['MapUrlAccess'], A:ORIGIN('MapUrlAccess'), cfg.keywords_lists['url-access'], nil);
if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then
MapUrlAccess = nil;
utilities.set_message ('err_param_access_requires_param', {'map-url'});
end
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language
local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil);
-- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories
if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page
if cfg.uncategorized_namespaces[this_page.namespace] then -- is this page's namespace id one of the uncategorized namespace ids?
no_tracking_cats = "true"; -- set no_tracking_cats
end
for _, v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns
if this_page.text:match (v) then -- test page name against each pattern
no_tracking_cats = "true"; -- set no_tracking_cats
break; -- bail out if one is found
end
end
end
-- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it)
utilities.select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'err_redundant_parameters'); -- this is a dummy call simply to get the error message and category
local coins_pages;
Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN('Page'), Pages, A:ORIGIN('Pages'), At);
if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different
utilities.add_prop_cat ('location-test'); -- add property cat to evaluate how often PublicationPlace and Place are used together
if PublicationPlace == Place then
Place = ''; -- unset; don't need both if they are the same
end
elseif not utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- when only |place= (|location=) is set ...
PublicationPlace = Place; -- promote |place= (|location=) to |publication-place
end
if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same
local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL
local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL
-- local ScriptChapter = A['ScriptChapter'];
-- local ScriptChapter_origin = A:ORIGIN ('ScriptChapter');
local Format = A['Format'];
local ChapterFormat = A['ChapterFormat'];
local TransChapter = A['TransChapter'];
local TransChapter_origin = A:ORIGIN ('TransChapter');
local TransTitle = A['TransTitle'];
local ScriptTitle = A['ScriptTitle'];
--[[
Parameter remapping for cite encyclopedia:
When the citation has these parameters:
|encyclopedia= and |title= then map |title= to |article= and |encyclopedia= to |title= for rendering
|encyclopedia= and |article= then map |encyclopedia= to |title= for rendering
|trans-title= maps to |trans-chapter= when |title= is re-mapped
|url= maps to |chapter-url= when |title= is remapped
All other combinations of |encyclopedia=, |title=, and |article= are not modified
]]
local Encyclopedia = A['Encyclopedia']; -- used as a flag by this module and by ~/COinS
local ScriptEncyclopedia = A['ScriptEncyclopedia'];
local TransEncyclopedia = A['TransEncyclopedia'];
if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}}
if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then
if utilities.is_set (Encyclopedia) then
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')});
else
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('ScriptEncyclopedia')});
end
Encyclopedia = nil; -- unset these because not supported by this template
ScriptEncyclopedia = nil;
TransEncyclopedia = nil;
end
elseif utilities.is_set (TransEncyclopedia) then
utilities.set_message ('err_trans_missing_title', {'encyclopedia'});
end
if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then
if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both parameters set emit an error message; {{citation}} only; Periodical not allowed in {{cite encyclopedia}}
utilities.set_message ('err_periodical_ignored', {Periodical_origin});
end
if utilities.is_set (Encyclopedia) or utilities.is_set (ScriptEncyclopedia) then
Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia for rendering; {{citation}} could (not legitimately) have both; use Encyclopedia
Periodical_origin = A:ORIGIN ('Encyclopedia');
ScriptPeriodical = ScriptEncyclopedia;
ScriptPeriodical_origin = A:ORIGIN ('ScriptEncyclopedia');
if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then
if not utilities.is_set (Chapter) then
Chapter = Title; -- |encyclopedia= and |title= are set so map |title= params to |article= params for rendering
ScriptChapter = ScriptTitle;
ScriptChapter_origin = A:ORIGIN('ScriptTitle')
TransChapter = TransTitle;
ChapterURL = URL;
ChapterURL_origin = URL_origin;
ChapterUrlAccess = UrlAccess;
ChapterFormat = Format;
if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then
Chapter = utilities.make_wikilink (TitleLink, Chapter);
end
Title = Periodical; -- now map |encyclopedia= params to |title= params for rendering
ScriptTitle = ScriptPeriodical or '';
TransTitle = TransEncyclopedia or '';
Periodical = ''; -- redundant so unset
ScriptPeriodical = '';
URL = '';
Format = '';
TitleLink = '';
end
elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set
Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= for rendering
ScriptTitle = ScriptPeriodical or '';
TransTitle = TransEncyclopedia or '';
Periodical = ''; -- redundant so unset
ScriptPeriodical = '';
end
end
end
-- special case for cite techreport.
local ID = A['ID'];
if (config.CitationClass == "techreport") then -- special case for cite techreport
if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue'
if not utilities.is_set (ID) then -- can we use ID for the "number"?
ID = A['Number']; -- yes, use it
else -- ID has a value so emit error message
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'number')});
end
end
end
-- Account for the oddity that is {{cite conference}}, before generation of COinS data.
local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode
local Conference = A['Conference'];
local BookTitle = A['BookTitle'];
local TransTitle_origin = A:ORIGIN ('TransTitle');
if 'conference' == config.CitationClass then
if utilities.is_set (BookTitle) then
Chapter = Title;
Chapter_origin = 'title';
-- ChapterLink = TitleLink; -- |chapter-link= is deprecated
ChapterURL = URL;
ChapterUrlAccess = UrlAccess;
ChapterURL_origin = URL_origin;
URL_origin = '';
ChapterFormat = Format;
TransChapter = TransTitle;
TransChapter_origin = TransTitle_origin;
Title = BookTitle;
Format = '';
-- TitleLink = '';
TransTitle = '';
URL = '';
end
elseif 'speech' ~= config.CitationClass then
Conference = ''; -- not cite conference or cite speech so make sure this is empty string
end
local cs2_lower = function (text) -- if mode is cs2, use lower case
if (sepc ~= '.') then
return text:lower();
end
return text;
end
local use_lowercase = ( sepc == ',' ); -- controls capitalization of certain static text
-- cite map oddities
local Cartography = "";
local Scale = "";
local Sheet = A['Sheet'] or '';
local Sheets = A['Sheets'] or '';
if config.CitationClass == "map" then
if utilities.is_set (Chapter) then --TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message
end
Chapter = A['Map'];
Chapter_origin = A:ORIGIN('Map'); -- for now, ignore linter warning
ChapterURL = A['MapURL'];
ChapterURL_origin = A:ORIGIN('MapURL');
TransChapter = A['TransMap'];
ScriptChapter = A['ScriptMap']
ScriptChapter_origin = A:ORIGIN('ScriptMap')
ChapterUrlAccess = MapUrlAccess;
ChapterFormat = A['MapFormat'];
Cartography = A['Cartography'];
if utilities.is_set ( Cartography ) then
Cartography = sepc .. " " .. wrap_msg ('cartography', Cartography, use_lowercase);
end
Scale = A['Scale'];
if utilities.is_set ( Scale ) then
Scale = sepc .. " " .. Scale;
end
end
-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.
local Series = A['Series'];
if 'episode' == config.CitationClass or 'serial' == config.CitationClass then
local SeriesLink = A['SeriesLink'];
SeriesLink = link_title_ok (SeriesLink, A:ORIGIN ('SeriesLink'), Series, 'series'); -- check for wiki-markup in |series-link= or wiki-markup in |series= when |series-link= is set
local Network = A['Network'];
local Station = A['Station'];
local s, n = {}, {};
-- do common parameters first
if utilities.is_set (Network) then table.insert(n, Network); end
if utilities.is_set (Station) then table.insert(n, Station); end
ID = table.concat(n, sepc .. ' ');
if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}}
local Season = A['Season'];
local SeriesNumber = A['SeriesNumber'];
if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message
SeriesNumber = ''; -- unset; prefer |season= over |seriesno=
end
-- assemble a table of parts concatenated later into Series
if utilities.is_set (Season) then table.insert(s, wrap_msg ('season', Season, use_lowercase)); end
if utilities.is_set (SeriesNumber) then table.insert(s, wrap_msg ('seriesnum', SeriesNumber, use_lowercase)); end
if utilities.is_set (Issue) then table.insert(s, wrap_msg ('episode', Issue, use_lowercase)); end
Issue = ''; -- unset because this is not a unique parameter
Chapter = Title; -- promote title parameters to chapter
ScriptChapter = ScriptTitle;
ScriptChapter_origin = A:ORIGIN('ScriptTitle');
ChapterLink = TitleLink; -- alias |episode-link=
TransChapter = TransTitle;
ChapterURL = URL;
ChapterUrlAccess = UrlAccess;
ChapterURL_origin = URL_origin;
ChapterFormat = Format;
Title = Series; -- promote series to title
TitleLink = SeriesLink;
Series = table.concat(s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number
if utilities.is_set (ChapterLink) and not utilities.is_set (ChapterURL) then -- link but not URL
Chapter = utilities.make_wikilink (ChapterLink, Chapter);
elseif utilities.is_set (ChapterLink) and utilities.is_set (ChapterURL) then -- if both are set, URL links episode;
Series = utilities.make_wikilink (ChapterLink, Series);
end
URL = ''; -- unset
TransTitle = '';
ScriptTitle = '';
Format = '';
else -- now oddities that are cite serial
Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
if utilities.is_set (Series) and utilities.is_set (SeriesLink) then
Series = utilities.make_wikilink (SeriesLink, Series);
end
Series = utilities.wrap_style ('italic-title', Series); -- series is italicized
end
end
-- end of {{cite episode}} stuff
-- handle type parameter for those CS1 citations that have default values
local TitleType = A['TitleType'];
local Degree = A['Degree'];
if utilities.in_array (config.CitationClass, {'AV-media-notes', 'document', 'interview', 'mailinglist', 'map', 'podcast', 'pressrelease', 'report', 'speech', 'techreport', 'thesis'}) then
TitleType = set_titletype (config.CitationClass, TitleType);
if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis
TitleType = Degree .. ' ' .. cfg.title_types ['thesis']:lower();
end
end
if utilities.is_set (TitleType) then -- if type parameter is specified
TitleType = utilities.substitute ( cfg.messages['type'], TitleType); -- display it in parentheses
-- TODO: Hack on TitleType to fix bunched parentheses problem
end
-- legacy: promote PublicationDate to Date if neither Date nor Year are set.
local Date = A['Date'];
local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging
local PublicationDate = A['PublicationDate'];
local Year = A['Year'];
if utilities.is_set (Year) then
validation.year_check (Year); -- returns nothing; emits maint message when |year= doesn't hold a 'year' value
end
if not utilities.is_set (Date) then
Date = Year; -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
if not utilities.is_set (Date) and utilities.is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate; -- promote PublicationDate to Date
PublicationDate = ''; -- unset, no longer needed
Date_origin = A:ORIGIN('PublicationDate'); -- save the name of the promoted parameter
else
Date_origin = A:ORIGIN('Year'); -- save the name of the promoted parameter
end
else
Date_origin = A:ORIGIN('Date'); -- not a promotion; name required for error messaging
end
if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation
--[[
Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where
we get the date used in the metadata.
Date validation supporting code is in Module:Citation/CS1/Date_validation
]]
local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], '');
if not utilities.is_set (DF) then
DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template
end
local ArchiveURL;
local ArchiveDate;
local ArchiveFormat = A['ArchiveFormat'];
local archive_url_timestamp; -- timestamp from wayback machine url
ArchiveURL, ArchiveDate, archive_url_timestamp = archive_url_check (A['ArchiveURL'], A['ArchiveDate'])
ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url');
ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN('ArchiveURL'), ArchiveDate); -- add error message when URL or ChapterURL == ArchiveURL
local AccessDate = A['AccessDate'];
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification
local DoiBroken = A['DoiBroken'];
local Embargo = A['Embargo'];
local anchor_year; -- used in the CITEREF identifier
do -- create defined block to contain local variables date_parameters_list, mismatch
local date_parameters_list = { -- AirDate has been promoted to Date so not necessary to check it
['access-date'] = {val = AccessDate, name = A:ORIGIN ('AccessDate')},
['archive-date'] = {val = ArchiveDate, name = A:ORIGIN ('ArchiveDate')},
['date'] = {val = Date, name = Date_origin},
['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')},
['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')},
['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')},
['year'] = {val = Year, name = A:ORIGIN ('Year')},
};
local error_list = {};
anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list);
if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed;
validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list);
end
if 0 == #error_list then -- error free dates only; 0 when error_list is empty
local modified = false; -- flag
if utilities.is_set (DF) then -- if we need to reformat dates
modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate
end
if true == validation.date_hyphen_to_dash (date_parameters_list) then -- convert hyphens to dashes where appropriate
modified = true;
utilities.set_message ('maint_date_format'); -- hyphens were converted so add maint category
end
-- for those wikis that can and want to have English date names translated to the local language; not supported at en.wiki
if cfg.date_name_auto_xlate_enable and validation.date_name_xlate (date_parameters_list, cfg.date_digit_auto_xlate_enable ) then
utilities.set_message ('maint_date_auto_xlated'); -- add maint cat
modified = true;
end
if modified then -- if the date_parameters_list values were modified
AccessDate = date_parameters_list['access-date'].val; -- overwrite date holding parameters with modified values
ArchiveDate = date_parameters_list['archive-date'].val;
Date = date_parameters_list['date'].val;
DoiBroken = date_parameters_list['doi-broken-date'].val;
PublicationDate = date_parameters_list['publication-date'].val;
end
if archive_url_timestamp and utilities.is_set (ArchiveDate) then
validation.archive_date_check (ArchiveDate, archive_url_timestamp, DF); -- does YYYYMMDD in archive_url_timestamp match date in ArchiveDate
end
else
utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}); -- add this error message
end
end -- end of do
if utilities.in_array (config.CitationClass, {'book', 'encyclopaedia'}) or -- {{cite book}}, {{cite encyclopedia}}; TODO: {{cite conference}} and others?
('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) or -- {{citation}} as an encylopedia citation
('citation' == config.CitationClass and not utilities.is_set (Periodical)) then -- {{citation}} as a book citation
if utilities.is_set (PublicationPlace) then
if not utilities.is_set (PublisherName) then
local date = COinS_date.rftdate and tonumber (COinS_date.rftdate:match ('%d%d%d%d')); -- get year portion of COinS date (because in Arabic numerals); convert string to number
if date and (1850 <= date) then -- location has no publisher; if date is 1850 or later
utilities.set_message ('maint_location_no_publisher'); -- add maint cat
end
else -- PublisherName has a value
if cfg.keywords_xlate['none'] == PublisherName then -- if that value is 'none' (only for book and encyclopedia citations)
PublisherName = ''; -- unset
end
end
end
end
local ID_list_t; -- sequence table of rendered identifiers
local ID_list_coins_t; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key
local Class = A['Class']; -- arxiv class identifier
local ID_support = {
{A['ASINTLD'], 'ASIN', 'err_asintld_missing_asin', A:ORIGIN ('ASINTLD')},
{DoiBroken, 'DOI', 'err_doibroken_missing_doi', A:ORIGIN ('DoiBroken')},
{Embargo, 'PMC', 'err_embargo_missing_pmc', A:ORIGIN ('Embargo')},
}
ID_list_t, ID_list_coins_t = identifiers.identifier_lists_get (args, {
DoiBroken = DoiBroken, -- for |doi=
ASINTLD = A['ASINTLD'], -- for |asin=
Embargo = Embargo, -- for |pmc=
Class = Class, -- for |arxiv=
CitationClass = config.CitationClass, -- for |arxiv=
Year=anchor_year, -- for |isbn=
}, ID_support);
for _, id in ipairs (ID_list_t) do -- search through the ID_list_t sequence looking for an ISBN identifier string
if id:find ('ISBN', 3, true) then -- plain find, start at index 3 ([[ISBN)
if 'citation' == config.CitationClass then -- catch ve/citoid malformed book cites in {{citation}} templates
if utilities.is_set (Periodical) then -- when a |work= alias is set
utilities.set_message ('maint_work_isbn'); -- add maint cat
break; -- and abandon
end
elseif ({['journal'] = true, ['magazine'] = true, ['news'] = true, ['web'] = true})[config.CitationClass] then
utilities.set_message ('maint_periodical_has_isbn'); -- add maint cat
break; -- and abandon
end
end
end
-- if 'citation' == config.CitationClass then -- catch ve/citoid malformed book cites in {{citation}} templates
-- for _, id in ipairs (ID_list_t) do -- search through the ID_list_t sequence looking for an ISBN identifier string
-- if id:find ('ISBN', 3, true) then -- plain find, start at index 3 ([[ISBN)
-- if utilities.is_set (Periodical) then -- when a |work= alias is set
-- utilities.set_message ('maint_work_isbn'); -- add maint cat
-- end
-- end
-- end
-- end
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite medrxiv}}, {{cite ssrn}}, before generation of COinS data.
if utilities.in_array (config.CitationClass, whitelist.preprint_template_list_t) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv=, |citeseerx=, |medrxiv=, |ssrn= required for their templates
if not (args[cfg.id_handlers[config.CitationClass:upper()].parameters[1]] or -- can't use ID_list_coins_t k/v table here because invalid parameters omitted
args[cfg.id_handlers[config.CitationClass:upper()].parameters[2]]) then -- which causes unexpected parameter missing error message
utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message
end
Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX', ['medrxiv'] = 'medRxiv', ['ssrn'] = 'Social Science Research Network'})[config.CitationClass];
end
-- Link the title of the work if no |url= was provided, but we have a |pmc= or a |doi= with |doi-access=free
if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead
if 'none' ~= cfg.keywords_xlate[auto_select] then -- if auto-linking not disabled
if identifiers.auto_link_urls[auto_select] then -- manual selection
URL = identifiers.auto_link_urls[auto_select]; -- set URL to be the same as identifier's external link
URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title=
elseif identifiers.auto_link_urls['pmc'] then -- auto-select PMC
URL = identifiers.auto_link_urls['pmc']; -- set URL to be the same as the PMC external link if not embargoed
URL_origin = cfg.id_handlers['PMC'].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title=
elseif identifiers.auto_link_urls['doi'] then -- auto-select DOI
URL = identifiers.auto_link_urls['doi'];
URL_origin = cfg.id_handlers['DOI'].parameters[1];
end
end
if utilities.is_set (URL) then -- set when using an identifier-created URL
if utilities.is_set (AccessDate) then -- |access-date= requires |url=; identifier-created URL is not |url=
utilities.set_message ('err_accessdate_missing_url'); -- add an error message
AccessDate = ''; -- unset
end
if utilities.is_set (ArchiveURL) then -- |archive-url= requires |url=; identifier-created URL is not |url=
utilities.set_message ('err_archive_missing_url'); -- add an error message
ArchiveURL = ''; -- unset
end
end
end
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
-- Test if citation has no title
if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode
utilities.set_message ('err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'});
end
if utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) and
utilities.in_array (config.CitationClass, {'journal', 'citation'}) and
(utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and
('journal' == Periodical_origin or 'script-journal' == ScriptPeriodical_origin) then -- special case for journal cites
Title = ''; -- set title to empty string
utilities.set_message ('maint_untitled'); -- add maint cat
end
if 'journal' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then
if is_page_art_num (((utilities.is_set (Page) and Page) or (utilities.is_set (Pages) and Pages)) or nil, ID_list_coins_t['DOI']) then -- does |page(s)= look like it holds an article number
utilities.set_message ('maint_page_art_num'); -- add maint cat
end
end
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
-- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that
-- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title
-- is the article title, and Chapter is a section within the article. So, we remap
local coins_chapter = Chapter; -- default assuming that remapping not required
local coins_title = Title; -- et tu
if 'encyclopaedia' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then
if utilities.is_set (Chapter) and utilities.is_set (Title) and utilities.is_set (Periodical) then -- if all are used then
coins_chapter = Title; -- remap
coins_title = Periodical;
end
end
local coins_author = a; -- default for coins rft.au
if 0 < #c then -- but if contributor list
coins_author = c; -- use that instead
end
-- this is the function call to COinS()
local OCinSoutput = metadata.COinS({
['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata
['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS
['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic / accept-as-written markup
['Degree'] = Degree; -- cite thesis only
['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup
['PublicationPlace'] = PublicationPlace,
['Date'] = COinS_date.rftdate, -- COinS_date.* has correctly formatted date values if Date is valid;
['Season'] = COinS_date.rftssn,
['Quarter'] = COinS_date.rftquarter,
['Chron'] = COinS_date.rftchron,
['Series'] = Series,
['Volume'] = Volume,
['Issue'] = Issue,
['ArticleNumber'] = ArticleNumber,
['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links
['Edition'] = Edition,
['PublisherName'] = PublisherName or Newsgroup, -- any apostrophe markup already removed from PublisherName
['URL'] = first_set ({ChapterURL, URL}, 2),
['Authors'] = coins_author,
['ID_list'] = ID_list_coins_t,
['RawPage'] = this_page.prefixedText,
}, config.CitationClass);
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite medrxiv}}, and {{cite ssrn}} AFTER generation of COinS data.
if utilities.in_array (config.CitationClass, whitelist.preprint_template_list_t) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, medRxiv, or ssrn now unset so it isn't displayed
Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal
end
-- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text
if 'newsgroup' == config.CitationClass and utilities.is_set (Newsgroup) then
PublisherName = utilities.substitute (cfg.messages['newsgroup'], external_link( 'news:' .. Newsgroup, Newsgroup, Newsgroup_origin, nil ));
end
local Editors;
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list
local Contributors; -- assembled contributors name list
local contributor_etal = nil; -- must be intentionally initialized
local Translators; -- assembled translators name list
local translator_etal = nil; -- must be intentionally initialized
local t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
local Interviewers;
local interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters
local interviewer_etal = nil; -- must be intentionally initialized
-- Now perform various field substitutions.
-- We also add leading spaces and surrounding markup and punctuation to the
-- various parts of the citation, but only when they are non-nil.
do
local last_first_list;
local control = {
format = NameListStyle, -- empty string, '&', 'amp', 'and', or 'vanc'
maximum = nil, -- as if display-authors or display-editors not set
mode = Mode
};
do -- do editor name list first because the now unsupported coauthors used to modify control table
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayEditors'], A['DisplayEditors'], A:ORIGIN ('DisplayEditors'), #e);
control.maximum, editor_etal = get_display_names (display_names, #e, editor_etal, param);
Editors, EditorCount = list_people (control, e, editor_etal);
if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then
EditorCount = 2; -- spoof to display (eds.) annotation
end
end
do -- now do interviewers
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayInterviewers'], A['DisplayInterviewers'], A:ORIGIN ('DisplayInterviewers'), #interviewers_list);
control.maximum, interviewer_etal = get_display_names (display_names, #interviewers_list, interviewer_etal, param);
Interviewers = list_people (control, interviewers_list, interviewer_etal);
end
do -- now do translators
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayTranslators'], A['DisplayTranslators'], A:ORIGIN ('DisplayTranslators'), #t);
control.maximum, translator_etal = get_display_names (display_names, #t, translator_etal, param);
Translators = list_people (control, t, translator_etal);
end
do -- now do contributors
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayContributors'], A['DisplayContributors'], A:ORIGIN ('DisplayContributors'), #c);
control.maximum, contributor_etal = get_display_names (display_names, #c, contributor_etal, param);
Contributors = list_people (control, c, contributor_etal);
end
do -- now do authors
local display_names, param = display_names_select (cfg.global_cs1_config_t['DisplayAuthors'], A['DisplayAuthors'], A:ORIGIN ('DisplayAuthors'), #a, author_etal);
control.maximum, author_etal = get_display_names (display_names, #a, author_etal, param);
last_first_list = list_people (control, a, author_etal);
if utilities.is_set (Authors) then
Authors, author_etal = name_has_etal (Authors, author_etal, false, 'authors'); -- find and remove variations on et al.
if author_etal then
Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter
end
else
Authors = last_first_list; -- either an author name list or an empty string
end
end -- end of do
if utilities.is_set (Authors) and utilities.is_set (Collaboration) then
Authors = utilities.substitute (cfg.messages['collaboration'], {Authors, Collaboration}); -- add collaboration after et al.
end
end
local ConferenceFormat = A['ConferenceFormat'];
local ConferenceURL = A['ConferenceURL'];
ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url');
Format = style_format (Format, URL, 'format', 'url');
-- special case for chapter format so no error message or cat when chapter not supported
if not (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then
ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url');
end
if not utilities.is_set (URL) then
if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for {{cite web}}, {{cite podcast}}, and {{cite mailing list}}
('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website=
if not url_was_archive_today then -- is <URL> empty/missing because it was a deprecated archive.today url
utilities.set_message ('err_cite_web_url'); -- no; emit an error message for an empty/ missing |url=
end
end
-- do we have |accessdate= without either |url= or |chapter-url=?
if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set;
utilities.set_message ('err_accessdate_missing_url');
AccessDate = '';
end
end
local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], '');
local OriginalURL
local OriginalURL_origin
local OriginalFormat
local OriginalAccess;
UrlStatus = UrlStatus:lower(); -- used later when assembling archived text
if utilities.is_set ( ArchiveURL ) then
if utilities.is_set (ChapterURL) then -- if chapter-url= is set apply archive url to it
OriginalURL = ChapterURL; -- save copy of source chapter's url for archive text
OriginalURL_origin = ChapterURL_origin; -- name of |chapter-url= parameter for error messages
OriginalFormat = ChapterFormat; -- and original |chapter-format=
if 'live' ~= UrlStatus then
ChapterURL = ArchiveURL -- swap-in the archive's URL
ChapterURL_origin = A:ORIGIN('ArchiveURL') -- name of |archive-url= parameter for error messages
ChapterFormat = ArchiveFormat or ''; -- swap in archive's format
ChapterUrlAccess = nil; -- restricted access levels do not make sense for archived URLs
end
elseif utilities.is_set (URL) then
OriginalURL = URL; -- save copy of original source URL
OriginalURL_origin = URL_origin; -- name of URL parameter for error messages
OriginalFormat = Format; -- and original |format=
OriginalAccess = UrlAccess;
if 'live' ~= UrlStatus then -- if URL set then |archive-url= applies to it
URL = ArchiveURL -- swap-in the archive's URL
URL_origin = A:ORIGIN('ArchiveURL') -- name of archive URL parameter for error messages
Format = ArchiveFormat or ''; -- swap in archive's format
UrlAccess = nil; -- restricted access levels do not make sense for archived URLs
end
end
elseif utilities.is_set (UrlStatus) then -- if |url-status= is set when |archive-url= is not set
utilities.set_message ('maint_url_status'); -- add maint cat
end
if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or -- if any of the 'periodical' cites except encyclopedia
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then
local chap_param;
if utilities.is_set (Chapter) then -- get a parameter name from one of these chapter related meta-parameters
chap_param = A:ORIGIN ('Chapter')
elseif utilities.is_set (TransChapter) then
chap_param = A:ORIGIN ('TransChapter')
elseif utilities.is_set (ChapterURL) then
chap_param = A:ORIGIN ('ChapterURL')
elseif utilities.is_set (ScriptChapter) then
chap_param = ScriptChapter_origin;
else utilities.is_set (ChapterFormat)
chap_param = A:ORIGIN ('ChapterFormat')
end
if utilities.is_set (chap_param) then -- if we found one
utilities.set_message ('err_chapter_ignored', {chap_param}); -- add error message
Chapter = ''; -- and set them to empty string to be safe with concatenation
TransChapter = ''; -- for now, ignore linter warnings
ChapterURL = '';
ScriptChapter = '';
ChapterFormat = '';
end
else -- otherwise, format chapter / article title
local no_quotes = false; -- default assume that we will be quoting the chapter parameter value
if utilities.is_set (Contribution) and 0 < #c then -- if this is a contribution with contributor(s)
if utilities.in_array (Contribution:lower(), cfg.keywords_lists.contribution) then -- and a generic contribution title
no_quotes = true; -- then render it unquoted
end
end
Chapter = format_chapter_title (ScriptChapter, ScriptChapter_origin, Chapter, TransChapter, TransChapter_origin, ChapterURL, ChapterURL_origin, no_quotes, ChapterUrlAccess); -- Contribution is also in Chapter
if utilities.is_set (Chapter) then
Chapter = Chapter .. ChapterFormat ;
if 'map' == config.CitationClass and utilities.is_set (TitleType) then
Chapter = Chapter .. ' ' .. TitleType; -- map annotation here; not after title
end
Chapter = Chapter .. sepc .. ' ';
elseif utilities.is_set (ChapterFormat) then -- |chapter= not set but |chapter-format= is so ...
Chapter = ChapterFormat .. sepc .. ' '; -- ... ChapterFormat has error message, we want to see it
end
end
-- Format main title
local plain_title = false;
local accept_title;
Title, accept_title = utilities.has_accept_as_written (Title, true); -- remove accept-this-as-written markup when it wraps all of <Title>
if accept_title and ('' == Title) then -- only support forced empty for now "(())"
Title = cfg.messages['notitle']; -- replace by predefined "No title" message
-- TODO: utilities.set_message ( 'err_redundant_parameters', ...); -- issue proper error message instead of muting
ScriptTitle = ''; -- just mute for now
TransTitle = ''; -- just mute for now
plain_title = true; -- suppress text decoration for descriptive title
utilities.set_message ('maint_untitled'); -- add maint cat
end
if not accept_title then -- <Title> not wrapped in accept-as-written markup
if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title=
Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three
elseif not mw.ustring.find (Title, '%.%s*%a%.$') and -- end of title is not a 'dot-(optional space-)letter-dot' initialism ...
not mw.ustring.find (Title, '%s+%a%.$') then -- ...and not a 'space-letter-dot' initial (''Allium canadense'' L.)
Title = mw.ustring.gsub(Title, '%' .. sepc .. '$', ''); -- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters
end
if utilities.is_set (ArchiveURL) and is_archived_copy (Title) then
utilities.set_message ('maint_archived_copy'); -- add maintenance category before we modify the content of Title
end
if is_generic ('generic_titles', Title) then
utilities.set_message ('err_generic_title'); -- set an error message
end
end
if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'document', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) or
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or
('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article
Title = kern_quotes (Title); -- if necessary, separate title's leading and trailing quote marks from module provided quote marks
Title = utilities.wrap_style ('quoted-title', Title);
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle );
elseif plain_title or ('report' == config.CitationClass) then -- no styling for cite report and descriptive titles (otherwise same as above)
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title
else
Title = utilities.wrap_style ('italic-title', Title);
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped
TransTitle = utilities.wrap_style ('trans-italic-title', TransTitle);
end
if utilities.is_set (TransTitle) then
if utilities.is_set (Title) then
TransTitle = " " .. TransTitle;
else
utilities.set_message ('err_trans_missing_title', {'title'});
end
end
if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs?
if utilities.is_set (TitleLink) and utilities.is_set (URL) then
utilities.set_message ('err_wikilink_in_url'); -- set an error message because we can't have both
TitleLink = ''; -- unset
end
if not utilities.is_set (TitleLink) and utilities.is_set (URL) then
Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format;
URL = ''; -- unset these because no longer needed
Format = ''; -- for now, ignore linter warning
elseif utilities.is_set (TitleLink) and not utilities.is_set (URL) then
local ws_url;
ws_url = wikisource_url_make (TitleLink); -- ignore ws_label return; not used here
if ws_url then
Title = external_link (ws_url, Title .. ' ', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title});
Title = Title .. TransTitle;
else
Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle;
end
else
local ws_url, ws_label, L; -- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink)
ws_url, ws_label, L = wikisource_url_make (Title:gsub('^[\'"]*(.-)[\'"]*$', '%1')); -- make ws URL from |title= interwiki link (strip italic or quote markup); link portion L becomes tooltip label
if ws_url then
Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup
Title = external_link (ws_url, Title .. ' ', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this?
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title});
Title = Title .. TransTitle;
else
Title = Title .. TransTitle;
end
end
else
Title = TransTitle;
end
if utilities.is_set (Place) then
Place = " " .. wrap_msg ('written', Place, use_lowercase) .. sepc .. " ";
end
local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL
if utilities.is_set (Conference) then
if utilities.is_set (ConferenceURL) then
Conference = external_link( ConferenceURL, Conference, ConferenceURL_origin, nil );
end
Conference = sepc .. " " .. Conference .. ConferenceFormat;
elseif utilities.is_set (ConferenceURL) then
Conference = sepc .. " " .. external_link( ConferenceURL, nil, ConferenceURL_origin, nil );
end
local Position = '';
if not utilities.is_set (Position) then
local Minutes = A['Minutes'];
local Time = A['Time'];
if utilities.is_set (Minutes) then
if utilities.is_set (Time) then --TODO: make a function for this and similar?
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'time')});
end
Position = utilities.substitute (cfg.messages.minutes, Minutes);
else
if utilities.is_set (Time) then
local TimeCaption = A['TimeCaption']
if not utilities.is_set (TimeCaption) then
TimeCaption = cs2_lower(cfg.messages['event']);
end
Position = " " .. TimeCaption .. " " .. Time;
end
end
else
Position = " " .. Position;
At = '';
end
Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase);
At = utilities.is_set (At) and (sepc .. " " .. At) or "";
Position = utilities.is_set (Position) and (sepc .. " " .. Position) or "";
if config.CitationClass == 'map' then
local Sections = A['Sections']; -- Section (singular) is an alias of Chapter so set earlier
local Inset = A['Inset'];
if utilities.is_set ( Inset ) then
Inset = sepc .. " " .. wrap_msg ('inset', Inset, use_lowercase);
end
if utilities.is_set ( Sections ) then
Section = sepc .. " " .. wrap_msg ('sections', Sections, use_lowercase);
elseif utilities.is_set ( Section ) then
Section = sepc .. " " .. wrap_msg ('section', Section, use_lowercase);
end
At = At .. Inset .. Section;
end
local Others = A['Others'];
if utilities.is_set (Others) and 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor=
if config.CitationClass == "AV-media-notes"
or config.CitationClass == "audio-visual" then -- special maint for AV/M which has a lot of 'false' positives right now
utilities.set_message ('maint_others_avm')
else
utilities.set_message ('maint_others');
end
end
Others = utilities.is_set (Others) and (sepc .. " " .. Others) or "";
if utilities.is_set (Translators) then
Others = safe_join ({sepc .. ' ', wrap_msg ('translated', Translators, use_lowercase), Others}, sepc);
end
if utilities.is_set (Interviewers) then
Others = safe_join ({sepc .. ' ', wrap_msg ('interview', Interviewers, use_lowercase), Others}, sepc);
end
local TitleNote = A['TitleNote'];
TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or "";
if utilities.is_set (Edition) then
if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn.
utilities.set_message ('err_extra_text_edition'); -- add error message
end
Edition = " " .. wrap_msg ('edition', Edition);
else
Edition = '';
end
Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum
local Agency = A['Agency'] or ''; -- |agency= is supported by {{cite magazine}}, {{cite news}}, {{cite press release}}, {{cite web}}, and certain {{citation}} templates
if utilities.is_set (Agency) then -- this testing done here because {{citation}} supports 'news' citations
if utilities.in_array (config.CitationClass, {'magazine', 'news', 'pressrelease', 'web'}) or ('citation' == config.CitationClass and utilities.in_array (Periodical_origin, {"magazine", "newspaper", "work"})) then
Agency = wrap_msg ('agency', {sepc, Agency}); -- format for rendering
else
Agency = ''; -- unset; not supported
utilities.set_message ('err_parameter_ignored', {'agency'}); -- add error message
end
end
Volume = format_volume_issue (Volume, Issue, ArticleNumber, config.CitationClass, Periodical_origin, sepc, use_lowercase);
if utilities.is_set (AccessDate) then
local retrv_text = " " .. cfg.messages['retrieved'];
AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format
retrv_text = cs2_lower(retrv_text); -- if mode is cs2, lower case
AccessDate = utilities.substitute (retrv_text, AccessDate); -- add retrieved text
AccessDate = utilities.substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates
end
if utilities.is_set (ID) then ID = sepc .. " " .. ID; end
local Docket = A['Docket'];
if "thesis" == config.CitationClass and utilities.is_set (Docket) then
ID = sepc .. " Docket " .. Docket .. ID;
end
if "report" == config.CitationClass and utilities.is_set (Docket) then -- for cite report when |docket= is set
ID = sepc .. ' ' .. Docket; -- overwrite ID even if |id= is set
end
if utilities.is_set (URL) then
URL = " " .. external_link( URL, nil, URL_origin, UrlAccess );
end
-- We check length of PostScript here because it will have been nuked by
-- the quote parameters. We'd otherwise emit a message even if there wasn't
-- a displayed postscript.
-- TODO: Should the max size (1) be configurable?
-- TODO: Should we check a specific pattern?
if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then
utilities.set_message ('maint_postscript')
end
local Archived;
if utilities.is_set (ArchiveURL) then
if not utilities.is_set (ArchiveDate) then -- ArchiveURL set but ArchiveDate not set
utilities.set_message ('err_archive_missing_date'); -- emit an error message
ArchiveURL = ''; -- empty string for concatenation
ArchiveDate = ''; -- empty string for concatenation
end
else
if utilities.is_set (ArchiveDate) then -- ArchiveURL not set but ArchiveDate is set
utilities.set_message ('err_archive_date_missing_url'); -- emit an error message
ArchiveURL = ''; -- empty string for concatenation
ArchiveDate = ''; -- empty string for concatenation
end
end
if utilities.is_set (ArchiveURL) then
if "live" == UrlStatus then
if utilities.is_set (ArchiveDate) then
Archived = sepc .. ' ' .. utilities.substitute ( cfg.messages['archived-live'],
{ external_link( ArchiveURL, cs2_lower(cfg.messages['archived']), A:ORIGIN('ArchiveURL'), nil) .. ArchiveFormat, ArchiveDate } );
else
Archived = '';
end
if not utilities.is_set (OriginalURL) then
utilities.set_message ('err_archive_missing_url');
Archived = ''; -- empty string for concatenation
end
elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown'
if utilities.in_array (UrlStatus, {'unfit', 'usurped', 'bot: unknown'}) then
Archived = sepc .. ' ' .. utilities.substitute ( cs2_lower(cfg.messages['archived-unfit']), ArchiveDate);
if 'bot: unknown' == UrlStatus then
utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added
else
utilities.add_prop_cat ('unfit'); -- and add a category if not already added
end
else -- UrlStatus is empty, 'dead'
if utilities.is_set (ArchiveDate) then
Archived = sepc .. ' ' .. utilities.substitute ( cs2_lower(cfg.messages['archived-dead']),
{ external_link( OriginalURL, cfg.messages['original'], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } );
else
Archived = ''; -- unset for concatenation
end
end
else -- OriginalUrl not set
utilities.set_message ('err_archive_missing_url');
Archived = ''; -- empty string for concatenation
end
elseif utilities.is_set (ArchiveFormat) then
Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message
else
Archived = '';
end
local TranscriptURL = A['TranscriptURL']
local TranscriptFormat = A['TranscriptFormat'];
TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl');
local Transcript = A['Transcript'];
local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL
if utilities.is_set (Transcript) then
if utilities.is_set (TranscriptURL) then
Transcript = external_link( TranscriptURL, Transcript, TranscriptURL_origin, nil );
end
Transcript = sepc .. ' ' .. Transcript .. TranscriptFormat;
elseif utilities.is_set (TranscriptURL) then
Transcript = external_link( TranscriptURL, nil, TranscriptURL_origin, nil );
end
local Publisher;
if utilities.is_set (PublicationDate) then
PublicationDate = wrap_msg ('published', PublicationDate);
end
if utilities.is_set (PublisherName) then
if utilities.is_set (PublicationPlace) then
Publisher = sepc .. " " .. PublicationPlace .. ": " .. PublisherName .. PublicationDate;
else
Publisher = sepc .. " " .. PublisherName .. PublicationDate;
end
elseif utilities.is_set (PublicationPlace) then
Publisher= sepc .. " " .. PublicationPlace .. PublicationDate;
else
Publisher = PublicationDate;
end
-- Several of the above rely upon detecting this as nil, so do it last.
if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then
if utilities.is_set (Title) or utilities.is_set (TitleNote) then
Periodical = sepc .. " " .. format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);
else
Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);
end
end
local Language = A['Language'];
if utilities.is_set (Language) then
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc.
else
Language=''; -- language not specified so make sure this is an empty string;
--[[ TODO: need to extract the wrap_msg from language_parameter
so that we can solve parentheses bunching problem with Format/Language/TitleType
]]
end
--[[
Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that
the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).
]]
if "speech" == config.CitationClass then -- cite speech only
TitleNote = TitleType; -- move TitleType to TitleNote so that it renders ahead of |event=
TitleType = ''; -- and unset
if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter
if utilities.is_set (Conference) then -- and if |event= is set
Conference = Conference .. sepc .. " "; -- then add appropriate punctuation to the end of the Conference variable before rendering
end
end
end
-- Piece all bits together at last. Here, all should be non-nil.
-- We build things this way because it is more efficient in LUA
-- not to keep reassigning to the same string variable over and over.
local tcommon;
local tcommon2; -- used for book cite when |contributor= is set
local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At;
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (Periodical) then -- special cases for book cites
if utilities.is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc.
tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2
tcommon2 = safe_join ({TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc);
else
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Volume, Others, Edition, Publisher}, sepc);
end
elseif 'map' == config.CitationClass then -- special cases for cite map
if utilities.is_set (Chapter) then -- map in a book; TitleType is part of Chapter
tcommon = safe_join ({Title, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc);
elseif utilities.is_set (Periodical) then -- map in a periodical
tcommon = safe_join ({Title, TitleType, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc);
else -- a sheet or stand-alone map
tcommon = safe_join ({Title, TitleType, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc);
end
elseif 'episode' == config.CitationClass then -- special case for cite episode
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc);
else -- all other CS1 templates
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc);
end
if #ID_list_t > 0 then
ID_list_t = safe_join( { sepc .. " ", table.concat( ID_list_t, sepc .. " " ), ID }, sepc );
else
ID_list_t = ID;
end
local Via = A['Via'];
Via = utilities.is_set (Via) and wrap_msg ('via', Via) or '';
local idcommon;
if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript
idcommon = safe_join( { ID_list_t, URL, Archived, Transcript, AccessDate, Via, Quote }, sepc );
else
idcommon = safe_join( { ID_list_t, URL, Archived, AccessDate, Via, Quote }, sepc );
end
local text;
-- local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At;
local OrigDate = A['OrigDate'];
OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or '';
if utilities.is_set (Date) then
if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set
Date = " (" .. Date .. ")" .. OrigDate .. sepc .. " "; -- in parentheses
else -- neither of authors and editors set
if (string.sub(tcommon, -1, -1) == sepc) then -- if the last character of tcommon is sepc
Date = " " .. Date .. OrigDate; -- Date does not begin with sepc
else
Date = sepc .. " " .. Date .. OrigDate; -- Date begins with sepc
end
end
end
if utilities.is_set (Authors) then
if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Authors termination
Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space
end
if utilities.is_set (Editors) then
local in_text = '';
local post_text;
if utilities.is_set (Chapter) and 0 == #c then
in_text = cfg.messages['in'] .. ' ';
in_text = cs2_lower(in_text); -- lowercase for cs2
end
if EditorCount <= 1 then
post_text = ' (' .. cfg.messages['editor'] .. ')'; -- be consistent with no-author, no-date case
else
post_text = ' (' .. cfg.messages['editors'] .. ')';
end
Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space
end
if utilities.is_set (Contributors) then -- book cite and we're citing the intro, preface, etc.
local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' ';
by_text = cs2_lower(by_text); -- lowercase for cs2
Authors = by_text .. Authors; -- author follows title so tweak it here
if utilities.is_set (Editors) and utilities.is_set (Date) then -- when Editors make sure that Authors gets terminated
Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space
end
if (not utilities.is_set (Date)) then -- when date is set it's in parentheses; no Contributors termination
Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space
end
text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc );
else
text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc );
end
elseif utilities.is_set (Editors) then
if utilities.is_set (Date) then
if EditorCount <= 1 then
Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editor'];
else
Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editors'];
end
else
if EditorCount <= 1 then
Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "
else
Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " "
end
end
text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc );
else
if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then
text = safe_join( {Chapter, Place, tcommon, pgtext, Date, idcommon}, sepc );
else
text = safe_join( {Chapter, Place, tcommon, Date, pgtext, idcommon}, sepc );
end
end
if utilities.is_set (PostScript) and PostScript ~= sepc then
text = safe_join( {text, sepc}, sepc ); -- Deals with italics, spaces, etc.
if '.' == sepc then -- remove final seperator if present
text = text:gsub ('%' .. sepc .. '$', ''); -- dot must be escaped here
else
text = mw.ustring.gsub (text, sepc .. '$', ''); -- using ustring for non-dot sepc (likely a non-Latin character)
end
end
text = safe_join( {text, PostScript}, sepc );
-- Now enclose the whole thing in a <cite> element
local options_t = {};
options_t.class = cite_class_attribute_make (config.CitationClass, Mode);
local Ref = is_valid_parameter_value (A['Ref'], A:ORIGIN('Ref'), cfg.keywords_lists['ref'], nil, true); -- nil when |ref=harv; A['Ref'] else
if 'none' ~= cfg.keywords_xlate[(Ref and Ref:lower()) or ''] then
local namelist_t = {}; -- holds selected contributor, author, editor name list
local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation
if #c > 0 then -- if there is a contributor list
namelist_t = c; -- select it
elseif #a > 0 then -- or an author list
namelist_t = a;
elseif #e > 0 then -- or an editor list
namelist_t = e;
end
local citeref_id;
if #namelist_t > 0 then -- if there are names in namelist_t
citeref_id = make_citeref_id (namelist_t, year); -- go make the CITEREF anchor
if mw.uri.anchorEncode (citeref_id) == ((Ref and mw.uri.anchorEncode (Ref)) or '') then -- Ref may already be encoded (by {{sfnref}}) so citeref_id must be encoded before comparison
utilities.set_message ('maint_ref_duplicates_default');
end
else
citeref_id = ''; -- unset
end
options_t.id = Ref or citeref_id;
end
if string.len (text:gsub('%b<>', '')) <= 2 then -- remove html and html-like tags; then get length of what remains;
z.error_cats_t = {}; -- blank the categories list
z.error_msgs_t = {}; -- blank the error messages list
OCinSoutput = nil; -- blank the metadata string
text = ''; -- blank the the citation
utilities.set_message ('err_empty_citation'); -- set empty citation message and category
end
local render_t = {}; -- here we collect the final bits for concatenation into the rendered citation
if is_preview_mode and (0 ~= #z.error_msgs_t or 0 ~= #z.maint_cats_t) then -- when in preview mode
if not utilities.is_set (options_t.id) then -- and when this template has not created an anchor ID
math.randomseed (tonumber (mw.getLanguage ('en'):formatDate ('U')) * 10000 + os.clock() * 10000);
options_t.id = 'CITEREF_temp_preview_id_' .. math.random (100000, 999999); -- create temporary anchor ID for preview mode
end
end
if utilities.is_set (options_t.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags
options_t.id = mw.uri.anchorEncode(options_t.id); -- do this here; also used when adding preview warning messages
table.insert (render_t, utilities.substitute (cfg.presentation['cite-id'], {options_t.id, mw.text.nowiki(options_t.class), text})); -- when |ref= is set or when there is a namelist
else
table.insert (render_t, utilities.substitute (cfg.presentation['cite'], {mw.text.nowiki(options_t.class), text})); -- when |ref=none or when namelist_t empty and |ref= is missing or is empty
end
if OCinSoutput then -- blanked when citation is 'empty' so don't bother to add boilerplate metadata span
table.insert (render_t, utilities.substitute (cfg.presentation['ocins'], OCinSoutput)); -- format and append metadata to the citation
end
local template_name = cfg.citation_class_map_t[config.CitationClass];
local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]';
local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: ';
if 0 ~= #z.error_msgs_t then
mw.addWarning (utilities.substitute (cfg.messages.warning_msg_e, {template_link, options_t.id}));
table.insert (render_t, ' '); -- insert a space between citation and its error messages
table.sort (z.error_msgs_t); -- sort the error messages list; sorting includes wrapping <span> and <code> tags; hidden-error sorts ahead of visible-error
local hidden = true; -- presume that the only error messages emited by this template are hidden
for _, v in ipairs (z.error_msgs_t) do -- spin through the list of error messages
if v:find ('cs1-visible-error', 1, true) then -- look for the visible error class name
hidden = false; -- found one; so don't hide the error message prefix
break; -- and done because no need to look further
end
end
z.error_msgs_t[1] = table.concat ({utilities.error_comment (msg_prefix, hidden), z.error_msgs_t[1]}); -- add error message prefix to first error message to prevent extraneous punctuation
table.insert (render_t, table.concat (z.error_msgs_t, '; ')); -- make a big string of error messages and add it to the rendering
end
if 0 ~= #z.maint_cats_t then
mw.addWarning (utilities.substitute (cfg.messages.warning_msg_m, {template_link, options_t.id}));
table.sort (z.maint_cats_t); -- sort the maintenance messages list
local maint_msgs_t = {}; -- here we collect all of the maint messages
if 0 == #z.error_msgs_t then -- if no error messages
table.insert (maint_msgs_t, msg_prefix); -- insert message prefix in maint message livery
end
for _, v in ipairs( z.maint_cats_t ) do -- append maintenance categories
table.insert (maint_msgs_t, -- assemble new maint message and add it to the maint_msgs_t table
table.concat ({v, ' (', utilities.substitute (cfg.messages[':cat wikilink'], v), ')'})
);
end
table.insert (render_t, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs_t, ' '))); -- wrap the group of maint messages with proper presentation and save
end
if not no_tracking_cats then
local sort_key;
local cat_wikilink = 'cat wikilink';
if cfg.enable_sort_keys then -- when namespace sort keys enabled
local namespace_number = mw.title.getCurrentTitle().namespace; -- get namespace number for this wikitext
sort_key = (0 ~= namespace_number and (cfg.name_space_sort_keys[namespace_number] or cfg.name_space_sort_keys.other)) or nil; -- get sort key character; nil for mainspace
cat_wikilink = (not sort_key and 'cat wikilink') or 'cat wikilink sk'; -- make <cfg.messages> key
end
for _, v in ipairs (z.error_cats_t) do -- append error categories
table.insert (render_t, utilities.substitute (cfg.messages[cat_wikilink], {v, sort_key}));
end
if cfg.id_limits_data_load_fail then -- boolean true when load failed
utilities.set_message ('maint_id_limit_load_fail'); -- done here because this maint cat emits no message
end
for _, v in ipairs (z.maint_cats_t) do -- append maintenance categories
table.insert (render_t, utilities.substitute (cfg.messages[cat_wikilink], {v, sort_key}));
end
for _, v in ipairs (z.prop_cats_t) do -- append properties categories
table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v)); -- no sort keys
end
end
return table.concat (render_t); -- make a big string and done
end
--[[--------------------------< V A L I D A T E >--------------------------------------------------------------
Looks for a parameter's name in one of several whitelists.
Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
local function validate (name, cite_class, empty)
local enum_name; -- parameter name with enumerator (if any) replaced with '#'
local state;
local function state_test () -- local function to do testing of state values; operates on the upvalues <state> and <name>
if true == state then return true; end -- valid actively supported parameter
if false == state then
if empty then return nil; end -- empty deprecated parameters are treated as unknowns
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
if 'tracked' == state then
local base_name = name:gsub ('%d', ''); -- strip enumerators from parameter names that have them to get the base name
utilities.add_prop_cat ('tracked-param', {base_name}, base_name); -- add a properties category; <base_name> modifies <key>
return true;
end
return nil;
end
if 'string' ~= type (name) or name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted; positional params are 'number' type; not supported
return nil;
end
-- replace enumerator digit(s) with # (|last25= becomes |last#=) (mw.ustring because non-Western 'local' digits)
enum_name = mw.ustring.gsub (name, '%d+$', '#'); -- where enumerator is last charaters in parameter name (these to protect |s2cid=)
enum_name = mw.ustring.gsub (enum_name, '%d+([%-l])', '#%1'); -- where enumerator is in the middle of the parameter name; |author#link= is the oddity
if 'document' == cite_class then -- special case for {{cite document}}
state = whitelist.document_parameters_t[enum_name]; -- this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
return false;
end
if utilities.in_array (cite_class, whitelist.preprint_template_list_t) then -- limited parameter sets allowed for these templates
state = whitelist.limited_parameters_t[enum_name]; -- this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
state = whitelist.preprint_arguments_t[cite_class][name]; -- look in the parameter-list for the template identified by cite_class
if true == state_test () then return true; end
return false; -- not supported because not found or name is set to nil
end -- end limited parameter-set templates
if utilities.in_array (cite_class, whitelist.unique_param_template_list_t) then -- template-specific parameters for templates that accept parameters from the basic argument list
state = whitelist.unique_arguments_t[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class
if true == state_test () then return true; end
end -- if here, fall into general validation
state = whitelist.common_parameters_t[enum_name]; -- all other templates; all normal parameters allowed; this list holds enumerated and nonenumerated parameters
if true == state_test () then return true; end
return false; -- not supported because not found or name is set to nil
end
--[=[-------------------------< I N T E R _ W I K I _ C H E C K >----------------------------------------------
check <value> for inter-language interwiki-link markup. <prefix> must be a MediaWiki-recognized language
code. when these values have the form (without leading colon):
[[<prefix>:link|label]] return label as plain-text
[[<prefix>:link]] return <prefix>:link as plain-text
return value as is else
]=]
local function inter_wiki_check (parameter, value)
local prefix = value:match ('%[%[(%a+):'); -- get an interwiki prefix if one exists
local _;
if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so
utilities.set_message ('err_bad_paramlink', parameter); -- emit an error message
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink
end
return value;
end
--[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------
Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal
sign, compare the alphanumeric string to the list of cs1|2 parameters. If found, then the string is possibly a
parameter that is missing its pipe. There are two tests made:
{{cite ... |title=Title access-date=2016-03-17}} -- the first parameter has a value and whitespace separates that value from the missing pipe parameter name
{{cite ... |title=access-date=2016-03-17}} -- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki)
cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc. To prevent false positives XML/HTML
tags are removed before the search.
If a missing pipe is detected, this function adds the missing pipe maintenance category.
]]
local function missing_pipe_check (parameter, value)
local capture;
value = value:gsub ('%b<>', ''); -- remove XML/HTML tags because attributes: class=, title=, etc.
capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes
if capture and validate (capture) then -- if the capture is a valid parameter name
utilities.set_message ('err_missing_pipe', parameter);
end
end
--[[--------------------------< H A S _ E X T R A N E O U S _ P U N C T >--------------------------------------
look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked
]]
local function has_extraneous_punc (param, value)
if 'number' == type (param) then
return;
end
param = param:gsub ('%d+', '#'); -- enumerated name-list mask params allow terminal punct; normalize
if cfg.punct_skip[param] then
return; -- parameter name found in the skip table so done
end
if value:match ('[,;:]$') then
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
if value:match ('^=') then -- sometimes an extraneous '=' character appears ...
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
end
--[[--------------------------< H A S _ T W L _ U R L >--------------------------------------------------------
look for The Wikipedia Library urls in url-holding parameters. TWL urls are accessible only for readers who are
active extended confirmed Wikipedia editors. This function sets an error message when such urls are discovered
and when appropriate, sets the |<param>-url-access=subscription. returns nothing.
looks for: '.wikipedialibrary.idm.oclc.org'
]]
local function has_twl_url (url_params_t, cite_args_t)
local url_error_t = {}; -- sequence of url-holding parameters that have a TWL url
for param, value in pairs (url_params_t) do
if value:find ('%.wikipedialibrary%.idm%.oclc%.org') then -- has the TWL base url?
table.insert (url_error_t, param); -- add parameter name to the error list
end
end
if 0 ~= #url_error_t then -- non-zero when there are errors
table.sort (url_error_t); -- sor for error messaging
for i, param in ipairs (url_error_t) do
if cfg.url_access_map_t[param] then -- if <param> has a matching -access parameter
cite_args_t[cfg.url_access_map_t[param]] = cfg.keywords_xlate.subscription; -- set |<param>-url-access=subscription
end
url_error_t[i] = utilities.wrap_style ('parameter', param); -- make the parameter pretty for error message
end
utilities.set_message ('err_param_has_twl_url', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message
end
end
--[[--------------------------< M I S C _ U R L _ D E T E C T >------------------------------------------------
look for miscellaneous urls that might be converted to, or are duplicates of, identifiers.
]]
local misc_url_patterns_t = {
'idm%.oclc%.org', -- but not wikipedialibrary.idm.oclc.org; has_twl_url()
'https?://citeseerx?%.ist%.psu%.edu/', -- simplified so we catch all citeseer and citeseerx urls except ~/document/... (the 'new' form)
}
local ignore_patterns_t = {
'wikipedialibrary.idm.oclc.org', -- handled by has_twl_url()
'https?://citeseerx?%.ist%.psu%.edu/document', -- 'new'-form citeseerx urls that mostly work; ignore for now
}
local function misc_url_detect (url_params_t)
local ignore_flag = false;
for _, value in pairs (url_params_t) do
for _, ignore_pattern in ipairs (ignore_patterns_t) do
if value:find (ignore_pattern) then -- matches this ignore_pattern?
ignore_flag = true; -- found a pattern to ignore
break; --
end
end
if not ignore_flag then -- if ignore_flag is set then don't bother to test this url <value>
for _, misc_pattern in ipairs (misc_url_patterns_t) do
if value:find (misc_pattern) then -- matches this misc_pattern?
utilities.set_message ('maint_misc_url'); -- found one; set the message
return; -- and done; no need to test other <value>s
end
end
end
ignore_flag = false; -- reset
end
end
--[[--------------------------< H A S _ E X T R A N E O U S _ U R L >------------------------------------------
look for extraneous url parameter values; parameters listed in skip table are not checked
]]
local function has_extraneous_url (non_url_param_t)
local url_error_t = {};
check_for_url (non_url_param_t, url_error_t); -- extraneous url check
if 0 ~= #url_error_t then -- non-zero when there are errors
table.sort (url_error_t);
utilities.set_message ('err_param_has_ext_link', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message
end
end
--[[--------------------------< _ C I T A T I O N >------------------------------------------------------------
Module entry point
frame – from template call (citation()); may be nil when called from another module
args_t – table of all cs1|2 parameters in the template (the parent frame)
config_t – table of template-supplied parameter (the #invoke frame)
]]
local function _citation (frame, args_t, config_t) -- save a copy in case we need to display an error message in preview mode
if not frame then
frame = mw.getCurrentFrame(); -- if called from another module, get a frame for frame-provided functions
end
-- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here)
local sandbox = ((config_t.SandboxPath and '' ~= config_t.SandboxPath) and config_t.SandboxPath) or '/sandbox'; -- sandbox path from {{#invoke:Citation/CS1/sandbox|citation|SandboxPath=/...}}
is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module?
sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else
cfg = mw.loadData ('Module:Citation/CS1/Configuration' .. sandbox); -- load sandbox versions of support modules when {{#invoke:Citation/CS1/sandbox|...}}; live modules else
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist' .. sandbox);
utilities = require ('Module:Citation/CS1/Utilities' .. sandbox);
validation = require ('Module:Citation/CS1/Date_validation' .. sandbox);
identifiers = require ('Module:Citation/CS1/Identifiers' .. sandbox);
metadata = require ('Module:Citation/CS1/COinS' .. sandbox);
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables
identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module
validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module
metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities
local cite_args_t = {}; -- because args_t is the parent (template) frame args (which cannot be modified); params and their values will be placed here
is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}'));
local suggestions = {}; -- table where we store suggestions if we need to loadData them
local error_text; -- used as a flag
local capture; -- the single supported capture when matching unknown parameters using patterns
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing
for k, v in pairs (args_t) do -- get parameters from the parent (template) frame
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string
if v ~= '' then
if cfg.enum_needs_xlation and 'string' == type (k) then -- for wikis that set date_names['local_digits'] to non-western digits
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- translate 'local' digits enumerators to Western 0-9
end
if not validate( k, config_t.CitationClass ) then
if type (k) ~= 'string' then -- exclude empty numbered parameters
if v:match("%S+") ~= nil then
error_text = utilities.set_message ('err_text_ignored', {v});
end
elseif validate (k:lower(), config_t.CitationClass) then
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter
else
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' .. sandbox); --load sandbox version of suggestion module when {{#invoke:Citation/CS1/sandbox|...}}; live module else
end
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
capture = k:match (pattern); -- the whole match if no capture in pattern else the capture if a match
if capture then -- if the pattern matches
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
if validate (param, config_t.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists)
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message
else
error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template
v = ''; -- unset
end
end
end
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion?
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config_t.CitationClass) then
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]});
else
utilities.set_message ('err_parameter_ignored', {k});
v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists)
end
end
end
end
cite_args_t[k] = v; -- save this parameter and its value
elseif not utilities.is_set (v) then -- for empty parameters
if not validate (k, config_t.CitationClass, true) then -- is this empty parameter a valid parameter
k = ('' == k) and cfg.err_msg_supl.empty_str or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text
table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list
end
end
end
if 0 ~= #empty_unknowns then -- create empty unknown error message
utilities.set_message ('err_param_unknown_empty', {
1 == #empty_unknowns and '' or 's',
utilities.make_sep_list (#empty_unknowns, empty_unknowns)
});
end
local non_url_param_t = {}; -- table of parameters and values that are not url-holding parameters
local url_param_t = {}; -- table of url-holding paramters and their values
for k, v in pairs (cite_args_t) do
if 'string' == type (k) then -- don't evaluate positional parameters
has_invisible_chars (k, v); -- look for invisible characters
end
has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values
missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe?
cite_args_t[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label
if 'string' == type (k) then -- when parameter k is not positional
if not cfg.url_skip[k] then -- and not in url skip table
non_url_param_t[k] = v; -- make a parameter/value list for extraneous url check
else -- and is in url skip table (a url-holding parameter)
url_param_t[k] = v; -- make a parameter/value list to check for values that are The Wikipedia Library url
end
end
end
if cfg.suppress_archive_today_urls then
has_archive_today_url (cite_args_t); -- look for and suppress archive.today urls and dependent parameters for all templates
end
has_extraneous_url (non_url_param_t); -- look for url in parameter values where a url does not belong
has_twl_url (url_param_t, cite_args_t); -- look for url-holding parameters that hold a The Wikipedia Library url
misc_url_detect (url_param_t); -- look for url-holding parameters that hold certain miscellaneous urls
return table.concat ({
frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1' .. sandbox .. '/styles.css'}),
citation0 (config_t, cite_args_t)
});
end
--[[--------------------------< C I T A T I O N >--------------------------------------------------------------
Template entry point
]]
local function citation (frame)
local config_t = {}; -- table to store parameters from the module {{#invoke:}}
local args_t = frame:getParent().args; -- get template's preset parameters
for k, v in pairs (frame.args) do -- get parameters from the {{#invoke}} frame
config_t[k] = v;
-- args_t[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep?
end
return _citation (frame, args_t, config_t)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
citation = citation, -- template entry point
_citation = _citation, -- module entry point
}
mzkfjlhyhvftcb93lj0ik7zu7t1myhw
Module:Citation/CS1/Configuration
828
925
9003
2026-08-11T19:05:25Z
en>Trappist the monk
0
synch from sandbox;
9003
Scribunto
text/plain
local lang_obj = mw.getContentLanguage(); -- make a language object for the local language; used here for languages and dates
--[[--------------------------< S E T T I N G S >--------------------------------------------------------------
boolean settings used to control various things. these setting located here to make them easy to find
]]
-- these settings local to this module only
local local_digits_from_mediawiki = false; -- for i18n; when true, module fills date_names['local_digits'] from MediaWiki; manual fill required else; always false at en.wiki
-- these settings exported to other modules
local use_identifier_redirects = true; -- when true use redirect name for identifier label links; always true at en.wiki
local local_lang_cat_enable = false; -- when true categorizes pages where |language=<local wiki's language>; always false at en.wiki
local date_name_auto_xlate_enable = false; -- when true translates English month-names to the local-wiki's language month names; always false at en.wiki
local date_digit_auto_xlate_enable = false; -- when true translates Western date digit to the local-wiki's language digits (date_names['local_digits']); always false at en.wiki
local enable_sort_keys = true; -- when true module adds namespace sort keys to error and maintenance category links
local suppress_archive_today_urls = true; -- when true module suppresses all parameters with an archive.today url and any deprendent parameters
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------
List of namespaces identifiers for namespaces that will not be included in citation error categories.
Same as setting notracking = true by default.
For wikis that have a current version of Module:cs1 documentation support, this #invoke will return an unordered
list of namespace names and their associated identifiers:
{{#invoke:cs1 documentation support|uncategorized_namespace_lister|all=<anything>}}
]]
local uncategorized_namespaces_t = {[2]=true}; -- init with user namespace id
for k, _ in pairs (mw.site.talkNamespaces) do -- add all talk namespace ids
uncategorized_namespaces_t[k] = true;
end
local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases', '/[^/]*[Ll]og', '/[Aa]rchive'}; -- list of Lua patterns found in page names of pages we should not categorize
--[[
at en.wiki Greek characters are used as sort keys for certain items in a category so that those items are
placed at the end of a category page. See Wikipedia:Categorization#Sort_keys. That works well for en.wiki
because English is written using the Latn script. This may not work well for other languages. At en.wiki it
is desireable to place content from certain namespaces at the end of a category listing so the module adds sort
keys to error and maintenance category links when rendering a cs1|2 template on a page in that namespace.
i18n: if this does not work well for your language, set <enable_sort_keys> to false.
]]
local name_space_sort_keys = { -- sort keys to be used with these namespaces:
[4] = 'ω', -- wikipedia; omega
[10] = 'τ', -- template; tau
[118] = 'Δ', -- draft; delta
['other'] = 'ο', -- all other non-talk namespaces except main (article); omicron
}
--[[--------------------------< M E S S A G E S >--------------------------------------------------------------
Translation table
The following contains fixed text that may be output as part of a citation.
This is separated from the main body to aid in future translations of this
module.
]]
local messages = {
['agency'] = '$1 $2', -- $1 is sepc, $2 is agency
['archived-dead'] = 'Archived from $1 on $2',
['archived-live'] = '$1 from the original on $2',
['archived-unfit'] = 'Archived from the original on $1',
['archived'] = 'Archived',
['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword
['cartography'] = 'Cartography by $1',
['collaboration'] = '$1 ($2)', -- $1 is author with et al, $2 is collaboration
['editor'] = 'ed.',
['editors'] = 'eds.',
['edition'] = '($1 ed.)',
['episode'] = 'Episode $1',
['et al'] = 'et al.',
['in'] = 'In', -- edited works
['inactive'] = ' (inactive $1)', -- $1 is date which the doi was found to be broken in
['inset'] = '$1 inset',
['interview'] = 'Interviewed by $1',
invisible_1 = '$1 $2', -- $1 stripmarker name; $2 is text from <invisible_chars[1]>
invisible_2 = '$1 character', -- $1 character name from <invisible_chars[1]>
['mismatch'] = '<code class="cs1-code">|$1=</code> / <code class="cs1-code">|$2=</code> mismatch', -- $1 is year param name; $2 is date param name
['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1',
['notitle'] = 'No title', -- for |title=(()) and (in the future) |title=none
['original'] = 'the original',
['origdate'] = ' [$1]',
['published'] = ' (published $1)',
['retrieved'] = 'Retrieved $1',
['season'] = 'Season $1',
['section'] = '§ $1',
['sections'] = '§§ $1',
['series'] = '$1 $2', -- $1 is sepc, $2 is series
['seriesnum'] = 'Series $1',
['translated'] = 'Translated by $1',
['type'] = ' ($1)', -- for titletype
wikidata = 'Wikidata', -- these used for interwikilinked author/editor/... names
wikipedia = 'Wikipedia',
wikisource = 'Wikisource',
['written'] = 'Written at $1',
['vol'] = '$1 Vol. $2', -- $1 is sepc; bold journal style volume is in presentation{}
['vol-no'] = '$1 Vol. $2, no. $3', -- sepc, volume, issue (alternatively insert $1 after $2, but then we'd also have to change capitalization)
['issue'] = '$1 No. $2', -- $1 is sepc
['art'] = '$1 Art. $2', -- $1 is sepc; for {{cite conference}} only
['vol-art'] = '$1 Vol. $2, art. $3', -- sepc, volume, article-number; for {{cite conference}} only
['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{}
['j-issue'] = ' ($1)',
['j-article-num'] = ' $1', -- TODO: any punctuation here? static text?
['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc
['p-prefix'] = "$1 p. $2", -- $1 is sepc
['pp-prefix'] = "$1 pp. $2", -- $1 is sepc
['j-page(s)'] = ': $1', -- same for page and pages
['sheet'] = '$1 Sheet $2', -- $1 is sepc
['sheets'] = '$1 Sheets $2', -- $1 is sepc
['j-sheet'] = ': Sheet $1',
['j-sheets'] = ': Sheets $1',
['language'] = '(in $1)',
['via'] = " – via $1",
['event'] = 'Event occurs at',
['minutes'] = ' $1 minutes in', -- $1 is the number of minutes
-- Determines the location of the help page
['help page link'] = 'Help:CS1 errors',
['help page label'] = 'help',
-- categories
['cat wikilink'] = '[[Category:$1]]', -- $1 is the category name
['cat wikilink sk'] = '[[Category:$1|$2]]', -- $1 is the category name; $2 is namespace sort key
[':cat wikilink'] = '[[:Category:$1|link]]', -- category name as maintenance message wikilink; $1 is the category name
-- Internal errors (should only occur if configuration is bad)
['undefined_error'] = 'Called with an undefined error condition',
['unknown_ID_key'] = 'Unrecognized ID key: ', -- an ID key in id_handlers not found in ~/Identifiers func_map{}
['unknown_ID_access'] = 'Unrecognized ID access keyword: ', -- an ID access keyword in id_handlers not found in keywords_lists['id-access']{}
['unknown_argument_map'] = 'Argument map not defined for this variable',
['bare_url_no_origin'] = 'Bare URL found but origin indicator is nil or empty',
['warning_msg_e'] = '<span style="color:#d33"><code style="color: inherit; background: inherit; border: none; padding: inherit;">{{$1}}</code>: this [[#$2|reference]] has errors</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link; $2 is anchor ID
['warning_msg_m'] = '<span style="color:#085"><code style="color: inherit; background: inherit; border: none; padding: inherit;">{{$1}}</code>: this [[#$2|reference]] has maintenance messages</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link; $2 is anchor ID
}
--[[--------------------------< C I T A T I O N _ C L A S S _ M A P >------------------------------------------
this table maps the value assigned to |CitationClass= in the cs1|2 templates to the canonical template name when
the value assigned to |CitationClass= is different from the canonical template name. |CitationClass= values are
used as class attributes in the <cite> tag that encloses the citation so these names may not contain spaces while
the canonical template name may. These names are used in warning_msg_e and warning_msg_m to create links to the
template's documentation when an article is displayed in preview mode.
]]
local citation_class_map_t = { -- TODO: in Module:Cite/config write a function to use this table
arxiv = 'cite arXiv', -- as the source for known_templates_t and citation_classes_t
['audio-visual'] = 'cite AV media',
['AV-media-notes'] = 'cite AV media notes',
biorxiv = 'cite bioRxiv',
book = 'cite book',
citation = 'citation',
citeseerx = 'cite CiteSeerX',
conference = 'cite conference',
document = 'cite document',
encyclopaedia = 'cite encyclopedia',
episode = 'cite episode',
interview = 'cite interview',
journal = 'cite journal',
magazine = 'cite magazine',
mailinglist = 'cite mailing list',
map = 'cite map',
medrxiv = 'cite medRxiv',
news = 'cite news',
newsgroup = 'cite newsgroup',
podcast = 'cite podcast',
pressrelease = 'cite press release',
report = 'cite report',
serial = 'cite serial',
sign = 'cite sign',
speech = 'cite speech',
ssrn = 'cite SSRN',
techreport = 'cite tech report',
thesis = 'cite thesis',
web = 'cite web',
}
--[=[-------------------------< E T _ A L _ P A T T E R N S >--------------------------------------------------
This table provides Lua patterns for the phrase "et al" and variants in name text
(author, editor, etc.). The main module uses these to identify and emit the 'etal' message.
]=]
local et_al_patterns = {
"[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\"']*$", -- variations on the 'et al' theme
"[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\"']*$", -- variations on the 'et alia', 'et alii' and 'et aliae' themes (false positive 'et aliie' unlikely to match)
"[;,]? *%f[%a]and [Oo]thers", -- an alternative to et al.
"%[%[ *[Ee][Tt]%.? *[Aa][Ll]%.? *%]%]", -- a wikilinked form
"%(%( *[Ee][Tt]%.? *[Aa][Ll]%.? *%)%)", -- a double-bracketed form (to counter partial removal of ((...)) syntax)
"[%(%[] *[Ee][Tt]%.? *[Aa][Ll]%.? *[%)%]]", -- a bracketed form
}
--[[--------------------------< P R E S E N T A T I O N >------------------------
Fixed presentation markup. Originally part of citation_config.messages it has
been moved into its own, more semantically correct place.
]]
local presentation =
{
-- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display
['hidden-error'] = '<span class="cs1-hidden-error citation-comment">$1</span>',
['visible-error'] = '<span class="cs1-visible-error citation-comment">$1</span>',
['hidden-maint'] = '<span class="cs1-maint citation-comment">$1</span>',
['accessdate'] = '<span class="reference-accessdate">$1$2</span>', -- to allow editors to hide accessdate using personal CSS
['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like
['cite'] = '<cite class="$1">$2</cite>'; -- for use when citation does not have a namelist and |ref= not set so no id="..." attribute
['cite-id'] = '<cite id="$1" class="$2">$3</cite>'; -- for use when when |ref= is set or when citation has a namelist
['format'] = ' <span class="cs1-format">($1)</span>', -- for |format=, |chapter-format=, etc.
['interwiki'] = ' <span class="cs1-format">[in $1]</span>', -- for interwiki-language-linked author, editor, etc
['interproj'] = ' <span class="cs1-format">[at $1]</span>', -- for interwiki-project-linked author, editor, etc (:d: and :s: supported; :w: ignored)
-- various access levels, for |access=, |doi-access=, |arxiv=, ...
-- narrow no-break space   may work better than nowrap CSS. Or not? Browser support?
['ext-link-access-signal'] = '<span class="$1" title="$2">$3</span>', -- external link with appropriate lock icon
['free'] = {class='id-lock-free', title='Freely accessible'}, -- classes defined in Module:Citation/CS1/styles.css
['registration'] = {class='id-lock-registration', title='Free registration required'},
['limited'] = {class='id-lock-limited', title='Free access subject to limited trial, subscription normally required'},
['subscription'] = {class='id-lock-subscription', title='Paid subscription required'},
['interwiki-icon'] = '<span class="$1" title="$2">$3</span>',
['class-wikisource'] = 'cs1-ws-icon',
['italic-title'] = "''$1''",
['kern-left'] = '<span class="cs1-kern-left"></span>$1', -- spacing to use when title contains leading single or double quote mark
['kern-right'] = '$1<span class="cs1-kern-right"></span>', -- spacing to use when title contains trailing single or double quote mark
['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span>
['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space)
['ocins'] = '<span title="$1" class="Z3988"></span>',
['parameter'] = '<code class="cs1-code">|$1=</code>',
['ps_cs1'] = '.'; -- CS1 style postscript (terminal) character
['ps_cs2'] = ''; -- CS2 style postscript (terminal) character (empty string)
['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content
['quoted-title'] = '"$1"',
['sep_cs1'] = '.', -- CS1 element separator
['sep_cs2'] = ',', -- CS2 separator
['sep_nl'] = ';', -- CS1|2 style name-list separator between names is a semicolon
['sep_nl_and'] = ' and ', -- used as last nl sep when |name-list-style=and and list has 2 items
['sep_nl_end'] = '; and ', -- used as last nl sep when |name-list-style=and and list has 3+ names
['sep_name'] = ', ', -- CS1|2 style last/first separator is <comma><space>
['sep_nl_vanc'] = ',', -- Vancouver style name-list separator between authors is a comma
['sep_name_vanc'] = ' ', -- Vancouver style last/first separator is a space
['sep_list'] = ', ', -- used for |language= when list has 3+ items except for last sep which uses sep_list_end
['sep_list_pair'] = ' and ', -- used for |language= when list has 2 items
['sep_list_end'] = ', and ', -- used as last list sep for |language= when list has 3+ items
['trans-italic-title'] = "[''$1'']",
['trans-quoted-title'] = "[$1]", -- for |trans-title= and |trans-quote=
['vol-bold'] = '$1 <b>$2</b>', -- sepc, volume; for bold journal cites; for other cites ['vol'] in messages{}
}
--[[--------------------------< A L I A S E S >---------------------------------
Aliases table for commonly passed parameters.
Parameter names on the right side in the assignments in this table must have been
defined in the Whitelist before they will be recognized as valid parameter names
]]
local aliases = {
['AccessDate'] = {'access-date', 'accessdate'}, -- Used by InternetArchiveBot
['Agency'] = 'agency',
['ArchiveDate'] = {'archive-date', 'archivedate'}, -- Used by InternetArchiveBot
['ArchiveFormat'] = 'archive-format',
['ArchiveURL'] = {'archive-url', 'archiveurl'}, -- Used by InternetArchiveBot
['ArticleNumber'] = 'article-number',
['ASINTLD'] = 'asin-tld',
['At'] = 'at', -- Used by InternetArchiveBot
['Authors'] = {'people', 'credits'},
['BookTitle'] = {'book-title', 'booktitle'},
['Cartography'] = 'cartography',
['Chapter'] = {'chapter', 'contribution', 'entry', 'article', 'section'},
['ChapterFormat'] = {'chapter-format', 'contribution-format', 'entry-format',
'article-format', 'section-format'};
['ChapterURL'] = {'chapter-url', 'contribution-url', 'entry-url', 'article-url', 'section-url'}, -- Used by InternetArchiveBot
['ChapterUrlAccess'] = {'chapter-url-access', 'contribution-url-access',
'entry-url-access', 'article-url-access', 'section-url-access'}, -- Used by InternetArchiveBot
['Class'] = 'class', -- cite arxiv and arxiv identifier
['Collaboration'] = 'collaboration',
['Conference'] = {'conference', 'event'},
['ConferenceFormat'] = 'conference-format',
['ConferenceURL'] = 'conference-url', -- Used by InternetArchiveBot
['Date'] = {'date', 'air-date', 'airdate'}, -- air-date and airdate for cite episode and cite serial only
['Degree'] = 'degree',
['DF'] = 'df',
['DisplayAuthors'] = {'display-authors', 'display-subjects'},
['DisplayContributors'] = 'display-contributors',
['DisplayEditors'] = 'display-editors',
['DisplayInterviewers'] = 'display-interviewers',
['DisplayTranslators'] = 'display-translators',
['Docket'] = 'docket',
['DoiBroken'] = 'doi-broken-date',
['Edition'] = 'edition',
['Embargo'] = 'pmc-embargo-date',
['Encyclopedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'}, -- cite encyclopedia only
['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode?
['Format'] = 'format',
['ID'] = {'id', 'ID'},
['Inset'] = 'inset',
['Issue'] = {'issue', 'number'},
['Language'] = {'language', 'lang'},
['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only
['Map'] = 'map', -- cite map only
['MapFormat'] = 'map-format', -- cite map only
['MapURL'] = {'map-url', 'mapurl'}, -- cite map only -- Used by InternetArchiveBot
['MapUrlAccess'] = 'map-url-access', -- cite map only -- Used by InternetArchiveBot
['Minutes'] = 'minutes',
['Mode'] = 'mode',
['NameListStyle'] = 'name-list-style',
['Network'] = 'network',
['Newsgroup'] = 'newsgroup', -- cite newsgroup only
['NoPP'] = {'no-pp', 'nopp'},
['NoTracking'] = {'no-tracking', 'template-doc-demo'},
['Number'] = 'number', -- this case only for cite techreport
['OrigDate'] = {'orig-date', 'orig-year', 'origyear'},
['Others'] = 'others',
['Page'] = {'page', 'p'}, -- Used by InternetArchiveBot
['Pages'] = {'pages', 'pp'}, -- Used by InternetArchiveBot
['Periodical'] = {'journal', 'magazine', 'newspaper', 'periodical', 'website', 'work'},
['Place'] = {'place', 'location'},
['PostScript'] = 'postscript',
['PublicationDate'] = {'publication-date', 'publicationdate'},
['PublicationPlace'] = {'publication-place', 'publicationplace'},
['PublisherName'] = {'publisher', 'institution'},
['Quote'] = {'quote', 'quotation'},
['QuotePage'] = 'quote-page',
['QuotePages'] = 'quote-pages',
['Ref'] = 'ref',
['Scale'] = 'scale',
['ScriptChapter'] = {'script-chapter', 'script-contribution', 'script-entry',
'script-article', 'script-section'},
['ScriptEncyclopedia'] = {'script-encyclopedia', 'script-encyclopaedia'}, -- cite encyclopedia only
['ScriptMap'] = 'script-map',
['ScriptPeriodical'] = {'script-journal', 'script-magazine', 'script-newspaper',
'script-periodical', 'script-website', 'script-work'},
['ScriptQuote'] = 'script-quote',
['ScriptTitle'] = 'script-title', -- Used by InternetArchiveBot
['Season'] = 'season',
['Sections'] = 'sections', -- cite map only
['Series'] = {'series', 'version'},
['SeriesLink'] = {'series-link', 'serieslink'},
['SeriesNumber'] = {'series-number', 'series-no'},
['Sheet'] = 'sheet', -- cite map only
['Sheets'] = 'sheets', -- cite map only
['Station'] = 'station',
['Time'] = 'time',
['TimeCaption'] = 'time-caption',
['Title'] = 'title', -- Used by InternetArchiveBot
['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot
['TitleNote'] = {'title-note', 'department'},
['TitleType'] = {'type', 'medium'},
['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution',
'trans-entry', 'trans-section'},
['Transcript'] = 'transcript',
['TranscriptFormat'] = 'transcript-format',
['TranscriptURL'] = 'transcript-url', -- Used by InternetArchiveBot
['TransEncyclopedia'] = {'trans-encyclopedia', 'trans-encyclopaedia'}, -- cite encyclopedia only
['TransMap'] = 'trans-map', -- cite map only
['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper',
'trans-periodical', 'trans-website', 'trans-work'},
['TransQuote'] = 'trans-quote',
['TransTitle'] = 'trans-title', -- Used by InternetArchiveBot
['URL'] = {'url', 'URL'}, -- Used by InternetArchiveBot
['UrlAccess'] = 'url-access', -- Used by InternetArchiveBot
['UrlStatus'] = 'url-status', -- Used by InternetArchiveBot
['Vauthors'] = 'vauthors',
['Veditors'] = 'veditors',
['Via'] = 'via',
['Volume'] = 'volume',
['Year'] = 'year',
['AuthorList-First'] = {"first#", "author-first#", "author#-first", "author-given#", "author#-given",
"subject-first#", "subject#-first", "subject-given#", "subject#-given",
"given#"},
['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "author-surname#", "author#-surname",
"subject-last#", "subject#-last", "subject-surname#", "subject#-surname",
"author#", 'host#', "subject#", "surname#"},
['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#",
"subject#-link", "authorlink#", "author#link"},
['AuthorList-Mask'] = {"author-mask#", "author#-mask", "subject-mask#", "subject#-mask"},
['ContributorList-First'] = {'contributor-first#', 'contributor#-first',
'contributor-given#', 'contributor#-given'},
['ContributorList-Last'] = {'contributor-last#', 'contributor#-last',
'contributor-surname#', 'contributor#-surname', 'contributor#'},
['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'},
['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'},
['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"},
['EditorList-Last'] = {"editor-last#", "editor#-last", "editor-surname#",
"editor#-surname", "editor#"},
['EditorList-Link'] = {"editor-link#", "editor#-link"},
['EditorList-Mask'] = {"editor-mask#", "editor#-mask"},
['InterviewerList-First'] = {'interviewer-first#', 'interviewer#-first',
'interviewer-given#', 'interviewer#-given'},
['InterviewerList-Last'] = {'interviewer-last#', 'interviewer#-last',
'interviewer-surname#', 'interviewer#-surname', 'interviewer#'},
['InterviewerList-Link'] = {'interviewer-link#', 'interviewer#-link'},
['InterviewerList-Mask'] = {'interviewer-mask#', 'interviewer#-mask'},
['TranslatorList-First'] = {'translator-first#', 'translator#-first',
'translator-given#', 'translator#-given'},
['TranslatorList-Last'] = {'translator-last#', 'translator#-last',
'translator-surname#', 'translator#-surname', 'translator#'},
['TranslatorList-Link'] = {'translator-link#', 'translator#-link'},
['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'},
}
--[[--------------------------< D E P E N D E N C I E S _ T >--------------------------------------------------
a table of url-holding parameters upon which other parameters are dependent.
this table is used by has_archive_today_url() to suppress parameters that are dependant upon a url-holding parameter
that has as a value an archive.today (or alternate tld) url.
archive.today is deprecated at en.wiki; see Wikipedia:Requests_for_comment/Archive.is_RFC_5
]]
local url_dependency_map_t = { -- table of url-holding parameters and the meta-parameters that are dependent on them
['url'] = {'AccessDate', 'ArchiveURL', 'Format', 'UrlAccess'},
['archive-url'] = {'ArchiveDate', 'ArchiveFormat', 'UrlStatus'},
['archiveurl'] = {'ArchiveDate', 'ArchiveFormat', 'UrlStatus'},
['article-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['chapter-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['conference-url'] = {'ConferenceFormat'},
['contribution-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['entry-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['map-url'] = {'MapFormat', 'MapUrlAccess'},
['section-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['transcript-url'] = {'TranscriptFormat'},
};
local dependencies_t = {}; -- the table of url-holding parameters and their dependent parameters
for url_param, meta_parameters_t in pairs (url_dependency_map_t) do -- sequence of meta-parameters (indexes) into <aliases> table
local dependant_params_t = {}; -- collection of parameters that are dependent on this <url_param>
for _, meta_parameter in ipairs (meta_parameters_t) do -- for each <aliases> meta-parameter (index)
if 'string' == type (aliases[meta_parameter]) then -- for single parameter names (no aliases), <aliases[meta_parameter]> will be a string
table.insert (dependant_params_t, aliases[meta_parameter]); -- add to this <url_param>'s dependency sequence
else
for _, alias in ipairs (aliases[meta_parameter]) do -- for each alias in aliases[meta_parameter] (aliases['AccessDate'] for example)
table.insert (dependant_params_t, alias); -- add to this <url_param>'s dependency sequence
end
end
end
dependencies_t[url_param] = dependant_params_t; -- add the <url_param> and its dependent parameters
end
--[[--------------------------< P U N C T _ S K I P >---------------------------
builds a table of parameter names that the extraneous terminal punctuation check should not check.
]]
local punct_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value
'BookTitle', 'Chapter', 'ScriptChapter', 'ScriptTitle', 'Title', 'TransChapter', 'Transcript', 'TransMap', 'TransTitle', -- title-holding parameters
'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators
'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous
'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'MapURL', 'TranscriptURL', 'URL', -- URL-holding parameters
}
local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value
'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID', 'MapURL', 'TranscriptURL', 'URL', -- parameters allowed to hold urls
'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls
}
local function build_skip_table (skip_t, meta_params)
for _, meta_param in ipairs (meta_params) do -- for each meta parameter key
local params = aliases[meta_param]; -- get the parameter or the table of parameters associated with the meta parameter name
if 'string' == type (params) then
skip_t[params] = 1; -- just a single parameter
else
for _, param in ipairs (params) do -- get the parameter name
skip_t[param] = 1; -- add the parameter name to the skip table
local count;
param, count = param:gsub ('#', ''); -- remove enumerator marker from enumerated parameters
if 0 ~= count then -- if removed
skip_t[param] = 1; -- add param name without enumerator marker
end
end
end
end
return skip_t;
end
local punct_skip = {};
local url_skip = {};
--[[--------------------------< U R L _ A C C E S S _ M A P >--------------------------------------------------
this table used by the wikipedia library url test, has_twl_url(), which automatically sets a url-access parameter
to 'subscription' when it discovers a wikipedia library url in any of the url-holding paramters used as keys in
this table.
translators: if your wiki uses parameter names for these url-holding parameters and their matching -access parameters,
add your wiki's parameters to this list. Leave the English parameters in place.
TODO: is there a better way to do this?
]]
local url_access_map_t = {
['chapter-url'] = 'chapter-url-access',
['contribution-url'] = 'contribution-url-access',
['entry-url'] = 'entry-url-access',
['article-url'] = 'article-url-access',
['section-url'] = 'section-url-access',
['map-url'] = 'map-url-access',
['mapurl'] = 'map-url-access',
['url'] = 'url-access',
['URL'] = 'url-access'
}
--[[--------------------------< S I N G L E - L E T T E R S E C O N D - L E V E L D O M A I N S >----------
this is a list of tlds that are known to have single-letter second-level domain names. This list does not include
ccTLDs which are accepted in is_domain_name().
]]
local single_letter_2nd_lvl_domains_t = {'cash', 'company', 'foundation', 'media', 'org', 'today'};
--[[-----------< S P E C I A L C A S E T R A N S L A T I O N S >------------
This table is primarily here to support internationalization. Translations in
this table are used, for example, when an error message, category name, etc.,
is extracted from the English alias key. There may be other cases where
this translation table may be useful.
]]
local is_Latn = 'A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191';
local special_case_translation = {
author = 'author',
editor = 'editor',
name_list_params = '$1-name-list parameters', -- $1 is 'author' or 'editor'; used with err_redundant_parameters
['AuthorList'] = 'authors list', -- used to assemble maintenance category names
['ContributorList'] = 'contributors list', -- translation of these names plus translation of the base maintenance category names in maint_cats{} table below
['EditorList'] = 'editors list', -- must match the names of the actual categories
['InterviewerList'] = 'interviewers list', -- this group or translations used by name_has_ed_markup() and name_has_mult_names()
['TranslatorList'] = 'translators list',
-- Lua patterns to match pseudo-titles used by InternetArchiveBot and others as placeholder for unknown |title= value
['archived_copy'] = { -- used with CS1 maint: Archive[d] copy as title
['en'] = '^archived?%s+copy$', -- for English; translators: keep this because templates imported from en.wiki
['local'] = nil, -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language
},
-- Lua patterns to match generic titles; usually created by bots or reference filling tools
-- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language
-- generic titles and patterns in this table should be lowercase only
-- leave ['local'] nil except when there is a matching generic title in your language
-- boolean 'true' for plain-text searches; 'false' for pattern searches
['generic_titles'] = {
['accept'] = {
},
['reject'] = {
{['en'] = {'^wayback%s+machine$', false}, ['local'] = nil},
{['en'] = {'are you a robot', true}, ['local'] = nil},
{['en'] = {'hugedomains', true}, ['local'] = nil},
{['en'] = {'^[%(%[{<]?no +title[>}%]%)]?$', false}, ['local'] = nil},
{['en'] = {'page not found', true}, ['local'] = nil},
{['en'] = {'subscribe to read', true}, ['local'] = nil},
{['en'] = {'^[%(%[{<]?unknown[>}%]%)]?$', false}, ['local'] = nil},
{['en'] = {'website is for sale', true}, ['local'] = nil},
{['en'] = {'^404', false}, ['local'] = nil},
{['en'] = {'error[ %-]404', false}, ['local'] = nil},
{['en'] = {'internet archive wayback machine', true}, ['local'] = nil},
{['en'] = {'log into facebook', true}, ['local'] = nil},
{['en'] = {'login • instagram', true}, ['local'] = nil},
{['en'] = {'redirecting...', true}, ['local'] = nil},
{['en'] = {'usurped title', true}, ['local'] = nil}, -- added by a GreenC bot
{['en'] = {'wayback machine', true}, ['local'] = nil},
{['en'] = {'webcite query result', true}, ['local'] = nil},
{['en'] = {'wikiwix\'s cache', true}, ['local'] = nil},
{['en'] = {'bot verification', true}, ['local'] = nil},
}
},
-- boolean 'true' for plain-text searches, search string must be lowercase only
-- boolean 'false' for pattern searches
-- leave ['local'] nil except when there is a matching generic name in your language
['generic_names'] = {
['accept'] = {
{['en'] = {'%[%[[^|]*%(author%) *|[^%]]*%]%]', false}, ['local'] = nil},
},
['reject'] = {
{['en'] = {'about us', true}, ['local'] = nil},
{['en'] = {'%f[%a][Aa]dvisor%f[%A]', false}, ['local'] = nil},
{['en'] = {'allmusic', true}, ['local'] = nil},
{['en'] = {'%f[%a][Aa]uthor%f[%A]', false}, ['local'] = nil},
{['en'] = {'^[Bb]ureau$', false}, ['local'] = nil},
{['en'] = {'business', true}, ['local'] = nil},
{['en'] = {'cnn', true}, ['local'] = nil},
{['en'] = {'collaborator', true}, ['local'] = nil},
{['en'] = {'^[Cc]ompany$', false}, ['local'] = nil},
{['en'] = {'contributor', true}, ['local'] = nil},
{['en'] = {'contact us', true}, ['local'] = nil},
{['en'] = {'correspondent', true}, ['local'] = nil},
{['en'] = {'^[Dd]esk$', false}, ['local'] = nil},
{['en'] = {'directory', true}, ['local'] = nil},
{['en'] = {'%f[%(%[][%(%[]%s*eds?%.?%s*[%)%]]?$', false}, ['local'] = nil},
{['en'] = {'[,%.%s]%f[e]eds?%.?$', false}, ['local'] = nil},
{['en'] = {'^eds?[%.,;]', false}, ['local'] = nil},
{['en'] = {'^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]dited%f[%A]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]ditors?%f[%A]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]mail%f[%A]', false}, ['local'] = nil},
{['en'] = {'facebook', true}, ['local'] = nil},
{['en'] = {'google', true}, ['local'] = nil},
{['en'] = {'^[Gg]roup$', false}, ['local'] = nil},
{['en'] = {'home page', true}, ['local'] = nil},
{['en'] = {'^[Ii]nc%.?$', false}, ['local'] = nil},
{['en'] = {'instagram', true}, ['local'] = nil},
{['en'] = {'interviewer', true}, ['local'] = nil},
{['en'] = {'^[Ll]imited$', false}, ['local'] = nil},
{['en'] = {'linkedIn', true}, ['local'] = nil},
{['en'] = {'^[Nn]ews$', false}, ['local'] = nil},
{['en'] = {'[Nn]ews[ %-]?[Rr]oom', false}, ['local'] = nil},
{['en'] = {'pinterest', true}, ['local'] = nil},
{['en'] = {'policy', true}, ['local'] = nil},
{['en'] = {'privacy', true}, ['local'] = nil},
{['en'] = {'reuters', true}, ['local'] = nil},
{['en'] = {'translator', true}, ['local'] = nil},
{['en'] = {'tumblr', true}, ['local'] = nil},
{['en'] = {'twitter', true}, ['local'] = nil},
{['en'] = {'site name', true}, ['local'] = nil},
{['en'] = {'statement', true}, ['local'] = nil},
{['en'] = {'submitted', true}, ['local'] = nil},
{['en'] = {'super.?user', false}, ['local'] = nil},
{['en'] = {'%f['..is_Latn..'][Uu]ser%f[^'..is_Latn..']', false}, ['local'] = nil},
{['en'] = {'updated', true}, ['local'] = nil},
{['en'] = {'verfasser', true}, ['local'] = nil},
}
}
}
--[[--------------------------< D A T E _ N A M E S >----------------------------------------------------------
This table of tables lists local language date names and fallback English date names.
The code in Date_validation will look first in the local table for valid date names.
If date names are not found in the local table, the code will look in the English table.
Because citations can be copied to the local wiki from en.wiki, the English is
required when the date-name translation function date_name_xlate() is used.
In these tables, season numbering is defined by
Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard
defines various divisions using numbers 21-41. CS1|2 only supports generic seasons.
EDTF does support the distinction between north and south hemisphere seasons
but CS1|2 has no way to make that distinction.
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
The standard does not address 'named' dates so, for the purposes of CS1|2,
Easter and Christmas are defined here as 98 and 99, which should be out of the
ISO 8601 (EDTF) range of uses for a while.
local_date_names_from_mediawiki is a boolean. When set to:
true – module will fetch local month names from MediaWiki for both date_names['local']['long'] and date_names['local']['short']; this will unconditionally overwrite manual translations
false – module will *not* fetch local month names from MediaWiki
Caveat lector: There is no guarantee that MediaWiki will provide short month names. At your wiki you can test
the results of the MediaWiki fetch in the debug console with this command (the result is alpha sorted):
=mw.dumpObject (p.date_names['local'])
While the module can fetch month names from MediaWiki, it cannot fetch the quarter, season, and named date names
from MediaWiki. Those must be translated manually.
]]
local local_date_names_from_mediawiki = true; -- when false, manual translation required for date_names['local']['long'] and date_names['local']['short']; overwrites manual translations
-- when true, module fetches long and short month names from MediaWiki
local date_names = {
['en'] = { -- English
['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12},
['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12},
['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36},
['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23},
['named'] = {['Easter'] = 98, ['Christmas'] = 99},
},
-- when local_date_names_from_mediawiki = false
['local'] = { -- replace these English date names with the local language equivalents
['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12},
['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12},
['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36},
['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23},
['named'] = {['Easter'] = 98, ['Christmas'] = 99},
},
['inv_local_long'] = {}, -- used in date reformatting & translation; copy of date_names['local'].long where k/v are inverted: [1]='<local name>' etc.
['inv_local_short'] = {}, -- used in date reformatting & translation; copy of date_names['local'].short where k/v are inverted: [1]='<local name>' etc.
['inv_local_quarter'] = {}, -- used in date translation; copy of date_names['local'].quarter where k/v are inverted: [1]='<local name>' etc.
['inv_local_season'] = {}, -- used in date translation; copy of date_names['local'].season where k/v are inverted: [1]='<local name>' etc.
['inv_local_named'] = {}, -- used in date translation; copy of date_names['local'].named where k/v are inverted: [1]='<local name>' etc.
['local_digits'] = {['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7', ['8'] = '8', ['9'] = '9'}, -- used to convert local language digits to Western 0-9
['xlate_digits'] = {},
}
if local_date_names_from_mediawiki then -- if fetching local month names from MediaWiki is enabled
local long_t = {};
local short_t = {};
for i=1, 12 do -- loop 12x and
local name = lang_obj:formatDate('F', '2022-' .. i .. '-1'); -- get long month name for each i
long_t[name] = i; -- save it
name = lang_obj:formatDate('M', '2022-' .. i .. '-1'); -- get short month name for each i
short_t[name] = i; -- save it
end
date_names['local']['long'] = long_t; -- write the long table – overwrites manual translation
date_names['local']['short'] = short_t; -- write the short table – overwrites manual translation
end
-- create inverted date-name tables for reformatting and/or translation
for _, invert_t in pairs {{'long', 'inv_local_long'}, {'short', 'inv_local_short'}, {'quarter', 'inv_local_quarter'}, {'season', 'inv_local_season'}, {'named', 'inv_local_named'}} do
for name, i in pairs (date_names['local'][invert_t[1]]) do -- this table is ['name'] = i
date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd
end
end
if local_digits_from_mediawiki then -- if fetching local digits from MediaWiki is enabled
local digits_t = {};
for i=0, 9 do -- loop 10x and
digits_t [lang_obj:formatNum (i)] = tostring (i); -- format the loop indexer as local lang table index and assign loop indexer (a string) as the value
end
date_names['local_digits'] = digits_t;
end
for ld, ed in pairs (date_names.local_digits) do -- make a digit translation table for simple date translation from en to local language using local_digits table
date_names.xlate_digits [ed] = ld; -- en digit becomes index with local digit as the value
end
local df_template_patterns = { -- table of redirects to {{Use dmy dates}} and {{Use mdy dates}}
'{{ *[Uu]se +(dmy) +dates *[|}]', -- 1159k -- sorted by approximate transclusion count
'{{ *[Uu]se +(mdy) +dates *[|}]', -- 212k
'{{ *[Uu]se +(MDY) +dates *[|}]', -- 788
'{{ *[Uu]se +(DMY) +dates *[|}]', -- 343
'{{ *([Mm]dy) *[|}]', -- 176
'{{ *[Uu]se *(dmy) *[|}]', -- 156 + 18
'{{ *[Uu]se *(mdy) *[|}]', -- 149 + 11
'{{ *([Dd]my) *[|}]', -- 56
'{{ *[Uu]se +(MDY) *[|}]', -- 5
'{{ *([Dd]MY) *[|}]', -- 3
'{{ *[Uu]se(mdy)dates *[|}]', -- 1
'{{ *[Uu]se +(DMY) *[|}]', -- 0
'{{ *([Mm]DY) *[|}]', -- 0
}
local title_object = mw.title.getCurrentTitle();
local content; -- done this way so that unused templates appear in unused-template-reports; self-transcluded makes them look like they are used
if 10 ~= title_object.namespace then -- all namespaces except Template
content = title_object:getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625
end
local function get_date_format ()
if not content then -- nil content when we're in template
return nil; -- auto-formatting does not work in Template space so don't set global_df
end
for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects
local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format
if match then
local use_dates_template = content:match ('%b{}', start); -- get the whole template
if use_dates_template:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length
return match:lower() .. '-' .. use_dates_template:match ('| *cs1%-dates *= *([lsy][sy]?)');
else
return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df=
end
end
end
end
--[[-----------------< V O L U M E , I S S U E , P A G E S >------------------
These tables hold cite class values (from the template invocation) and identify those templates that support
|volume=, |issue=, and |page(s)= parameters. Cite conference and cite map require further qualification which
is handled in the main module.
]]
local templates_using_volume = {'citation', 'audio-visual', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'}
local templates_using_issue = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news', 'podcast'}
local templates_not_using_page = {'audio-visual', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'}
--[[
These tables control when it is appropriate for {{citation}} to render |volume= and/or |issue=. The parameter
names in the tables constrain {{citation}} so that its renderings match the renderings of the equivalent cs1
templates. For example, {{cite web}} does not support |volume= so the equivalent {{citation |website=...}} must
not support |volume=.
]]
local citation_no_volume_t = { -- {{citation}} does not render |volume= when these parameters are used
'website', 'mailinglist', 'script-website',
}
local citation_issue_t = { -- {{citation}} may render |issue= when these parameters are used
'journal', 'magazine', 'newspaper', 'periodical', 'work',
'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work',
}
--[[
Patterns for finding extra text in |volume=, |issue=, |page=, |pages=
]]
local vol_iss_pg_patterns = {
good_ppattern = '^P[^%.PpGg]', -- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123); TODO: this allows 'Pages' which it should not
bad_ppatterns = { -- patterns for |page= and |pages=
'^[Pp][PpGg]?%.?[ %d]',
'^[Pp][Pp]?%. ', -- from {{p.}} and {{pp.}} templates
'^[Pp]ages?',
'^[Pp]gs.?',
},
vi_patterns_t = { -- combined to catch volume-like text in |issue= and issue-like text in |volume=
'^volumes?', -- volume-like text
'^vols?[%.:=]?',
'^issues?', --issue-like text
'^iss[%.:=]?',
'^numbers?',
'^nos?%A', -- don't match 'november' or 'nostradamus'
'^nr[%.:=]?',
'^n[%.:= ]', -- might be a valid issue without separator (space char is sep char here)
'^n°', -- 'n' with degree sign (U+00B0)
'^№', -- precomposed unicode numero character (U+2116)
},
}
--[[--------------------------< K E Y W O R D S >-------------------------------
These tables hold keywords for those parameters that have defined sets of acceptable keywords.
]]
--[[-------------------< K E Y W O R D S T A B L E >--------------------------
this is a list of keywords; each key in the list is associated with a table of
synonymous keywords possibly from different languages.
for I18N: add local-language keywords to value table; do not change the key.
For example, adding the German keyword 'ja':
['affirmative'] = {'yes', 'true', 'y', 'ja'},
Because CS1|2 templates from en.wiki articles are often copied to other local wikis,
it is recommended that the English keywords remain in these tables.
]]
local keywords = {
['amp'] = {'&', 'amp', 'ampersand'}, -- |name-list-style=
['and'] = {'and', 'serial'}, -- |name-list-style=
['affirmative'] = {'yes', 'true', 'y'}, -- |no-tracking=, |no-pp= -- Used by InternetArchiveBot
['afterword'] = {'afterword'}, -- |contribution=
['bot: unknown'] = {'bot: unknown'}, -- |url-status= -- Used by InternetArchiveBot
['cs1'] = {'cs1'}, -- |mode=
['cs2'] = {'cs2'}, -- |mode=
['dead'] = {'dead', 'deviated'}, -- |url-status= -- Used by InternetArchiveBot
['dmy'] = {'dmy'}, -- |df=
['dmy-all'] = {'dmy-all'}, -- |df=
etal = {'etal'}, -- |display-authors=, etc
['foreword'] = {'foreword'}, -- |contribution=
['free'] = {'free'}, -- |<id>-access= -- Used by InternetArchiveBot
['harv'] = {'harv'}, -- |ref=; this no longer supported; is_valid_parameter_value() called with <invert> = true
['introduction'] = {'introduction'}, -- |contribution=
['limited'] = {'limited'}, -- |url-access= -- Used by InternetArchiveBot
['live'] = {'live'}, -- |url-status= -- Used by InternetArchiveBot
['mdy'] = {'mdy'}, -- |df=
['mdy-all'] = {'mdy-all'}, -- |df=
['none'] = {'none'}, -- |postscript=, |ref=, |title=, |type= -- Used by InternetArchiveBot
['off'] = {'off'}, -- |title= (potentially also: |title-link=, |postscript=, |ref=, |type=)
['preface'] = {'preface'}, -- |contribution=
['registration'] = {'registration'}, -- |url-access= -- Used by InternetArchiveBot
['subscription'] = {'subscription'}, -- |url-access= -- Used by InternetArchiveBot
['unfit'] = {'unfit'}, -- |url-status= -- Used by InternetArchiveBot
['usurped'] = {'usurped'}, -- |url-status= -- Used by InternetArchiveBot
['vanc'] = {'vanc'}, -- |name-list-style=
['ymd'] = {'ymd'}, -- |df=
['ymd-all'] = {'ymd-all'}, -- |df=
-- ['yMd'] = {'yMd'}, -- |df=; not supported at en.wiki
-- ['yMd-all'] = {'yMd-all'}, -- |df=; not supported at en.wiki
}
--[[------------------------< X L A T E _ K E Y W O R D S >---------------------
this function builds a list, keywords_xlate{}, of the keywords found in keywords{} where the values from keywords{}
become the keys in keywords_xlate{} and the keys from keywords{} become the values in keywords_xlate{}:
['affirmative'] = {'yes', 'true', 'y'}, -- in keywords{}
becomes
['yes'] = 'affirmative', -- in keywords_xlate{}
['true'] = 'affirmative',
['y'] = 'affirmative',
the purpose of this function is to act as a translator between a non-English keyword and its English equivalent
that may be used in other modules of this suite
]]
local function xlate_keywords ()
local out_table = {}; -- output goes here
for k, keywords_t in pairs (keywords) do -- spin through the keywords table
for _, keyword in ipairs (keywords_t) do -- for each keyword
out_table[keyword] = k; -- create an entry in the output table where keyword is the key
end
end
return out_table;
end
local keywords_xlate = xlate_keywords (); -- the list of translated keywords
--[[----------------< M A K E _ K E Y W O R D S _ L I S T >---------------------
this function assembles, for parameter-value validation, the list of keywords appropriate to that parameter.
keywords_lists{}, is a table of tables from keywords{}
]]
local function make_keywords_list (keywords_lists)
local out_table = {}; -- output goes here
for _, keyword_list in ipairs (keywords_lists) do -- spin through keywords_lists{} and get a table of keywords
for _, keyword in ipairs (keyword_list) do -- spin through keyword_list{} and add each keyword, ...
table.insert (out_table, keyword); -- ... as plain text, to the output list
end
end
return out_table;
end
--[[----------------< K E Y W O R D S _ L I S T S >-----------------------------
this is a list of lists of valid keywords for the various parameters in [key].
Generally the keys in this table are the canonical en.wiki parameter names though
some are contrived because of use in multiple differently named parameters:
['yes_true_y'], ['id-access'].
The function make_keywords_list() extracts the individual keywords from the
appropriate list in keywords{}.
The lists in this table are used to validate the keyword assignment for the
parameters named in this table's keys.
]]
local keywords_lists = {
['yes_true_y'] = make_keywords_list ({keywords.affirmative}),
['contribution'] = make_keywords_list ({keywords.afterword, keywords.foreword, keywords.introduction, keywords.preface}),
['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all']}),
-- ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all'], keywords.yMd, keywords['yMd-all']}), -- not supported at en.wiki
['mode'] = make_keywords_list ({keywords.cs1, keywords.cs2}),
['name-list-style'] = make_keywords_list ({keywords.amp, keywords['and'], keywords.vanc}),
['ref'] = make_keywords_list ({keywords.harv}), -- inverted check; |ref=harv no longer supported
['url-access'] = make_keywords_list ({keywords.subscription, keywords.limited, keywords.registration}),
['url-status'] = make_keywords_list ({keywords.dead, keywords.live, keywords.unfit, keywords.usurped, keywords['bot: unknown']}),
['id-access'] = make_keywords_list ({keywords.free}),
}
--[[--------------------------< C S 1 _ C O N F I G _ G E T >--------------------------------------------------
fetch and validate values from {{cs1 config}} template to fill <global_cs1_config_t>
no error messages; when errors are detected, the parameter value from {{cs1 config}} is blanked.
Supports all parameters and aliases associated with the metaparameters: DisplayAuthors, DisplayContributors,
DisplayEditors, DisplayInterviewers, DisplayTranslators, NameListStyle, and Mode. The DisplayWhatever metaparameters
accept numeric values only (|display-authors=etal and the like is not supported).
]]
local global_cs1_config_t = {}; -- TODO: add value returned from get_date_format() to this table?
local function get_cs1_config ()
if not content then -- nil content when we're in template
return nil; -- auto-formatting does not work in Template space so don't set global_df
end
local start = content:find('{{ *[Cc][Ss]1 config *[|}]'); -- <start> is offset into <content> when {{cs1 config}} found; nil else
if start then
local cs1_config_template = content:match ('%b{}', start); -- get the whole template
if not cs1_config_template then
return nil;
end
local params_t = mw.text.split (cs1_config_template:gsub ('^{{%s*', ''):gsub ('%s*}}$', ''), '%s*|%s*'); -- remove '{{' and '}}'; make a sequence of parameter/value pairs (split on the pipe)
table.remove (params_t, 1); -- remove the template name because it isn't a parameter/value pair
local config_meta_params_t = {'DisplayAuthors', 'DisplayContributors', 'DisplayEditors', 'DisplayInterviewers', 'DisplayTranslators', 'NameListStyle', 'Mode'};
local meta_param_map_t = {}; -- list of accepted parameter names usable in {{cs1 config}} goes here
for _, meta_param in ipairs (config_meta_params_t) do -- for i18n using <config_meta_params_t>, map template parameter names to their metaparameter equivalents
if 'table' == type (aliases[meta_param]) then -- if <meta_param> is a sequence,
for _, param in ipairs (aliases[meta_param]) do -- extract its contents
meta_param_map_t[param] = meta_param; -- and add to <meta_param_map_t>
end
else
meta_param_map_t[aliases[meta_param]] = meta_param; -- not a sequence so just add the parameter to <meta_param_map_t>
end
end
local keywords_t = {}; -- map valid keywords to their associate metaparameter; reverse form of <keyword_lists[key] for these metaparameters
for _, metaparam_t in ipairs ({{'NameListStyle', 'name-list-style'}, {'Mode', 'mode'}}) do -- only these metaparameter / keywords_lists key pairs
for _, keyword in ipairs (keywords_lists[metaparam_t[2]]) do -- spin through the list of keywords
keywords_t[keyword] = metaparam_t[1]; -- add [keyword] = metaparameter to the map
end
end
for _, param in ipairs (params_t) do -- spin through the {{cs1 config}} parameters and fill <global_cs1_config_t>
local k, v = param:match ('([^=]-)%s*=%s*(.+)'); -- <k> is the parameter name; <v> is parameter's assigned value
if k then
if k:find ('^display') then -- if <k> is one of the |display-<namelist>= parameters
if v:match ('%d+') then -- the assigned value must be digits; doesn't accept 'etal'
global_cs1_config_t[meta_param_map_t[k]]=v; -- add the display param and its value to globals table
end
else
if keywords_t[v] == meta_param_map_t[k] then -- keywords_t[v] returns nil or the metaparam name; these must be the same
global_cs1_config_t[meta_param_map_t[k]]=v; -- add the parameter and its value to globals table
end
end
end
end
end
end
get_cs1_config (); -- fill <global_cs1_config_t>
--[[---------------------< S T R I P M A R K E R S >----------------------------
Common pattern definition location for stripmarkers so that we don't have to go
hunting for them if (when) MediaWiki changes their form.
]]
local stripmarkers = {
['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker
['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker()
}
--[[------------< I N V I S I B L E _ C H A R A C T E R S >---------------------
This table holds non-printing or invisible characters indexed either by name or
by Unicode group. Values are decimal representations of UTF-8 codes. The table
is organized as a table of tables because the Lua pairs keyword returns table
data in an arbitrary order. Here, we want to process the table from top to bottom
because the entries at the top of the table are also found in the ranges specified
by the entries at the bottom of the table.
Also here is a pattern that recognizes stripmarkers that begin and end with the
delete characters. The nowiki stripmarker is not an error but some others are
because the parameter values that include them become part of the template's
metadata before stripmarker replacement.
]]
local invisible_defs = {
del = '\127', -- used to distinguish between stripmarker and del char
zwj = '\226\128\141', -- used with capture because zwj may be allowed
}
local invisible_chars = {
{'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD
{'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed
{'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B
{'hair space', '\226\128\138'}, -- U+200A, E2 80 8A
{'soft hyphen', '\194\173'}, -- U+00AD, C2 AD
{'horizontal tab', '\009'}, -- U+0009 (HT), 09
{'line feed', '\010'}, -- U+000A (LF), 0A
{'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0
{'carriage return', '\013'}, -- U+000D (CR), 0D
{'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type
{'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker
{'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D))
{'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F
-- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF
-- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF
-- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD
-- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD
}
--[[
Indic script makes use of zero width joiner as a character modifier so zwj
characters must be left in. This pattern covers all of the unicode characters
for these languages:
Devanagari 0900–097F – https://unicode.org/charts/PDF/U0900.pdf
Devanagari extended A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf
Bengali 0980–09FF – https://unicode.org/charts/PDF/U0980.pdf
Gurmukhi 0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf
Gujarati 0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf
Oriya 0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf
Tamil 0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf
Telugu 0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf
Kannada 0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf
Malayalam 0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf
plus the not-necessarily Indic scripts for Sinhala and Burmese:
Sinhala 0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf
Myanmar 1000-109F - https://unicode.org/charts/PDF/U1000.pdf
Myanmar extended A AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf
Myanmar extended B A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf
the pattern is used by has_invisible_chars() and coins_cleanup()
]]
local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]';
-- list of emoji that use a zwj character (U+200D) to combine with another emoji
-- from: https://unicode.org/Public/emoji/17.0/emoji-zwj-sequences.txt; version: 17.0; 2025-01-08
-- table created by: [[:en:Module:Make emoji zwj table]]
local emoji_t = { -- indexes are decimal forms of the hex values in U+xxxx
[8596] = true, -- U+2194 ↔ left right arrow
[8597] = true, -- U+2195 ↕ up down arrow
[9760] = true, -- U+2620 ☠ skull and crossbones
[9792] = true, -- U+2640 ♀ female sign
[9794] = true, -- U+2642 ♂ male sign
[9877] = true, -- U+2695 ⚕ staff of aesculapius
[9878] = true, -- U+2696 ⚖ scales
[9895] = true, -- U+26A7 ⚧ male with stroke and male and female sign
[9992] = true, -- U+2708 ✈ airplane
[10052] = true, -- U+2744 ❄ snowflake
[10084] = true, -- U+2764 ❤ heavy black heart
[10145] = true, -- U+27A1 ➡ black rightwards arrow
[11035] = true, -- U+2B1B ⬛ black large square
[127752] = true, -- U+1F308 🌈 rainbow
[127787] = true, -- U+1F32B 🌫 fog
[127806] = true, -- U+1F33E 🌾 ear of rice
[127859] = true, -- U+1F373 🍳 cooking
[127868] = true, -- U+1F37C 🍼 baby bottle
[127876] = true, -- U+1F384 🎄 christmas tree
[127891] = true, -- U+1F393 🎓 graduation cap
[127908] = true, -- U+1F3A4 🎤 microphone
[127912] = true, -- U+1F3A8 🎨 artist palette
[127979] = true, -- U+1F3EB 🏫 school
[127981] = true, -- U+1F3ED 🏭 factory
[128048] = true, -- U+1F430 🐰 rabbit face
[128102] = true, -- U+1F466 👦 boy
[128103] = true, -- U+1F467 👧 girl
[128104] = true, -- U+1F468 👨 man
[128105] = true, -- U+1F469 👩 woman
[128139] = true, -- U+1F48B 💋 kiss mark
[128165] = true, -- U+1F4A5 💥 collision symbol
[128168] = true, -- U+1F4A8 💨 dash symbol
[128171] = true, -- U+1F4AB 💫 dizzy symbol
[128187] = true, -- U+1F4BB 💻 personal computer
[128188] = true, -- U+1F4BC 💼 brief case
[128293] = true, -- U+1F525 🔥 fire
[128295] = true, -- U+1F527 🔧 wrench
[128300] = true, -- U+1F52C 🔬 microscope
[128488] = true, -- U+1F5E8 🗨 left speech bubble
[128640] = true, -- U+1F680 🚀 rocket
[128658] = true, -- U+1F692 🚒 fire engine
[129001] = true, -- U+1F7E9 🟩 large green square
[129003] = true, -- U+1F7EB 🟫 large brown square
[129309] = true, -- U+1F91D 🤝 handshake
[129455] = true, -- U+1F9AF 🦯 probing cane
[129456] = true, -- U+1F9B0 🦰 emoji component red hair
[129457] = true, -- U+1F9B1 🦱 emoji component curly hair
[129458] = true, -- U+1F9B2 🦲 emoji component bald
[129459] = true, -- U+1F9B3 🦳 emoji component white hair
[129466] = true, -- U+1F9BA 🦺 safety vest
[129468] = true, -- U+1F9BC 🦼 motorized wheelchair
[129469] = true, -- U+1F9BD 🦽 manual wheelchair
[129489] = true, -- U+1F9D1 🧑 adult
[129490] = true, -- U+1F9D2 🧒 child
[129648] = true, -- U+1FA70 🩰 ballet shoes
[129657] = true, -- U+1FA79 🩹 adhesive bandage
[129775] = true, -- U+1FAEF fight cloud
[129778] = true, -- U+1FAF2 🫲 leftwards hand
}
--[[----------------------< L A N G U A G E S U P P O R T >-------------------
These tables and constants support various language-specific functionality.
]]
--local this_wiki_code = mw.getContentLanguage():getCode(); -- get this wiki's language code
local this_wiki_code = lang_obj:getCode(); -- get this wiki's language code
if string.match (mw.site.server, 'wikidata') then
this_wiki_code = mw.getCurrentFrame():callParserFunction('int', {'lang'}); -- on Wikidata so use interface language setting instead
end
local mw_languages_by_tag_t = mw.language.fetchLanguageNames (this_wiki_code, 'all'); -- get a table of language tag/name pairs known to Wikimedia; used for interwiki tests
local mw_languages_by_name_t = {};
for k, v in pairs (mw_languages_by_tag_t) do -- build a 'reversed' table name/tag language pairs know to MediaWiki; used for |language=
v = mw.ustring.lower (v); -- lowercase for tag fetch; get name's proper case from mw_languages_by_tag_t[<tag>]
if mw_languages_by_name_t[v] then -- when name already in the table
if 2 == #k or 3 == #k then -- if tag does not have subtags
mw_languages_by_name_t[v] = k; -- prefer the shortest tag for this name
end
else -- here when name not in the table
mw_languages_by_name_t[v] = k; -- so add name and matching tag
end
end
local inter_wiki_map = {}; -- map of interwiki prefixes that are language-code prefixes
for k, v in pairs (mw.site.interwikiMap ('local')) do -- spin through the base interwiki map (limited to local)
if mw_languages_by_tag_t[v["prefix"]] then -- if the prefix matches a known language tag
inter_wiki_map[v["prefix"]] = true; -- add it to our local map
end
end
--[[--------------------< S C R I P T _ L A N G _ C O D E S >-------------------
This table is used to hold ISO 639-1 two-character and ISO 639-3 three-character
language codes that apply only to |script-title= and |script-chapter=
]]
local script_lang_codes = {
'ab', 'am', 'ar', 'as', 'az', 'be', 'bg', 'bn', 'bo', 'bs', 'ce', 'chr',
'cu', 'dv', 'dz', 'el', 'fa', 'grc', 'gu', 'he', 'hi', 'hy', 'ja', 'ka',
'kaa', 'kk', 'km', 'kn', 'ko', 'ku', 'ky', 'lo', 'mk', 'ml', 'mn', 'mni',
'mr', 'my', 'ne', 'or', 'ota', 'pa', 'ps', 'ru', 'sd', 'si', 'sr', 'syc',
'ta', 'te', 'tg', 'th', 'ti', 'tkr', 'tt', 'ug', 'uk', 'ur', 'uz', 'yi',
'yue', 'zh', 'zgh'
};
--[[---------------< L A N G U A G E R E M A P P I N G >----------------------
These tables hold language information that is different (correct) from MediaWiki's definitions
For each ['<tag>'] = 'language name' in lang_code_remap{} there must be a matching ['language name'] = {'language name', '<tag>'} in lang_name_remap{}
lang_tag_remap{}:
key is always lowercase ISO 639-1, -2, -3 language tag or a valid lowercase IETF language tag
value is properly spelled and capitalized language name associated with <tag>
only one language name per <tag>;
key/value pair must have matching entry in lang_name_remap{}
lang_name_remap{}:
key is always lowercase language name
value is a table the holds correctly spelled and capitalized language name [1] and associated tag [2] (tag must match a tag key in lang_tag_remap{})
may have multiple keys referring to a common preferred name and tag; For example:
['kolsch'] and ['kölsch'] both refer to 'Kölsch' and 'ksh'
]]
local lang_tag_remap = { -- used for |language= and |script-title= / |script-chapter=
['als'] = 'Tosk Albanian', -- MediaWiki returns Alemannisch
['bh'] = 'Bihari', -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org
['bla'] = 'Blackfoot', -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name
['bn'] = 'Bengali', -- MediaWiki returns Bangla
['ca-valencia'] = 'Valencian', -- IETF variant of Catalan
['fkv'] = 'Kven', -- MediaWiki returns Kvensk
['gsw'] = 'Swiss German',
['ilo'] = 'Ilocano', -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name
['ksh'] = 'Kölsch', -- MediaWiki: Colognian; use IANA/ISO 639 preferred name
['ksh-x-colog'] = 'Colognian', -- override MediaWiki ksh; no IANA/ISO 639 code for Colognian; IETF private code created at Module:Lang/data
['mis-x-ripuar'] = 'Ripuarian', -- override MediaWiki ksh; no IANA/ISO 639 code for Ripuarian; IETF private code created at Module:Lang/data
['nan-tw'] = 'Taiwanese Hokkien', -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese and support en.wiki preferred name
['sr-ec'] = 'Serbian (Cyrillic script)', -- MediaWiki returns српски (ћирилица)
['sr-el'] = 'Serbian (Latin script)', -- MediaWiki returns srpski (latinica)
}
local lang_name_remap = { -- used for |language=; names require proper capitalization; tags must be lowercase
['alemannic'] = {'Swiss German', 'gsw'}, -- ISO 639-2, -3 alternate for Swiss German; MediaWiki mediawiki returns Alemannic for gsw; en.wiki preferred name
['alemannisch'] = {'Swiss German', 'gsw'}, -- not an ISO or IANA language name; MediaWiki uses 'als' as a subdomain name for Alemannic Wikipedia: als.wikipedia.org
['bangla'] = {'Bengali', 'bn'}, -- MediaWiki returns Bangla (the endonym) but we want Bengali (the exonym); here we remap
['bengali'] = {'Bengali', 'bn'}, -- MediaWiki doesn't use exonym so here we provide correct language name and 639-1 code
['bhojpuri'] = {'Bhojpuri', 'bho'}, -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org
['bihari'] = {'Bihari', 'bh'}, -- MediaWiki replaces 'Bihari' with 'Bhojpuri' so 'Bihari' cannot be found
['blackfoot'] = {'Blackfoot', 'bla'}, -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name
['colognian'] = {'Colognian', 'ksh-x-colog'}, -- MediaWiki preferred name for ksh
['ilocano'] = {'Ilocano', 'ilo'}, -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name
['kolsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name (use non-diacritical o instead of umlaut ö)
['kölsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name
['kven'] = {'Kven', 'fkv'}, -- Unicode CLDR have decided not to support English language name for these two...
['kvensk'] = {'Kven', 'fkv'}, -- ...they say to refer to IANA registry for English names
['ripuarian'] = {'Ripuarian', 'mis-x-ripuar'}, -- group of dialects; no code in MediaWiki or in IANA/ISO 639
['serbian (cyrillic script)'] = {'Serbian (Cyrillic script)', 'sr-cyrl'}, -- special case to get correct tag when |language=sr-ec
['serbian (latin script)'] = {'Serbian (Latin script)', 'sr-latn'}, -- special case to get correct tag when |language=sr-el
['swiss german'] = {'Swiss German', 'gsw'},
['taiwanese hokkien'] = {'Taiwanese Hokkien', 'nan-tw'}, -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese
['tosk albanian'] = {'Tosk Albanian', 'als'}, -- MediaWiki replaces 'Tosk Albanian' with 'Alemannisch' so 'Tosk Albanian' cannot be found
['valencian'] = {'Valencian', 'ca-valencia'}, -- variant of Catalan; categorizes as Valencian
}
--[[---------------< P R O P E R T I E S _ C A T E G O R I E S >----------------
Properties categories. These are used for investigating qualities of citations.
]]
local prop_cats = {
['foreign-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is foreign-language name, $2 is ISO639-1 code
['foreign-lang-source-2'] = 'CS1 foreign language sources (ISO 639-2)|$1', -- |language= category; a cat for ISO639-2 languages; $1 is the ISO 639-2 code used as a sort key
['interproj-linked-name'] = 'CS1 interproject-linked names|$1', -- any author, editor, etc that has an interproject link; $1 is interproject tag used as a sort key
['interwiki-linked-name'] = 'CS1 interwiki-linked names|$1', -- any author, editor, etc that has an interwiki link; $1 is interwiki tag used as a sort key; yeilds to interproject
['local-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is local-language name, $2 is ISO639-1 code; not emitted when local_lang_cat_enable is false
['location-test'] = 'CS1 location test',
['long-vol'] = 'CS1: long volume value', -- probably temporary cat to identify scope of |volume= values longer than 4 characters
['script'] = 'CS1 uses $1-language script ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is language tag
['tracked-param'] = 'CS1 tracked parameter: $1', -- $1 is base (enumerators removed) parameter name
['unfit'] = 'CS1: unfit URL', -- |url-status=unfit or |url-status=usurped; used to be a maint cat
['vanc-accept'] = 'CS1:Vancouver names with accept markup', -- for |vauthors=/|veditors= with accept-as-written markup
['year-range-abbreviated'] = 'CS1: abbreviated year range', -- probably temporary cat to identify scope of |date=, |year= values using YYYY–YY form
}
--[[-------------------< T I T L E _ T Y P E S >--------------------------------
Here we map a template's CitationClass to TitleType (default values for |type= parameter)
]]
local title_types = {
['AV-media-notes'] = 'Media notes',
['document'] = 'Document',
['interview'] = 'Interview',
['mailinglist'] = 'Mailing list',
['map'] = 'Map',
['podcast'] = 'Podcast',
['pressrelease'] = 'Press release',
['report'] = 'Report',
['speech'] = 'Speech',
['techreport'] = 'Technical report',
['thesis'] = 'Thesis',
}
--[[--------------------------< B U I L D _ K N O W N _ F R E E _ D O I _ R E G I S T R A N T S _ T A B L E >--
build a table of doi registrants known to be free-to-read In a doi, the registrant ID is the series of digits
between the '10.' and the first '/': in doi 10.1100/sommat, 1100 is the registrant ID
see §3.2.2 DOI prefix of the Doi Handbook p. 43
https://www.doi.org/doi-handbook/DOI_Handbook_Final.pdf#page=43
]]
local function build_free_doi_registrants_table()
local registrants_t = {};
for _, v in ipairs ({
'1045', '1074', '1096', '1100', '1155', '1186', '1194', '1371', '1613', '1629', '1989', '1999', '2147', '2196', '3114', '3285',
'3389', '3390', '3767', '3906', '3748', '3814', '3847', '3897', '4061', '4089', '4103', '4172', '4175', '4230', '4236', '4239',
'4240', '4249', '4251', '4252', '4253', '4254', '4291', '4292', '4312', '4329', '4330', '4331', '5074', '5086', '5194',
'5210', '5306', '5312', '5313', '5314', '5315', '5316', '5317', '5318', '5319', '5320', '5321', '5334', '5402', '5409',
'5410', '5411', '5412', '5492', '5493', '5494', '5495', '5496', '5497', '5498', '5499', '5500', '5501', '5527', '5528',
'5662', '6064', '6219', '7167', '7217', '7287', '7482', '7490', '7554', '7717', '7759', '7766', '9778',
'11131', '11569', '11647', '11648', '12688', '12703', '12715', '12942', '12998', '13105', '14256', '14293', '14303', '14502', '14720',
'15215', '15227', '15292', '15458', '15347', '15412', '15560', '16995', '17573', '17645', '18553', '18637', '18757', '19080', '19173', '20419',
'20944', '21037', '21105', '21468', '21767', '21425', '22261', '22323', '22459', '24105', '24196', '24404', '24413', '24966', '26529',
'26614', '26775', '26873', '30845', '32545', '34291', '34641', '35711', '35712', '35713', '35995', '36648', '37126', '37532', '37871',
'47128', '47622', '47959', '48438', '51741', '51746', '51935', '51936', '51937', '51938', '51939', '51940', '52165', '52437', '52975',
'53288', '53347', '54081', '54947', '55295', '55667', '55741', '55914', '57009', '58647', '58782', '59081', '59490', '61375', '66183', '70587',
}) do
registrants_t[v] = true; -- build a k/v table of known free-to-read doi registrants
end
return registrants_t;
end
-- known free registrants identifiable by the doi suffix incipit
local extended_registrants_t = { -- doi suffix incipits are evaluated as lua patterns
['1001'] = {'jamanetworkopen'}, -- JAMA Network Open
['1002'] = {'1878-0261', '2056-4538', '2211-5463', '2475-8876', '2688-8319', 'aaai%.', 'aac2%.', 'ache%.', 'acm2%.', 'acn3%.', 'acr2%.', 'admi%.', 'adpr%.', 'adrr%.', 'adsr%.', 'advs%.', 'ael2%.', 'aelm%.', 'aesr%.', 'aff2%.', 'agf2%.', 'agg2%.', 'agm2%.', 'ags3%.', 'agt2%.', 'aidi%.', 'ail2%.', 'aisy%.', 'aiv2%.', 'alz%.', 'ame2%.', 'ams2%.', 'anbr%.', 'ansa%.', 'apj%.', 'app5%.', 'aps3%.', 'apxr%.', 'aro2%.', 'ars2%.', 'asl2%.', 'atn2%.', 'bco2%.', 'bes2%.', 'bmm2%.', 'bod2%.', 'brb3%.', 'brh2%.', 'brx2%.', 'bsa3%.', 'bte2%.', 'btm2%.', 'cai2%.', 'cam4%.', 'cbh2%.', 'ccr3%.', 'ccs3%.', 'cdt3%.', 'celc%.', 'cep4%.', 'ces2%.', 'cesm%.', 'ceur%.', 'cey2%.', 'cfch%.', 'cfp2%.', 'cin4%.', 'clc%.', 'clem%.', 'cli2%.', 'clt2%.', 'cmt2%.', 'cmtd%.', 'cnl2%.', 'cnr2%.', 'cns%.', 'cns3%.', 'cnx2%.', 'cre2%.', 'csc3%.', 'cso2%.', 'ctd2%.', 'cti2%.', 'ctm2%.', 'dad2%.', 'deo2%.', 'dep2%.', 'dni2%.', 'dro2%.', 'dug2%.', 'dvr2%.', 'eas2%.', 'ece2%.', 'ece3%.', 'ecog%.', 'ecs2%.', 'edm2%.', 'edn3%.', 'eem2%.', 'eer3%.', 'efd2%.', 'ejsc%.', 'elsa%.', 'elt2%.', 'eng2%.', 'eom2%.', 'epi4%.', 'epr2%.', 'ese3%.', 'exp%.', 'fbe2%.', 'fci2%.', 'fer3%.', 'fes3%.', 'fft2%.', 'fhu2%.', 'fle2%.', 'flm2%.', 'fob2%.', 'fpf2%.', 'fsh3%.', 'fsn3%.', 'gcb4%.', 'gch2%.', 'gdj3%.', 'geo2%.', 'ggn2%.', 'gin2%.', 'glr2%.', 'gps3%.', 'gtm2%.', 'hbm%.', 'hcs2%.', 'hem3%.', 'hkj2%.', 'hsr2%.', 'ibra%.', 'idm2%.', 'ifm2%.', 'iid3%.', 'iju5%.', 'ila2%.', 'imed%.', 'imm3%.', 'imo2%.', 'imt2%.', 'inc2%.', 'inc3%.', 'inf2%.', 'inm3%.', 'inmd%.', 'ird3%.', 'ise3%.', 'jaa2%.', 'jav%.', 'jbt%.', 'jcc5%.', 'jcla%.', 'jcsm%.', 'jcv2%.', 'jeo2%.', 'jev2%.', 'jex2%.', 'jfa2%.', 'jgf2%.', 'jgh3%.', 'jha2%.', 'jia2%.', 'jmd2%.', 'jmrs%.', 'joa3%.', 'jpr3%.', 'jsf2%.', 'jsp2%.', 'jvc2%.', 'kjm2%.', 'kot2%.', 'lci2%.', 'ldr%.', 'leap%.', 'leg3%.', 'lim2%.', 'lio2%.', 'loe2%.', 'lol2%.', 'lrh2%.', 'mame%.', 'mba2%.', 'mbo3%.', 'mco2%.', 'mdb2%.', 'mdr2%.', 'med4%.', 'mef2%.', 'met%.', 'metm%.', 'mgea%.', 'mgg3%.', 'mhs2%.', 'mlf2%.', 'mmr3%.', 'moda%.', 'mog2%.', 'mpr%.', 'mps2%.', 'msd2%.', 'nam2%.', 'nano%.', 'nap2%.', 'neo2%.', 'nep3%.', 'njb%.', 'nop2%.', 'npp2%.', 'npr2%.', 'ntls%.', 'open%.', 'orm2%.', 'osp4%.', 'oto2%.', 'pan3%.', 'pchj%.', 'pcn5%.', 'pdi3%.', 'ped4%.', 'pei3%.', 'pfm2%.', 'pgr2%.', 'phmt%.', 'pld3%.', 'pls2%.', 'pmf2%.', 'pne2%.', 'pnp%.', 'poh2%.', 'ppj2%.', 'ppp3%.', 'prm2%.', 'pro6%.', 'prp2%.', 'psp4%.', 'puh2%.', 'pul2%.', 'qub2%.', 'rai2%.', 'rar2%.', 'rco2%.', 'rcr2%.', 'rfc2%.', 'rmb2%.', 'rpm2%.', 'rse2%.', 'rvr2%.', 'sae2%.', 'sen2%.', 'sfp2%.', 'smb2%.', 'smm2%.', 'smmd%.', 'smo2%.', 'smsc%.', 'sst2%.', 'sst3%.', 'sstr%.', 'sus2%.', 'tch2%.', 'tcr4%.', 'tpg2%.', 'trc2%.', 'tre%.', 'uar2%.', 'ueg2%.', 'uro2%.', 'viw2%.', 'vms3%.', 'vro2%.', 'vzj2%.', 'we%.', 'wjo2%.', 'wlb3%.', 'wll2%.', 'wsb%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1016'] = {'j%.aace', 'j%.aed', 'j%.aiopen', 'j%.animal', 'j%.apsb', 'j%.addicn', -- AACE Endocrinology and Diabetes, AACE Endocrinology and Diabetes, AI Open, Animal, Acta Pharmaceutica Sinica B, Addiction Neuroscience
'j%.abrep', 'j%.fob', 'j%.gpb', 'j%.heliyon', 'j%.mucimm%.', 'j%.nlp', 'j%.patter', 'j%.proche', -- Addictive Behaviors Reports, FEBS Open Bio, Genomics, Proteomics & Bioinformatics after 2015, Heliyon, Mucosal Immunology, Natural Language Processing, Patterns, Procedia Chemistry
'j%.vgie', 'S1672-0229', 'S1933-0219'}, -- VideoGIE, Genomics, Proteomics & Bioinformatics before 2015, Mucosal Immunology
['1017'] = {'apj%.', 'nlp', 'mdh', 'S15574660'}, -- Natural Language Processing Journal, Medical History, Asia Pacific Journal
['1021'] = {'acscentsci', 'acsomega'}, -- ACS Central Science, ACS Omega
['1029'] = {'2025cn', '2025csj', '2025ea', '2025gc', '2025gh', '2025ms', '2025sw', '2025wr', '2026ef', '2026gl', '2026jh', 'aga2.70129'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1038'] = {'41541%.', '43246%.', 'asiamat%.', 'boneres%.', 'cddis%.', 'cddiscovery%.', 'celldisc%.', 'mi%.', 'nutd%.', 'oncsis%.', 's40494', 's41377', 's41392', 's41396', 's41398', 's41405', 's41407', 's41408', 's41439', 's41467', 's41514', 's41522', 's41523', 's41524', 's41525', 's41526', 's41528', 's41529', 's41531', 's41533', 's41534', 's41535', 's41536', 's41537', 's41538', 's41539', 's41540', 's41545', 's41598', 's41612', 's41698', 's41699', 's41746', 's42003', 's42004', 's42005', 's42949', 's43247', 's43705', 's43856', 's44168', 's44172', 's44182', 's44183', 's44184', 's44185', 's44259', 's44260', 's44264', 's44271', 's44276', 's44294', 's44296', 's44298', 's44303', 's44304', 's44306', 's44310', 's44323', 's44324', 's44325', 's44328', 's44333', 's44334', 's44335', 's44341', 's44355', 's44383', 's44384', 's44385', 's44386', 's44387', 's44400', 's44401', 's44406', 's44407', 's44431', 's44432', 's44433', 's44434', 's44435', 's44440', 's44453', 's44454', 's44455', 's44456', 's44458', 's44459', 's44482', 's44484', 's44485', 's44488', 's44513', 's44528', 'sdata%.'}, -- Nature journals (npj series, Communications series, and many others, see https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&diff=prev&oldid=1368822567 and https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&diff=next&oldid=1368822567)
['1046'] = {'j%.1365-8711', 'j%.1365-246x'}, -- MNRAS, GJI
['1049'] = {'aie2%.', 'blc2%.', 'bme2', 'bsb2%.', 'ccs2%.', 'cds2', 'cdt2', 'cim2%.', 'cit2%.', 'cmu2%.', 'cps2%.', 'csy2%.', 'cth2%.', 'cvi2%.', 'dgt2%.', 'ein2%.', 'ell2%.', 'elp2%.', 'els2', 'ema3%.', 'enb2%.', 'enc2%.', 'esi2%.', 'gtd2%.', 'htl2%.', 'hve2%.', 'ipr2%.', 'ise2', 'itr2%.', 'mia2%.', 'mna2%.', 'nbt2', 'nde2%.', 'ntw2%.', 'ote2%.', 'pel2%.', 'qtc2%.', 'rpg2%.', 'rsn2%.', 'ses2%.', 'sfw2', 'sil2', 'smc2%.', 'smt2%.', 'stg2%.', 'syb2%.', 'tje2%.', 'wss2%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1051'] = {'parasite'}, -- Parasite
['1057'] = {'s41599'}, -- Humanities and Social Sciences Communications
['1093'] = {'mnras', 'mnrasl', 'gji', 'pnasnexus', 'rasti', 'ismeco', 'ismejo'}, -- MNRAS, MNRAS Letters, GJI, PNAS Nexus, RASTI, ISME Communications, ISME Journal
['1096'] = {'fba%.'}, -- FASEB BioAdvances
['1098'] = {'rsbm', 'rsob', 'rsos'}, -- Biographical Memoirs of Fellows of the Royal Society, Open Biology, Royal Society Open Science
['1099'] = {'acmi', 'mic', '00221287', 'mgen'}, -- Access Microbiology, Microbiology, Journal of General Microbiology, Microbial Genomics
['1107'] = {'S20569890', 'S20522525', 'S16005775', 'S24143146'}, -- Acta Crystallographica E, IUCrJ, Journal of Synchrotron Radiation, IUCrData
['1109'] = {'access', 'oa', 'oj'}, -- IEEE Access, IEEE Open Access..., IEEE Open Journal...
['1111'] = {'1365-2435', '1442-1984', '1751-7915', '1753-0407', '1755-0998', '1758-2229', '1759-7714', '2041-210x', 'j%.1365-2966', 'j%.1745-3933', 'j%.1365-246X','acel%.', 'adb%.', 'anec%.', 'aogs%.', 'bor%.', 'bpa%.', 'cas%.', 'con4%.', 'cpr%.', 'crj%.', 'csp2%.', 'cts%.', 'ddi%.', 'ejed%.', 'ene%.', 'eva%.', 'gbb%.', 'gcbb%.', 'hex%.', 'irv%.', 'iwj%.', 'jch%.', 'jcmm%.', 'jdi%.', 'jfr3%.', 'jocd%.', 'jwas%.', 'mcn%.', 'mpp%.', 'myc%.', 'nrm%.', 'os%.', 'pbi%.', 'srt%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1112'] = {'tlm3%.'}, -- Transactions of the London Mathematical Society
['1113'] = {'ep'}, -- Experimental Physiology
['1128'] = {'asmcr', 'jmbe', 'mbio', 'mra', 'spectrum', 'msphere', 'msystems'}, --ASM Case Reports, Journal of Microbiology & Biology Education, mBio, Microbiology Resource Announcements, Microbiology Spectrum, mSphere, mSystems
['1136'] = {'bmjopen'}, -- BMJ Open
['1140'] = {'epjconf'}, -- EPJ Web of Conferences
['1161'] = {'jaha%.'},
['1176'] = {'appi%.prcp%.'},
['1192'] = {'bjo'}, -- BJPsych Open
['1210'] = {'jendso','jcemcr'}, -- Journal of the Endocrine Society, JCEM Case Reports
['1215'] = {'21573689', '21573698'}, -- L&O Fluids
['1257'] = {'jep'}, -- Journal of Economic Perspectives
['1590'] = {'0102-3306'}, -- Acta Botanica Brasilica
['2903'] = {'j%.efsa%.'},
['3322'] = {'caac%.'},
['3982'] = {'qw', 'te'},
['4171'] = {'dm','mag'}, -- Documenta Mathematica, EMS Magazine
['4319'] = {'lo%.', 'lol%.', 'lom%.'}, -- L&O, L&O e-Lectures, L&O Methods
['5852'] = {'ejt'}, -- European Journal of Taxonomy
['7155'] = {'jgaa'}, -- Journal of Graph Algorithms and Applications
['7758'] = {'rsf'}, -- RSJ Journal
['11158'] = {'saasp'}, -- Systematic and Applied Acarology Special Publications
['11646'] = {'megataxa', 'mesozoic'}, -- Megataxa, Mesozoic
['14231'] = {'ag'}, -- Algebraic Geometry
['14814'] = {'phy2%.'},
['15302'] = {'vr%.'},
['15446'] = {'abc'}, -- Acta Biológica Colombiana
['17239'] = {'jowr'}, -- Journal of Writing Research
['22073'] = {'pja'}, -- Persian Journal of Acarology
['24310'] = {'abm'}, -- Acta Botanica Malacitana
['24425'] = {'agp'}, -- Acta Geologica Polonica
['35249'] = {'rche'}, -- Revista Chilena de Entomología
['37520'] = {'fi'}, -- Fossil Imprint
['53562'] = {'ajcb'} -- Asian Journal of Conservation Biology
}
--[[===================<< E R R O R M E S S A G I N G >>======================
]]
--[[----------< E R R O R M E S S A G E S U P P L E M E N T S >-------------
I18N for those messages that are supplemented with additional specific text that
describes the reason for the error
TODO: merge this with special_case_translations{}?
]]
local err_msg_supl = {
['char'] = 'invalid character', -- |isbn=, |sbn=
['check'] = 'checksum', -- |isbn=, |sbn=
empty_str = '(empty string)', -- empty unknown parameter check when cite has |=
['flag'] = 'flag', -- |archive-url=
['form'] = 'invalid form', -- |isbn=, |sbn=
['group'] = 'invalid group id', -- |isbn=
['initials'] = 'initials', -- Vancouver
['invalid language code'] = 'invalid language code', -- |script-<param>=
['journal'] = 'journal', -- |bibcode=
['length'] = 'length', -- |isbn=, |bibcode=, |sbn=
['liveweb'] = 'liveweb', -- |archive-url=
['missing comma'] = 'missing comma', -- Vancouver
['missing prefix'] = 'missing prefix', -- |script-<param>=
['missing title part'] = 'missing title part', -- |script-<param>=
['name'] = 'name', -- Vancouver
['non-Latin char'] = 'non-Latin character', -- Vancouver
['path'] = 'path', -- |archive-url=
['prefix'] = 'invalid prefix', -- |isbn=
['punctuation'] = 'punctuation', -- Vancouver
['save'] = 'save command', -- |archive-url=
['suffix'] = 'suffix', -- Vancouver
['timestamp'] = 'timestamp', -- |archive-url=
['unknown language code'] = 'unknown language code', -- |script-<param>=
['value'] = 'value', -- |bibcode=
['year'] = 'year', -- |bibcode=
}
--[[--------------< E R R O R _ C O N D I T I O N S >---------------------------
Error condition table. This table has two sections: errors at the top, maintenance
at the bottom. Maint 'messaging' does not have a 'message' (message=nil)
The following contains a list of IDs for various error conditions defined in the
code. For each ID, we specify a text message to display, an error category to
include, and whether the error message should be wrapped as a hidden comment.
Anchor changes require identical changes to matching anchor in Help:CS1 errors
TODO: rename error_conditions{} to something more generic; create separate error
and maint tables inside that?
]]
local error_conditions = {
err_accessdate_missing_url = {
message = '<code class="cs1-code">|access-date=</code> requires <code class="cs1-code">|url=</code>',
anchor = 'accessdate_missing_url',
category = 'CS1 errors: access-date without URL',
hidden = false
},
err_apostrophe_markup = {
message = 'Italic or bold markup not allowed in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'apostrophe_markup',
category = 'CS1 errors: markup',
hidden = false
},
err_archive_date_missing_url = {
message = '<code class="cs1-code">|archive-date=</code> requires <code class="cs1-code">|archive-url=</code>',
anchor = 'archive_date_missing_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_date_url_ts_mismatch = {
message = '<code class="cs1-code">|archive-date=</code> / <code class="cs1-code">|archive-url=</code> timestamp mismatch; $1 suggested',
anchor = 'archive_date_url_ts_mismatch',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_missing_date = {
message = '<code class="cs1-code">|archive-url=</code> requires <code class="cs1-code">|archive-date=</code>',
anchor = 'archive_missing_date',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_missing_url = {
message = '<code class="cs1-code">|archive-url=</code> requires <code class="cs1-code">|url=</code>',
anchor = 'archive_missing_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_url = {
message = '<code class="cs1-code">|archive-url=</code> is malformed: $1', -- $1 is error message detail
anchor = 'archive_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_arxiv_missing = {
message = '<code class="cs1-code">|arxiv=</code> required',
anchor = 'arxiv_missing',
category = 'CS1 errors: arXiv', -- same as bad arxiv
hidden = false
},
err_asintld_missing_asin = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|asin=</code>', -- $1 is parameter name
anchor = 'asintld_missing_asin',
category = 'CS1 errors: ASIN TLD',
hidden = false
},
err_bad_arxiv = {
message = 'Check <code class="cs1-code">|arxiv=</code> value',
anchor = 'bad_arxiv',
category = 'CS1 errors: arXiv',
hidden = false
},
err_bad_asin = {
message = 'Check <code class="cs1-code">|asin=</code> value',
anchor = 'bad_asin',
category ='CS1 errors: ASIN',
hidden = false
},
err_bad_asin_tld = {
message = 'Check <code class="cs1-code">|asin-tld=</code> value',
anchor = 'bad_asin_tld',
category ='CS1 errors: ASIN TLD',
hidden = false
},
err_bad_bibcode = {
message = 'Check <code class="cs1-code">|bibcode=</code> $1', -- $1 is error message detail
anchor = 'bad_bibcode',
category = 'CS1 errors: bibcode',
hidden = false
},
err_bad_biorxiv = {
message = 'Check <code class="cs1-code">|biorxiv=</code> value',
anchor = 'bad_biorxiv',
category = 'CS1 errors: bioRxiv',
hidden = false
},
err_bad_citeseerx = {
message = 'Check <code class="cs1-code">|citeseerx=</code> value',
anchor = 'bad_citeseerx',
category = 'CS1 errors: citeseerx',
hidden = false
},
err_bad_date = {
message = 'Check date values in: $1', -- $1 is a parameter name list
anchor = 'bad_date',
category = 'CS1 errors: dates',
hidden = false
},
err_bad_doi = {
message = 'Check <code class="cs1-code">|doi=</code> value',
anchor = 'bad_doi',
category = 'CS1 errors: DOI',
hidden = false
},
err_bad_hdl = {
message = 'Check <code class="cs1-code">|hdl=</code> value',
anchor = 'bad_hdl',
category = 'CS1 errors: HDL',
hidden = false
},
err_bad_isbn = {
message = 'Check <code class="cs1-code">|isbn=</code> value: $1', -- $1 is error message detail
anchor = 'bad_isbn',
category = 'CS1 errors: ISBN',
hidden = false
},
err_bad_ismn = {
message = 'Check <code class="cs1-code">|ismn=</code> value',
anchor = 'bad_ismn',
category = 'CS1 errors: ISMN',
hidden = false
},
err_bad_issn = {
message = 'Check <code class="cs1-code">|$1issn=</code> value', -- $1 is 'e' or '' for eissn or issn
anchor = 'bad_issn',
category = 'CS1 errors: ISSN',
hidden = false
},
err_bad_jfm = {
message = 'Check <code class="cs1-code">|jfm=</code> value',
anchor = 'bad_jfm',
category = 'CS1 errors: JFM',
hidden = false
},
err_bad_jstor = {
message = 'Check <code class="cs1-code">|jstor=</code> value',
anchor = 'bad_jstor',
category = 'CS1 errors: JSTOR',
hidden = false
},
err_bad_lccn = {
message = 'Check <code class="cs1-code">|lccn=</code> value',
anchor = 'bad_lccn',
category = 'CS1 errors: LCCN',
hidden = false
},
err_bad_medrxiv = {
message = 'Check <code class="cs1-code">|medrxiv=</code> value',
anchor = 'bad_medrxiv',
category = 'CS1 errors: medRxiv',
hidden = false
},
err_bad_mr = {
message = 'Check <code class="cs1-code">|mr=</code> value',
anchor = 'bad_mr',
category = 'CS1 errors: MR',
hidden = false
},
err_bad_oclc = {
message = 'Check <code class="cs1-code">|oclc=</code> value',
anchor = 'bad_oclc',
category = 'CS1 errors: OCLC',
hidden = false
},
err_bad_ol = {
message = 'Check <code class="cs1-code">|ol=</code> value',
anchor = 'bad_ol',
category = 'CS1 errors: OL',
hidden = false
},
err_bad_osti = {
message = 'Check <code class="cs1-code">|osti=</code> value',
anchor = 'bad_osti',
category = 'CS1 errors: OSTI',
hidden = false
},
err_bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link=
message = 'Check <code class="cs1-code">|$1=</code> value', -- $1 is parameter name
anchor = 'bad_paramlink',
category = 'CS1 errors: parameter link',
hidden = false
},
err_bad_pmc = {
message = 'Check <code class="cs1-code">|pmc=</code> value',
anchor = 'bad_pmc',
category = 'CS1 errors: PMC',
hidden = false
},
err_bad_pmid = {
message = 'Check <code class="cs1-code">|pmid=</code> value',
anchor = 'bad_pmid',
category = 'CS1 errors: PMID',
hidden = false
},
err_bad_rfc = {
message = 'Check <code class="cs1-code">|rfc=</code> value',
anchor = 'bad_rfc',
category = 'CS1 errors: RFC',
hidden = false
},
err_bad_s2cid = {
message = 'Check <code class="cs1-code">|s2cid=</code> value',
anchor = 'bad_s2cid',
category = 'CS1 errors: S2CID',
hidden = false
},
err_bad_sbn = {
message = 'Check <code class="cs1-code">|sbn=</code> value: $1', -- $1 is error message detail
anchor = 'bad_sbn',
category = 'CS1 errors: SBN',
hidden = false
},
err_bad_ssrn = {
message = 'Check <code class="cs1-code">|ssrn=</code> value',
anchor = 'bad_ssrn',
category = 'CS1 errors: SSRN',
hidden = false
},
err_bad_url = {
message = 'Check $1 value', -- $1 is parameter name
anchor = 'bad_url',
category = 'CS1 errors: URL',
hidden = false
},
err_bad_usenet_id = {
message = 'Check <code class="cs1-code">|message-id=</code> value',
anchor = 'bad_message_id',
category = 'CS1 errors: message-id',
hidden = false
},
err_bad_zbl = {
message = 'Check <code class="cs1-code">|zbl=</code> value',
anchor = 'bad_zbl',
category = 'CS1 errors: Zbl',
hidden = false
},
err_bare_url_missing_title = {
message = '$1 missing title', -- $1 is parameter name
anchor = 'bare_url_missing_title',
category = 'CS1 errors: bare URL',
hidden = false
},
err_biorxiv_missing = {
message = '<code class="cs1-code">|biorxiv=</code> required',
anchor = 'biorxiv_missing',
category = 'CS1 errors: bioRxiv', -- same as bad bioRxiv
hidden = false
},
err_chapter_ignored = {
message = '<code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'chapter_ignored',
category = 'CS1 errors: chapter ignored',
hidden = false
},
err_citation_missing_title = {
message = 'Missing or empty <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'citation_missing_title',
category = 'CS1 errors: missing title',
hidden = false
},
err_citeseerx_missing = {
message = '<code class="cs1-code">|citeseerx=</code> required',
anchor = 'citeseerx_missing',
category = 'CS1 errors: citeseerx', -- same as bad citeseerx
hidden = false
},
err_cite_web_url = { -- this error applies to cite web and to cite podcast
message = 'Missing or empty <code class="cs1-code">|url=</code>',
anchor = 'cite_web_url',
category = 'CS1 errors: requires URL',
hidden = false
},
err_class_ignored = {
message = '<code class="cs1-code">|class=</code> ignored',
anchor = 'class_ignored',
category = 'CS1 errors: class',
hidden = false
},
err_contributor_ignored = {
message = '<code class="cs1-code">|contributor=</code> ignored',
anchor = 'contributor_ignored',
category = 'CS1 errors: contributor',
hidden = false
},
err_contributor_missing_required_param = {
message = '<code class="cs1-code">|contributor=</code> requires <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'contributor_missing_required_param',
category = 'CS1 errors: contributor',
hidden = false
},
err_deprecated_params = {
message = 'Cite uses deprecated parameter <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'deprecated_params',
category = 'CS1 errors: deprecated parameters',
hidden = false
},
err_disp_name = {
message = 'Invalid <code class="cs1-code">|$1=$2</code>', -- $1 is parameter name; $2 is the assigned value
anchor = 'disp_name',
category = 'CS1 errors: display-names',
hidden = false,
},
err_doibroken_missing_doi = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|doi=</code>', -- $1 is parameter name
anchor = 'doibroken_missing_doi',
category = 'CS1 errors: DOI',
hidden = false
},
err_embargo_missing_pmc = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|pmc=</code>', -- $1 is parameter name
anchor = 'embargo_missing_pmc',
category = 'CS1 errors: PMC embargo',
hidden = false
},
err_empty_citation = {
message = 'Empty citation',
anchor = 'empty_citation',
category = 'CS1 errors: empty citation',
hidden = false
},
err_etal = {
message = 'Explicit use of et al. in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'explicit_et_al',
category = 'CS1 errors: explicit use of et al.',
hidden = false
},
err_extra_text_edition = {
message = '<code class="cs1-code">|edition=</code> has extra text',
anchor = 'extra_text_edition',
category = 'CS1 errors: extra text: edition',
hidden = false,
},
err_extra_text_issue = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_issue',
category = 'CS1 errors: extra text: issue',
hidden = false,
},
err_extra_text_pages = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_pages',
category = 'CS1 errors: extra text: pages',
hidden = false,
},
err_extra_text_volume = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_volume',
category = 'CS1 errors: extra text: volume',
hidden = false,
},
err_first_missing_last = {
message = '<code class="cs1-code">|$1=</code> missing <code class="cs1-code">|$2=</code>', -- $1 is first alias, $2 is matching last alias
anchor = 'first_missing_last',
category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator
hidden = false
},
err_format_missing_url = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|$2=</code>', -- $1 is format parameter $2 is url parameter
anchor = 'format_missing_url',
category = 'CS1 errors: format without URL',
hidden = false
},
err_generic_name = {
message = '<code class="cs1-code">|$1=</code> has generic name', -- $1 is parameter name
anchor = 'generic_name',
category = 'CS1 errors: generic name',
hidden = false,
},
err_generic_title = {
message = 'Cite uses generic title',
anchor = 'generic_title',
category = 'CS1 errors: generic title',
hidden = false,
},
err_invalid_isbn_date = {
message = 'ISBN / Date incompatibility',
anchor = 'invalid_isbn_date',
category = 'CS1 errors: ISBN date',
hidden = true
},
err_invalid_param_val = {
message = 'Invalid <code class="cs1-code">|$1=$2</code>', -- $1 is parameter name $2 is parameter value
anchor = 'invalid_param_val',
category = 'CS1 errors: invalid parameter value',
hidden = false
},
err_invisible_char = {
message = '$1 in $2 at position $3', -- $1 is invisible char $2 is parameter name $3 is position number
anchor = 'invisible_char',
category = 'CS1 errors: invisible characters',
hidden = false
},
err_medrxiv_missing = {
message = '<code class="cs1-code">|medrxiv=</code> required',
anchor = 'medrxiv_missing',
category = 'CS1 errors: medRxiv', -- same as bad medRxiv
hidden = false
},
err_missing_name = {
message = 'Missing <code class="cs1-code">|$1$2=</code>', -- $1 is modified NameList; $2 is enumerator
anchor = 'missing_name',
category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator
hidden = false
},
err_missing_periodical = {
message = 'Cite $1 requires <code class="cs1-code">|$2=</code>', -- $1 is cs1 template name; $2 is canonical periodical parameter name for cite $1
anchor = 'missing_periodical',
category = 'CS1 errors: missing periodical',
hidden = false
},
err_missing_pipe = {
message = 'Missing pipe in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'missing_pipe',
category = 'CS1 errors: missing pipe',
hidden = false
},
err_missing_publisher = {
message = 'Cite $1 requires <code class="cs1-code">|$2=</code>', -- $1 is cs1 template name; $2 is canonical publisher parameter name for cite $1
anchor = 'missing_publisher',
category = 'CS1 errors: missing publisher',
hidden = false
},
err_numeric_names = {
message = '<code class="cs1-code">|$1=</code> has numeric name', -- $1 is parameter name',
anchor = 'numeric_names',
category = 'CS1 errors: numeric name',
hidden = false,
},
err_param_access_requires_param = {
message = '<code class="cs1-code">|$1-access=</code> requires <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'param_access_requires_param',
category = 'CS1 errors: param-access',
hidden = false
},
err_param_has_ext_link = {
message = 'External link in <code class="cs1-code">$1</code>', -- $1 is parameter name
anchor = 'param_has_ext_link',
category = 'CS1 errors: external links',
hidden = false
},
err_param_has_twl_url = {
message = 'Wikipedia Library link in <code class="cs1-code">$1</code>', -- $1 is parameter name
anchor = 'param_has_twl_url',
category = 'CS1 errors: URL',
hidden = false
},
err_parameter_ignored = {
message = 'Unknown parameter <code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'parameter_ignored',
category = 'CS1 errors: unsupported parameter',
hidden = false
},
err_parameter_ignored_suggest = {
message = 'Unknown parameter <code class="cs1-code">|$1=</code> ignored (<code class="cs1-code">|$2=</code> suggested)', -- $1 is unknown parameter $2 is suggested parameter name
anchor = 'parameter_ignored_suggest',
category = 'CS1 errors: unsupported parameter',
hidden = false
},
err_periodical_ignored = {
message = '<code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'periodical_ignored',
category = 'CS1 errors: periodical ignored',
hidden = false
},
err_redundant_parameters = {
message = 'More than one of $1 specified', -- $1 is error message detail
anchor = 'redundant_parameters',
category = 'CS1 errors: redundant parameter',
hidden = false
},
err_script_parameter = {
message = 'Invalid <code class="cs1-code">|$1=</code>: $2', -- $1 is parameter name $2 is script language code or error detail
anchor = 'script_parameter',
category = 'CS1 errors: script parameters',
hidden = false
},
err_ssrn_missing = {
message = '<code class="cs1-code">|ssrn=</code> required',
anchor = 'ssrn_missing',
category = 'CS1 errors: SSRN',
hidden = false
},
err_text_ignored = {
message = 'Text "$1" ignored', -- $1 is ignored text
anchor = 'text_ignored',
category = 'CS1 errors: unrecognized parameter',
hidden = false
},
err_trans_missing_title = {
message = '<code class="cs1-code">|trans-$1=</code> requires <code class="cs1-code">|$1=</code> or <code class="cs1-code">|script-$1=</code>', -- $1 is base parameter name
anchor = 'trans_missing_title',
category = 'CS1 errors: translated title',
hidden = false
},
err_param_unknown_empty = {
message = 'Cite has empty unknown parameter$1: $2', -- $1 is 's' or empty space; $2 is emty unknown param list
anchor = 'param_unknown_empty',
category = 'CS1 errors: empty unknown parameters',
hidden = false
},
err_vancouver = {
message = 'Vancouver style error: $1 in name $2', -- $1 is error detail, $2 is the nth name
anchor = 'vancouver',
category = 'CS1 errors: Vancouver style',
hidden = false
},
err_wikilink_in_url = {
message = 'URL–wikilink conflict', -- uses ndash
anchor = 'wikilink_in_url',
category = 'CS1 errors: URL–wikilink conflict', -- uses ndash
hidden = false
},
--[[--------------------------< M A I N T >-------------------------------------
maint messages do not have a message (message = nil); otherwise the structure
is the same as error messages
]]
maint_archive_origin = {
message = nil,
anchor = 'archive_origin',
category = 'CS1 maint: archive origin',
hidden = true,
},
maint_archived_copy = {
message = nil,
anchor = 'archived_copy',
category = 'CS1 maint: archived copy as title',
hidden = true,
},
maint_bibcode = {
message = nil,
anchor = 'bibcode',
category = 'CS1 maint: bibcode',
hidden = true,
},
maint_location_no_publisher = { -- cite book, conference, encyclopedia; citation as book cite or encyclopedia cite
message = nil,
anchor = 'location_no_publisher',
category = 'CS1 maint: location missing publisher',
hidden = true,
},
maint_bot_unknown = {
message = nil,
anchor = 'bot:_unknown',
category = 'CS1 maint: bot: original URL status unknown',
hidden = true,
},
maint_date_auto_xlated = { -- date auto-translation not supported by en.wiki
message = nil,
anchor = 'date_auto_xlated',
category = 'CS1 maint: date auto-translated',
hidden = true,
},
maint_date_format = {
message = nil,
anchor = 'date_format',
category = 'CS1 maint: date format',
hidden = true,
},
maint_date_year = {
message = nil,
anchor = 'date_year',
category = 'CS1 maint: date and year',
hidden = true,
},
maint_deprecated_archive = {
message = nil,
anchor = 'deprecated_archive',
category = 'CS1 maint: deprecated archival service',
hidden = true,
},
maint_doi_ignore = {
message = nil,
anchor = 'doi_ignore',
category = 'CS1 maint: ignored DOI errors',
hidden = true,
},
maint_doi_inactive = {
message = nil,
anchor = 'doi_inactive',
category = 'CS1 maint: DOI inactive',
hidden = true,
},
maint_doi_inactive_dated = {
message = nil,
anchor = 'doi_inactive_dated',
category = 'CS1 maint: DOI inactive as of $2$3$1', -- $1 is year, $2 is month-name or empty string, $3 is space or empty string
hidden = true,
},
maint_doi_unflagged_free = {
message = nil,
anchor = 'doi_unflagged_free',
category = 'CS1 maint: unflagged free DOI',
hidden = true,
},
maint_extra_punct = {
message = nil,
anchor = 'extra_punct',
category = 'CS1 maint: extra punctuation',
hidden = true,
},
maint_id_limit_load_fail = { -- applies to all cs1|2 templates on a page;
message = nil, -- maint message (category link) never emitted
anchor = 'id_limit_load_fail',
category = 'CS1 maint: ID limit load fail',
hidden = true,
},
maint_isbn_ignore = {
message = nil,
anchor = 'ignore_isbn_err',
category = 'CS1 maint: ignored ISBN errors',
hidden = true,
},
maint_issn_ignore = {
message = nil,
anchor = 'ignore_issn',
category = 'CS1 maint: ignored ISSN errors',
hidden = true,
},
maint_jfm_format = {
message = nil,
anchor = 'jfm_format',
category = 'CS1 maint: JFM format',
hidden = true,
},
maint_location = {
message = nil,
anchor = 'location',
category = 'CS1 maint: location',
hidden = true,
},
maint_misc_url = {
message = nil,
anchor = 'misc_url',
category = 'CS1 maint: miscellaneous url',
hidden = true,
},
maint_missing_class = {
message = nil,
anchor = 'missing_class',
category = 'CS1 maint: missing class',
hidden = true,
},
maint_mr_format = {
message = nil,
anchor = 'mr_format',
category = 'CS1 maint: MR format',
hidden = true,
},
maint_mult_names = {
message = nil,
anchor = 'mult_names',
category = 'CS1 maint: multiple names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table
hidden = true,
},
maint_numeric_names = {
message = nil,
anchor = 'numeric_names',
category = 'CS1 maint: numeric names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table
hidden = true,
},
maint_others = {
message = nil,
anchor = 'others',
category = 'CS1 maint: others',
hidden = true,
},
maint_others_avm = {
message = nil,
anchor = 'others_avm',
category = 'CS1 maint: others in cite AV media (notes)',
hidden = true,
},
maint_overridden_setting = {
message = nil,
anchor = 'overridden',
category = 'CS1 maint: overridden setting',
hidden = true,
},
maint_page_art_num = {
message = nil,
anchor = 'page_art_num',
category = 'CS1 maint: article number as page number',
hidden = true,
},
maint_periodical_has_isbn = {
message = nil,
anchor = 'periodical_has_isbn',
category = 'CS1 maint: periodical has ISBN',
hidden = true,
},
maint_pmc_embargo = {
message = nil,
anchor = 'embargo',
category = 'CS1 maint: PMC embargo expired',
hidden = true,
},
maint_pmc_format = {
message = nil,
anchor = 'pmc_format',
category = 'CS1 maint: PMC format',
hidden = true,
},
maint_postscript = {
message = nil,
anchor = 'postscript',
category = 'CS1 maint: postscript',
hidden = true,
},
maint_publisher_location = {
message = nil,
anchor = 'publisher_location',
category = 'CS1 maint: publisher location',
hidden = true,
},
maint_ref_duplicates_default = {
message = nil,
anchor = 'ref_default',
category = 'CS1 maint: ref duplicates default',
hidden = true,
},
maint_shortened_archive_url = {
message = nil,
anchor = 'shortened_archive_url',
category = 'CS1 maint: shortened archive url',
hidden = true,
},
maint_unknown_lang = {
message = nil,
anchor = 'unknown_lang',
category = 'CS1 maint: unrecognized language',
hidden = true,
},
maint_untitled = {
message = nil,
anchor = 'untitled',
category = 'CS1 maint: untitled periodical',
hidden = true,
},
maint_url_status = {
message = nil,
anchor = 'url_status',
category = 'CS1 maint: url-status',
hidden = true,
},
maint_work_isbn = {
message = nil,
anchor = 'work_isbn',
category = 'CS1 maint: work parameter with ISBN',
hidden = true,
},
maint_year= {
message = nil,
anchor = 'year',
category = 'CS1 maint: year',
hidden = true,
},
maint_zbl = {
message = nil,
anchor = 'zbl',
category = 'CS1 maint: Zbl',
hidden = true,
},
}
--[[--------------------------< I D _ L I M I T S _ D A T A _ T >----------------------------------------------
fetch id limits for certain identifiers from c:Data:CS1/Identifier limits.tab. This source is a json tabular
data file maintained at wikipedia commons. Convert the json format to a table of k/v pairs.
The values from <id_limits_data_t> are used to set handle.id_limit.
From 2025-02-21, MediaWiki is broken. Use this link to edit the tablular data file:
https://commons.wikimedia.org/w/index.php?title=Data:CS1/Identifier_limits.tab&action=edit
See Phab:T389105
]]
local id_limits_data_t;
local id_limits_data_load_fail = false; -- flag; assume that we will be successful when loading json id limit tabular data
local use_commons_data = true; -- set to false if your wiki does not have access to mediawiki commons; then,
if false == use_commons_data then -- update this table from https://commons.wikimedia.org/wiki/Data:CS1/Identifier_limits.tab; last update: 2026-08-02
id_limits_data_t = {['OCLC'] = 11160000000, ['OSTI'] = 23010000, ['PMC'] = 13500000, ['PMID'] = 42900000, ['RFC'] = 9300, ['SSRN'] = 7500000, ['S2CID'] = 290000000}; -- this table must be maintained locally
else -- here for wikis that do have access to mediawiki commons
local load_fail_limit = 99999999999; -- very high number to avoid error messages on load failure
id_limits_data_t = {['OCLC'] = load_fail_limit, ['OSTI'] = load_fail_limit, ['PMC'] = load_fail_limit, ['PMID'] = load_fail_limit, ['RFC'] = load_fail_limit, ['SSRN'] = load_fail_limit, ['S2CID'] = load_fail_limit};
if mw.ext.data == nil then
id_limits_data_load_fail = true; -- safeguard against Lua errors if mw.ext.data is not available for some reason
else
local tab_data_t = mw.ext.data.get ('CS1/Identifier limits.tab'); -- attempt to load the tabular data from commons into <tab_data_t>
if false == tab_data_t then -- undocumented 'feature': mw.ext.data.get() sometimes returns false
id_limits_data_load_fail = true; -- set the flag so that Module:Citation/CS1 can create an unannotated maint category
else
for _, limit_t in ipairs (tab_data_t.data) do -- overwrite default <load_fail_limit> values from the data table in the tabular data
id_limits_data_t[limit_t[1]] = limit_t[2]; -- <limit[1]> is identifier; <limit[2]> is upper limit for that identifier
end
end
end
end
--[[--------------------------< I D _ H A N D L E R S >--------------------------------------------------------
The following contains a list of values for various defined identifiers. For each
identifier we specify a variety of information necessary to properly render the
identifier in the citation.
parameters: a list of parameter aliases for this identifier; first in the list is the canonical form
link: Wikipedia article name
redirect: a local redirect to a local Wikipedia article name; at en.wiki, 'ISBN (identifier)' is a redirect to 'International Standard Book Number'
q: Wikidata q number for the identifier
label: the label preceding the identifier; label is linked to a Wikipedia article (in this order):
redirect from id_handlers['<id>'].redirect when use_identifier_redirects is true
Wikidata-supplied article name for the local wiki from id_handlers['<id>'].q
local article name from id_handlers['<id>'].link
prefix: the first part of a URL that will be concatenated with a second part which usually contains the identifier
suffix: optional third part to be added after the identifier
encode: true if URI should be percent-encoded; otherwise false
COinS: identifier link or keyword for use in COinS:
for identifiers registered at info-uri.info use: info:.... where '...' is the appropriate identifier label
for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn
for |asin= and |ol=, which require assembly, use the keyword: url
for others make a URL using the value in prefix/suffix and #label, use the keyword: pre (not checked; any text other than 'info', 'rft', or 'url' works here)
set to nil to leave the identifier out of the COinS
separator: character or text between label and the identifier in the rendered citation
id_limit: for those identifiers with established limits, this property holds the upper limit
access: use this parameter to set the access level for all instances of this identifier.
the value must be a valid access level for an identifier (see ['id-access'] in this file).
custom_access: to enable custom access level for an identifier, set this parameter
to the parameter that should control it (normally 'id-access')
]]
local id_handlers = {
['ARXIV'] = {
parameters = {'arxiv', 'eprint'},
link = 'arXiv',
redirect = 'arXiv (identifier)',
q = 'Q118398',
label = 'arXiv',
prefix = 'https://arxiv.org/abs/',
encode = false,
COinS = 'info:arxiv',
separator = ':',
access = 'free', -- free to read
},
['ASIN'] = {
parameters = { 'asin', 'ASIN' },
link = 'Amazon Standard Identification Number',
redirect = 'ASIN (identifier)',
q = 'Q1753278',
label = 'ASIN',
prefix = 'https://www.amazon.',
COinS = 'url',
separator = ' ',
encode = false;
},
['BIBCODE'] = {
parameters = {'bibcode'},
link = 'Bibcode',
redirect = 'Bibcode (identifier)',
q = 'Q25754',
label = 'Bibcode',
prefix = 'https://ui.adsabs.harvard.edu/abs/',
encode = false,
COinS = 'info:bibcode',
separator = ':',
custom_access = 'bibcode-access',
},
['BIORXIV'] = {
parameters = {'biorxiv'},
link = 'bioRxiv',
redirect = 'bioRxiv (identifier)',
q = 'Q19835482',
label = 'bioRxiv',
prefix = 'https://doi.org/',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['CITESEERX'] = {
parameters = {'citeseerx'},
link = 'CiteSeerX',
redirect = 'CiteSeerX (identifier)',
q = 'Q2715061',
label = 'CiteSeerX',
prefix = 'https://citeseerx.ist.psu.edu/viewdoc/summary?doi=',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['DOI'] = { -- Used by InternetArchiveBot
parameters = { 'doi', 'DOI'},
link = 'Digital object identifier',
redirect = 'doi (identifier)',
q = 'Q25670',
label = 'doi',
prefix = 'https://doi.org/',
COinS = 'info:doi',
separator = ':',
encode = true,
custom_access = 'doi-access',
},
['EISSN'] = {
parameters = {'eissn', 'EISSN'},
link = 'International Standard Serial Number#Electronic ISSN',
redirect = 'eISSN (identifier)',
q = 'Q46339674',
label = 'eISSN',
prefix = 'https://search.worldcat.org/issn/',
COinS = 'rft.eissn',
encode = false,
separator = ' ',
},
['HDL'] = {
parameters = { 'hdl', 'HDL' },
link = 'Handle System',
redirect = 'hdl (identifier)',
q = 'Q3126718',
label = 'hdl',
prefix = 'https://hdl.handle.net/',
COinS = 'info:hdl',
separator = ':',
encode = true,
custom_access = 'hdl-access',
},
['ISBN'] = { -- Used by InternetArchiveBot
parameters = {'isbn', 'ISBN'},
link = 'International Standard Book Number',
redirect = 'ISBN (identifier)',
q = 'Q33057',
label = 'ISBN',
prefix = 'Special:BookSources/',
COinS = 'rft.isbn',
separator = ' ',
},
['ISMN'] = {
parameters = {'ismn', 'ISMN'},
link = 'International Standard Music Number',
redirect = 'ISMN (identifier)',
q = 'Q1666938',
label = 'ISMN',
prefix = '', -- not currently used;
COinS = nil, -- nil because we can't use pre or rft or info:
separator = ' ',
},
['ISSN'] = {
parameters = {'issn', 'ISSN'},
link = 'International Standard Serial Number',
redirect = 'ISSN (identifier)',
q = 'Q131276',
label = 'ISSN',
prefix = 'https://search.worldcat.org/issn/',
COinS = 'rft.issn',
encode = false,
separator = ' ',
},
['JFM'] = {
parameters = {'jfm', 'JFM'},
link = 'Jahrbuch über die Fortschritte der Mathematik',
redirect = 'JFM (identifier)',
q = '',
label = 'JFM',
prefix = 'https://zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['JSTOR'] = {
parameters = {'jstor', 'JSTOR'},
link = 'JSTOR',
redirect = 'JSTOR (identifier)',
q = 'Q1420342',
label = 'JSTOR',
prefix = 'https://www.jstor.org/stable/',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
custom_access = 'jstor-access',
},
['LCCN'] = {
parameters = {'lccn', 'LCCN'},
link = 'Library of Congress Control Number',
redirect = 'LCCN (identifier)',
q = 'Q620946',
label = 'LCCN',
prefix = 'https://lccn.loc.gov/',
COinS = 'info:lccn',
encode = false,
separator = ' ',
},
['MEDRXIV'] = {
parameters = {'medrxiv'},
link = 'medRxiv',
redirect = 'medRxiv (identifier)',
q = 'Q58465838',
label = 'medRxiv',
prefix = 'https://www.medrxiv.org/content/',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = false,
separator = ' ',
},
['MR'] = {
parameters = {'mr', 'MR'},
link = 'Mathematical Reviews',
redirect = 'MR (identifier)',
q = 'Q211172',
label = 'MR',
prefix = 'https://mathscinet.ams.org/mathscinet-getitem?mr=',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['OCLC'] = {
parameters = {'oclc', 'OCLC'},
link = 'OCLC',
redirect = 'OCLC (identifier)',
q = 'Q190593',
label = 'OCLC',
prefix = 'https://search.worldcat.org/oclc/',
COinS = 'info:oclcnum',
encode = true,
separator = ' ',
id_limit = id_limits_data_t.OCLC or 0,
},
['OL'] = {
parameters = { 'ol', 'OL' },
link = 'Open Library',
redirect = 'OL (identifier)',
q = 'Q1201876',
label = 'OL',
prefix = 'https://openlibrary.org/',
COinS = 'url',
separator = ' ',
encode = true,
custom_access = 'ol-access',
},
['OSTI'] = {
parameters = {'osti', 'OSTI'},
link = 'Office of Scientific and Technical Information',
redirect = 'OSTI (identifier)',
q = 'Q2015776',
label = 'OSTI',
prefix = 'https://www.osti.gov/biblio/',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.OSTI or 0,
custom_access = 'osti-access',
},
['PMC'] = {
parameters = {'pmc', 'PMC'},
link = 'PubMed Central',
redirect = 'PMC (identifier)',
q = 'Q229883',
label = 'PMC',
prefix = 'https://www.ncbi.nlm.nih.gov/pmc/articles/PMC',
suffix = '',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.PMC or 0,
access = 'free', -- free to read
},
['PMID'] = {
parameters = {'pmid', 'PMID'},
link = 'PubMed Identifier',
redirect = 'PMID (identifier)',
q = 'Q2082879',
label = 'PMID',
prefix = 'https://pubmed.ncbi.nlm.nih.gov/',
COinS = 'info:pmid',
encode = false,
separator = ' ',
id_limit = id_limits_data_t.PMID or 0,
},
['RFC'] = {
parameters = {'rfc', 'RFC'},
link = 'Request for Comments',
redirect = 'RFC (identifier)',
q = 'Q212971',
label = 'RFC',
prefix = 'https://tools.ietf.org/html/rfc',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
id_limit = id_limits_data_t.RFC or 0,
access = 'free', -- free to read
},
['SBN'] = {
parameters = {'sbn', 'SBN'},
link = 'Standard Book Number', -- redirect to International_Standard_Book_Number#History
redirect = 'SBN (identifier)',
label = 'SBN',
prefix = 'Special:BookSources/0-', -- prefix has leading zero necessary to make 9-digit sbn a 10-digit isbn
COinS = nil, -- nil because we can't use pre or rft or info:
separator = ' ',
},
['SSRN'] = {
parameters = {'ssrn', 'SSRN'},
link = 'Social Science Research Network',
redirect = 'SSRN (identifier)',
q = 'Q7550801',
label = 'SSRN',
prefix = 'https://papers.ssrn.com/sol3/papers.cfm?abstract_id=',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.SSRN or 0,
custom_access = 'ssrn-access',
},
['S2CID'] = {
parameters = {'s2cid', 'S2CID'},
link = 'Semantic Scholar',
redirect = 'S2CID (identifier)',
q = 'Q22908627',
label = 'S2CID',
prefix = 'https://api.semanticscholar.org/CorpusID:',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
id_limit = id_limits_data_t.S2CID or 0,
custom_access = 's2cid-access',
},
['USENETID'] = {
parameters = {'message-id'},
link = 'Usenet',
redirect = 'Usenet (identifier)',
q = 'Q193162',
label = 'Usenet:',
prefix = 'news:',
encode = false,
COinS = 'pre', -- use prefix value
separator = ' ',
},
['ZBL'] = {
parameters = {'zbl', 'ZBL' },
link = 'Zentralblatt MATH',
redirect = 'Zbl (identifier)',
q = 'Q190269',
label = 'Zbl',
prefix = 'https://zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
}
--[[--------------------------< E X P O R T S >---------------------------------
]]
return {
use_identifier_redirects = use_identifier_redirects, -- booleans defined in the settings at the top of this module
local_lang_cat_enable = local_lang_cat_enable,
date_name_auto_xlate_enable = date_name_auto_xlate_enable,
date_digit_auto_xlate_enable = date_digit_auto_xlate_enable,
enable_sort_keys = enable_sort_keys,
suppress_archive_today_urls = suppress_archive_today_urls,
-- tables and variables created when this module is loaded
dependencies_t = dependencies_t, -- used to suppress parameters dependent on url-holding parameters holding archive.today urls
enum_needs_xlation = '1' ~= date_names.xlate_digits['1'], -- to avoid unnecessary enumerator translation
global_df = get_date_format (), -- this line can be replaced with "global_df = 'dmy-all'," to have all dates auto translated to dmy format.
global_cs1_config_t = global_cs1_config_t, -- global settings from {{cs1 config}}
id_limits_data_load_fail = id_limits_data_load_fail, -- true when commons tabular identifier-limit data fails to load
known_free_doi_registrants_t = build_free_doi_registrants_table(),
punct_skip = build_skip_table (punct_skip, punct_meta_params),
url_skip = build_skip_table (url_skip, url_meta_params),
archive_today_tlds_t = {['today'] = true, ['ph'] = true, ['is'] = true, ['md'] = true, ['li'] = true, ['fo'] = true, ['vn'] = true}; -- used by is_archive_today_url()
name_space_sort_keys = name_space_sort_keys,
aliases = aliases,
special_case_translation = special_case_translation,
date_names = date_names,
err_msg_supl = err_msg_supl,
error_conditions = error_conditions,
et_al_patterns = et_al_patterns,
extended_registrants_t = extended_registrants_t,
id_handlers = id_handlers,
keywords_lists = keywords_lists,
keywords_xlate = keywords_xlate,
stripmarkers = stripmarkers,
invisible_chars = invisible_chars,
invisible_defs = invisible_defs,
indic_script = indic_script,
emoji_t = emoji_t,
messages = messages,
presentation = presentation,
prop_cats = prop_cats,
script_lang_codes = script_lang_codes,
lang_tag_remap = lang_tag_remap,
lang_name_remap = lang_name_remap,
this_wiki_code = this_wiki_code,
title_types = title_types,
uncategorized_namespaces = uncategorized_namespaces_t,
uncategorized_subpages = uncategorized_subpages,
templates_using_volume = templates_using_volume,
templates_using_issue = templates_using_issue,
templates_not_using_page = templates_not_using_page,
vol_iss_pg_patterns = vol_iss_pg_patterns,
single_letter_2nd_lvl_domains_t = single_letter_2nd_lvl_domains_t,
url_access_map_t = url_access_map_t,
inter_wiki_map = inter_wiki_map,
mw_languages_by_tag_t = mw_languages_by_tag_t,
mw_languages_by_name_t = mw_languages_by_name_t,
citation_class_map_t = citation_class_map_t,
citation_issue_t = citation_issue_t,
citation_no_volume_t = citation_no_volume_t,
}
e7w2jpc8m3hf485c54y7d0wmq4zi17p
9004
8256
2026-08-22T12:06:24Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/Configuration]]
8256
Scribunto
text/plain
local lang_obj = mw.getContentLanguage(); -- make a language object for the local language; used here for languages and dates
--[[--------------------------< S E T T I N G S >--------------------------------------------------------------
boolean settings used to control various things. these setting located here to make them easy to find
]]
-- these settings local to this module only
local local_digits_from_mediawiki = false; -- for i18n; when true, module fills date_names['local_digits'] from MediaWiki; manual fill required else; always false at en.wiki
-- these settings exported to other modules
local use_identifier_redirects = true; -- when true use redirect name for identifier label links; always true at en.wiki
local local_lang_cat_enable = false; -- when true categorizes pages where |language=<local wiki's language>; always false at en.wiki
local date_name_auto_xlate_enable = false; -- when true translates English month-names to the local-wiki's language month names; always false at en.wiki
local date_digit_auto_xlate_enable = false; -- when true translates Western date digit to the local-wiki's language digits (date_names['local_digits']); always false at en.wiki
local enable_sort_keys = true; -- when true module adds namespace sort keys to error and maintenance category links
local suppress_archive_today_urls = true; -- when true module suppresses all parameters with an archive.today url and any deprendent parameters
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------
List of namespaces identifiers for namespaces that will not be included in citation error categories.
Same as setting notracking = true by default.
For wikis that have a current version of Module:cs1 documentation support, this #invoke will return an unordered
list of namespace names and their associated identifiers:
{{#invoke:cs1 documentation support|uncategorized_namespace_lister|all=<anything>}}
]]
local uncategorized_namespaces_t = {[2]=true}; -- init with user namespace id
for k, _ in pairs (mw.site.talkNamespaces) do -- add all talk namespace ids
uncategorized_namespaces_t[k] = true;
end
local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases', '/[^/]*[Ll]og', '/[Aa]rchive'}; -- list of Lua patterns found in page names of pages we should not categorize
--[[
at en.wiki Greek characters are used as sort keys for certain items in a category so that those items are
placed at the end of a category page. See Wikipedia:Categorization#Sort_keys. That works well for en.wiki
because English is written using the Latn script. This may not work well for other languages. At en.wiki it
is desireable to place content from certain namespaces at the end of a category listing so the module adds sort
keys to error and maintenance category links when rendering a cs1|2 template on a page in that namespace.
i18n: if this does not work well for your language, set <enable_sort_keys> to false.
]]
local name_space_sort_keys = { -- sort keys to be used with these namespaces:
[4] = 'ω', -- wikipedia; omega
[10] = 'τ', -- template; tau
[118] = 'Δ', -- draft; delta
['other'] = 'ο', -- all other non-talk namespaces except main (article); omicron
}
--[[--------------------------< M E S S A G E S >--------------------------------------------------------------
Translation table
The following contains fixed text that may be output as part of a citation.
This is separated from the main body to aid in future translations of this
module.
]]
local messages = {
['agency'] = '$1 $2', -- $1 is sepc, $2 is agency
['archived-dead'] = 'Archived from $1 on $2',
['archived-live'] = '$1 from the original on $2',
['archived-unfit'] = 'Archived from the original on $1',
['archived'] = 'Archived',
['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword
['cartography'] = 'Cartography by $1',
['collaboration'] = '$1 ($2)', -- $1 is author with et al, $2 is collaboration
['editor'] = 'ed.',
['editors'] = 'eds.',
['edition'] = '($1 ed.)',
['episode'] = 'Episode $1',
['et al'] = 'et al.',
['in'] = 'In', -- edited works
['inactive'] = ' (inactive $1)', -- $1 is date which the doi was found to be broken in
['inset'] = '$1 inset',
['interview'] = 'Interviewed by $1',
invisible_1 = '$1 $2', -- $1 stripmarker name; $2 is text from <invisible_chars[1]>
invisible_2 = '$1 character', -- $1 character name from <invisible_chars[1]>
['mismatch'] = '<code class="cs1-code">|$1=</code> / <code class="cs1-code">|$2=</code> mismatch', -- $1 is year param name; $2 is date param name
['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1',
['notitle'] = 'No title', -- for |title=(()) and (in the future) |title=none
['original'] = 'the original',
['origdate'] = ' [$1]',
['published'] = ' (published $1)',
['retrieved'] = 'Retrieved $1',
['season'] = 'Season $1',
['section'] = '§ $1',
['sections'] = '§§ $1',
['series'] = '$1 $2', -- $1 is sepc, $2 is series
['seriesnum'] = 'Series $1',
['translated'] = 'Translated by $1',
['type'] = ' ($1)', -- for titletype
wikidata = 'Wikidata', -- these used for interwikilinked author/editor/... names
wikipedia = 'Wikipedia',
wikisource = 'Wikisource',
['written'] = 'Written at $1',
['vol'] = '$1 Vol. $2', -- $1 is sepc; bold journal style volume is in presentation{}
['vol-no'] = '$1 Vol. $2, no. $3', -- sepc, volume, issue (alternatively insert $1 after $2, but then we'd also have to change capitalization)
['issue'] = '$1 No. $2', -- $1 is sepc
['art'] = '$1 Art. $2', -- $1 is sepc; for {{cite conference}} only
['vol-art'] = '$1 Vol. $2, art. $3', -- sepc, volume, article-number; for {{cite conference}} only
['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{}
['j-issue'] = ' ($1)',
['j-article-num'] = ' $1', -- TODO: any punctuation here? static text?
['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc
['p-prefix'] = "$1 p. $2", -- $1 is sepc
['pp-prefix'] = "$1 pp. $2", -- $1 is sepc
['j-page(s)'] = ': $1', -- same for page and pages
['sheet'] = '$1 Sheet $2', -- $1 is sepc
['sheets'] = '$1 Sheets $2', -- $1 is sepc
['j-sheet'] = ': Sheet $1',
['j-sheets'] = ': Sheets $1',
['language'] = '(in $1)',
['via'] = " – via $1",
['event'] = 'Event occurs at',
['minutes'] = ' $1 minutes in', -- $1 is the number of minutes
-- Determines the location of the help page
['help page link'] = 'Help:CS1 errors',
['help page label'] = 'help',
-- categories
['cat wikilink'] = '[[Category:$1]]', -- $1 is the category name
['cat wikilink sk'] = '[[Category:$1|$2]]', -- $1 is the category name; $2 is namespace sort key
[':cat wikilink'] = '[[:Category:$1|link]]', -- category name as maintenance message wikilink; $1 is the category name
-- Internal errors (should only occur if configuration is bad)
['undefined_error'] = 'Called with an undefined error condition',
['unknown_ID_key'] = 'Unrecognized ID key: ', -- an ID key in id_handlers not found in ~/Identifiers func_map{}
['unknown_ID_access'] = 'Unrecognized ID access keyword: ', -- an ID access keyword in id_handlers not found in keywords_lists['id-access']{}
['unknown_argument_map'] = 'Argument map not defined for this variable',
['bare_url_no_origin'] = 'Bare URL found but origin indicator is nil or empty',
['warning_msg_e'] = '<span style="color:#d33"><code style="color: inherit; background: inherit; border: none; padding: inherit;">{{$1}}</code>: this [[#$2|reference]] has errors</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link; $2 is anchor ID
['warning_msg_m'] = '<span style="color:#085"><code style="color: inherit; background: inherit; border: none; padding: inherit;">{{$1}}</code>: this [[#$2|reference]] has maintenance messages</span>; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).'; -- $1 is template link; $2 is anchor ID
}
--[[--------------------------< C I T A T I O N _ C L A S S _ M A P >------------------------------------------
this table maps the value assigned to |CitationClass= in the cs1|2 templates to the canonical template name when
the value assigned to |CitationClass= is different from the canonical template name. |CitationClass= values are
used as class attributes in the <cite> tag that encloses the citation so these names may not contain spaces while
the canonical template name may. These names are used in warning_msg_e and warning_msg_m to create links to the
template's documentation when an article is displayed in preview mode.
]]
local citation_class_map_t = { -- TODO: in Module:Cite/config write a function to use this table
arxiv = 'cite arXiv', -- as the source for known_templates_t and citation_classes_t
['audio-visual'] = 'cite AV media',
['AV-media-notes'] = 'cite AV media notes',
biorxiv = 'cite bioRxiv',
book = 'cite book',
citation = 'citation',
citeseerx = 'cite CiteSeerX',
conference = 'cite conference',
document = 'cite document',
encyclopaedia = 'cite encyclopedia',
episode = 'cite episode',
interview = 'cite interview',
journal = 'cite journal',
magazine = 'cite magazine',
mailinglist = 'cite mailing list',
map = 'cite map',
medrxiv = 'cite medRxiv',
news = 'cite news',
newsgroup = 'cite newsgroup',
podcast = 'cite podcast',
pressrelease = 'cite press release',
report = 'cite report',
serial = 'cite serial',
sign = 'cite sign',
speech = 'cite speech',
ssrn = 'cite SSRN',
techreport = 'cite tech report',
thesis = 'cite thesis',
web = 'cite web',
}
--[=[-------------------------< E T _ A L _ P A T T E R N S >--------------------------------------------------
This table provides Lua patterns for the phrase "et al" and variants in name text
(author, editor, etc.). The main module uses these to identify and emit the 'etal' message.
]=]
local et_al_patterns = {
"[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\"']*$", -- variations on the 'et al' theme
"[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\"']*$", -- variations on the 'et alia', 'et alii' and 'et aliae' themes (false positive 'et aliie' unlikely to match)
"[;,]? *%f[%a]and [Oo]thers", -- an alternative to et al.
"%[%[ *[Ee][Tt]%.? *[Aa][Ll]%.? *%]%]", -- a wikilinked form
"%(%( *[Ee][Tt]%.? *[Aa][Ll]%.? *%)%)", -- a double-bracketed form (to counter partial removal of ((...)) syntax)
"[%(%[] *[Ee][Tt]%.? *[Aa][Ll]%.? *[%)%]]", -- a bracketed form
}
--[[--------------------------< P R E S E N T A T I O N >------------------------
Fixed presentation markup. Originally part of citation_config.messages it has
been moved into its own, more semantically correct place.
]]
local presentation =
{
-- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display
['hidden-error'] = '<span class="cs1-hidden-error citation-comment">$1</span>',
['visible-error'] = '<span class="cs1-visible-error citation-comment">$1</span>',
['hidden-maint'] = '<span class="cs1-maint citation-comment">$1</span>',
['accessdate'] = '<span class="reference-accessdate">$1$2</span>', -- to allow editors to hide accessdate using personal CSS
['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like
['cite'] = '<cite class="$1">$2</cite>'; -- for use when citation does not have a namelist and |ref= not set so no id="..." attribute
['cite-id'] = '<cite id="$1" class="$2">$3</cite>'; -- for use when when |ref= is set or when citation has a namelist
['format'] = ' <span class="cs1-format">($1)</span>', -- for |format=, |chapter-format=, etc.
['interwiki'] = ' <span class="cs1-format">[in $1]</span>', -- for interwiki-language-linked author, editor, etc
['interproj'] = ' <span class="cs1-format">[at $1]</span>', -- for interwiki-project-linked author, editor, etc (:d: and :s: supported; :w: ignored)
-- various access levels, for |access=, |doi-access=, |arxiv=, ...
-- narrow no-break space   may work better than nowrap CSS. Or not? Browser support?
['ext-link-access-signal'] = '<span class="$1" title="$2">$3</span>', -- external link with appropriate lock icon
['free'] = {class='id-lock-free', title='Freely accessible'}, -- classes defined in Module:Citation/CS1/styles.css
['registration'] = {class='id-lock-registration', title='Free registration required'},
['limited'] = {class='id-lock-limited', title='Free access subject to limited trial, subscription normally required'},
['subscription'] = {class='id-lock-subscription', title='Paid subscription required'},
['interwiki-icon'] = '<span class="$1" title="$2">$3</span>',
['class-wikisource'] = 'cs1-ws-icon',
['italic-title'] = "''$1''",
['kern-left'] = '<span class="cs1-kern-left"></span>$1', -- spacing to use when title contains leading single or double quote mark
['kern-right'] = '$1<span class="cs1-kern-right"></span>', -- spacing to use when title contains trailing single or double quote mark
['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span>
['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space)
['ocins'] = '<span title="$1" class="Z3988"></span>',
['parameter'] = '<code class="cs1-code">|$1=</code>',
['ps_cs1'] = '.'; -- CS1 style postscript (terminal) character
['ps_cs2'] = ''; -- CS2 style postscript (terminal) character (empty string)
['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content
['quoted-title'] = '"$1"',
['sep_cs1'] = '.', -- CS1 element separator
['sep_cs2'] = ',', -- CS2 separator
['sep_nl'] = ';', -- CS1|2 style name-list separator between names is a semicolon
['sep_nl_and'] = ' and ', -- used as last nl sep when |name-list-style=and and list has 2 items
['sep_nl_end'] = '; and ', -- used as last nl sep when |name-list-style=and and list has 3+ names
['sep_name'] = ', ', -- CS1|2 style last/first separator is <comma><space>
['sep_nl_vanc'] = ',', -- Vancouver style name-list separator between authors is a comma
['sep_name_vanc'] = ' ', -- Vancouver style last/first separator is a space
['sep_list'] = ', ', -- used for |language= when list has 3+ items except for last sep which uses sep_list_end
['sep_list_pair'] = ' and ', -- used for |language= when list has 2 items
['sep_list_end'] = ', and ', -- used as last list sep for |language= when list has 3+ items
['trans-italic-title'] = "[''$1'']",
['trans-quoted-title'] = "[$1]", -- for |trans-title= and |trans-quote=
['vol-bold'] = '$1 <b>$2</b>', -- sepc, volume; for bold journal cites; for other cites ['vol'] in messages{}
}
--[[--------------------------< A L I A S E S >---------------------------------
Aliases table for commonly passed parameters.
Parameter names on the right side in the assignments in this table must have been
defined in the Whitelist before they will be recognized as valid parameter names
]]
local aliases = {
['AccessDate'] = {'access-date', 'accessdate'}, -- Used by InternetArchiveBot
['Agency'] = 'agency',
['ArchiveDate'] = {'archive-date', 'archivedate'}, -- Used by InternetArchiveBot
['ArchiveFormat'] = 'archive-format',
['ArchiveURL'] = {'archive-url', 'archiveurl'}, -- Used by InternetArchiveBot
['ArticleNumber'] = 'article-number',
['ASINTLD'] = 'asin-tld',
['At'] = 'at', -- Used by InternetArchiveBot
['Authors'] = {'people', 'credits'},
['BookTitle'] = {'book-title', 'booktitle'},
['Cartography'] = 'cartography',
['Chapter'] = {'chapter', 'contribution', 'entry', 'article', 'section'},
['ChapterFormat'] = {'chapter-format', 'contribution-format', 'entry-format',
'article-format', 'section-format'};
['ChapterURL'] = {'chapter-url', 'contribution-url', 'entry-url', 'article-url', 'section-url'}, -- Used by InternetArchiveBot
['ChapterUrlAccess'] = {'chapter-url-access', 'contribution-url-access',
'entry-url-access', 'article-url-access', 'section-url-access'}, -- Used by InternetArchiveBot
['Class'] = 'class', -- cite arxiv and arxiv identifier
['Collaboration'] = 'collaboration',
['Conference'] = {'conference', 'event'},
['ConferenceFormat'] = 'conference-format',
['ConferenceURL'] = 'conference-url', -- Used by InternetArchiveBot
['Date'] = {'date', 'air-date', 'airdate'}, -- air-date and airdate for cite episode and cite serial only
['Degree'] = 'degree',
['DF'] = 'df',
['DisplayAuthors'] = {'display-authors', 'display-subjects'},
['DisplayContributors'] = 'display-contributors',
['DisplayEditors'] = 'display-editors',
['DisplayInterviewers'] = 'display-interviewers',
['DisplayTranslators'] = 'display-translators',
['Docket'] = 'docket',
['DoiBroken'] = 'doi-broken-date',
['Edition'] = 'edition',
['Embargo'] = 'pmc-embargo-date',
['Encyclopedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'}, -- cite encyclopedia only
['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode?
['Format'] = 'format',
['ID'] = {'id', 'ID'},
['Inset'] = 'inset',
['Issue'] = {'issue', 'number'},
['Language'] = {'language', 'lang'},
['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only
['Map'] = 'map', -- cite map only
['MapFormat'] = 'map-format', -- cite map only
['MapURL'] = {'map-url', 'mapurl'}, -- cite map only -- Used by InternetArchiveBot
['MapUrlAccess'] = 'map-url-access', -- cite map only -- Used by InternetArchiveBot
['Minutes'] = 'minutes',
['Mode'] = 'mode',
['NameListStyle'] = 'name-list-style',
['Network'] = 'network',
['Newsgroup'] = 'newsgroup', -- cite newsgroup only
['NoPP'] = {'no-pp', 'nopp'},
['NoTracking'] = {'no-tracking', 'template-doc-demo'},
['Number'] = 'number', -- this case only for cite techreport
['OrigDate'] = {'orig-date', 'orig-year', 'origyear'},
['Others'] = 'others',
['Page'] = {'page', 'p'}, -- Used by InternetArchiveBot
['Pages'] = {'pages', 'pp'}, -- Used by InternetArchiveBot
['Periodical'] = {'journal', 'magazine', 'newspaper', 'periodical', 'website', 'work'},
['Place'] = {'place', 'location'},
['PostScript'] = 'postscript',
['PublicationDate'] = {'publication-date', 'publicationdate'},
['PublicationPlace'] = {'publication-place', 'publicationplace'},
['PublisherName'] = {'publisher', 'institution'},
['Quote'] = {'quote', 'quotation'},
['QuotePage'] = 'quote-page',
['QuotePages'] = 'quote-pages',
['Ref'] = 'ref',
['Scale'] = 'scale',
['ScriptChapter'] = {'script-chapter', 'script-contribution', 'script-entry',
'script-article', 'script-section'},
['ScriptEncyclopedia'] = {'script-encyclopedia', 'script-encyclopaedia'}, -- cite encyclopedia only
['ScriptMap'] = 'script-map',
['ScriptPeriodical'] = {'script-journal', 'script-magazine', 'script-newspaper',
'script-periodical', 'script-website', 'script-work'},
['ScriptQuote'] = 'script-quote',
['ScriptTitle'] = 'script-title', -- Used by InternetArchiveBot
['Season'] = 'season',
['Sections'] = 'sections', -- cite map only
['Series'] = {'series', 'version'},
['SeriesLink'] = {'series-link', 'serieslink'},
['SeriesNumber'] = {'series-number', 'series-no'},
['Sheet'] = 'sheet', -- cite map only
['Sheets'] = 'sheets', -- cite map only
['Station'] = 'station',
['Time'] = 'time',
['TimeCaption'] = 'time-caption',
['Title'] = 'title', -- Used by InternetArchiveBot
['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot
['TitleNote'] = {'title-note', 'department'},
['TitleType'] = {'type', 'medium'},
['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution',
'trans-entry', 'trans-section'},
['Transcript'] = 'transcript',
['TranscriptFormat'] = 'transcript-format',
['TranscriptURL'] = 'transcript-url', -- Used by InternetArchiveBot
['TransEncyclopedia'] = {'trans-encyclopedia', 'trans-encyclopaedia'}, -- cite encyclopedia only
['TransMap'] = 'trans-map', -- cite map only
['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper',
'trans-periodical', 'trans-website', 'trans-work'},
['TransQuote'] = 'trans-quote',
['TransTitle'] = 'trans-title', -- Used by InternetArchiveBot
['URL'] = {'url', 'URL'}, -- Used by InternetArchiveBot
['UrlAccess'] = 'url-access', -- Used by InternetArchiveBot
['UrlStatus'] = 'url-status', -- Used by InternetArchiveBot
['Vauthors'] = 'vauthors',
['Veditors'] = 'veditors',
['Via'] = 'via',
['Volume'] = 'volume',
['Year'] = 'year',
['AuthorList-First'] = {"first#", "author-first#", "author#-first", "author-given#", "author#-given",
"subject-first#", "subject#-first", "subject-given#", "subject#-given",
"given#"},
['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "author-surname#", "author#-surname",
"subject-last#", "subject#-last", "subject-surname#", "subject#-surname",
"author#", 'host#', "subject#", "surname#"},
['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#",
"subject#-link", "authorlink#", "author#link"},
['AuthorList-Mask'] = {"author-mask#", "author#-mask", "subject-mask#", "subject#-mask"},
['ContributorList-First'] = {'contributor-first#', 'contributor#-first',
'contributor-given#', 'contributor#-given'},
['ContributorList-Last'] = {'contributor-last#', 'contributor#-last',
'contributor-surname#', 'contributor#-surname', 'contributor#'},
['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'},
['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'},
['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"},
['EditorList-Last'] = {"editor-last#", "editor#-last", "editor-surname#",
"editor#-surname", "editor#"},
['EditorList-Link'] = {"editor-link#", "editor#-link"},
['EditorList-Mask'] = {"editor-mask#", "editor#-mask"},
['InterviewerList-First'] = {'interviewer-first#', 'interviewer#-first',
'interviewer-given#', 'interviewer#-given'},
['InterviewerList-Last'] = {'interviewer-last#', 'interviewer#-last',
'interviewer-surname#', 'interviewer#-surname', 'interviewer#'},
['InterviewerList-Link'] = {'interviewer-link#', 'interviewer#-link'},
['InterviewerList-Mask'] = {'interviewer-mask#', 'interviewer#-mask'},
['TranslatorList-First'] = {'translator-first#', 'translator#-first',
'translator-given#', 'translator#-given'},
['TranslatorList-Last'] = {'translator-last#', 'translator#-last',
'translator-surname#', 'translator#-surname', 'translator#'},
['TranslatorList-Link'] = {'translator-link#', 'translator#-link'},
['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'},
}
--[[--------------------------< D E P E N D E N C I E S _ T >--------------------------------------------------
a table of url-holding parameters upon which other parameters are dependent.
this table is used by has_archive_today_url() to suppress parameters that are dependant upon a url-holding parameter
that has as a value an archive.today (or alternate tld) url.
archive.today is deprecated at en.wiki; see Wikipedia:Requests_for_comment/Archive.is_RFC_5
]]
local url_dependency_map_t = { -- table of url-holding parameters and the meta-parameters that are dependent on them
['url'] = {'AccessDate', 'ArchiveURL', 'Format', 'UrlAccess'},
['archive-url'] = {'ArchiveDate', 'ArchiveFormat', 'UrlStatus'},
['archiveurl'] = {'ArchiveDate', 'ArchiveFormat', 'UrlStatus'},
['article-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['chapter-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['conference-url'] = {'ConferenceFormat'},
['contribution-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['entry-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['map-url'] = {'MapFormat', 'MapUrlAccess'},
['section-url'] = {'ChapterFormat', 'ChapterUrlAccess'},
['transcript-url'] = {'TranscriptFormat'},
};
local dependencies_t = {}; -- the table of url-holding parameters and their dependent parameters
for url_param, meta_parameters_t in pairs (url_dependency_map_t) do -- sequence of meta-parameters (indexes) into <aliases> table
local dependant_params_t = {}; -- collection of parameters that are dependent on this <url_param>
for _, meta_parameter in ipairs (meta_parameters_t) do -- for each <aliases> meta-parameter (index)
if 'string' == type (aliases[meta_parameter]) then -- for single parameter names (no aliases), <aliases[meta_parameter]> will be a string
table.insert (dependant_params_t, aliases[meta_parameter]); -- add to this <url_param>'s dependency sequence
else
for _, alias in ipairs (aliases[meta_parameter]) do -- for each alias in aliases[meta_parameter] (aliases['AccessDate'] for example)
table.insert (dependant_params_t, alias); -- add to this <url_param>'s dependency sequence
end
end
end
dependencies_t[url_param] = dependant_params_t; -- add the <url_param> and its dependent parameters
end
--[[--------------------------< P U N C T _ S K I P >---------------------------
builds a table of parameter names that the extraneous terminal punctuation check should not check.
]]
local punct_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value
'BookTitle', 'Chapter', 'ScriptChapter', 'ScriptTitle', 'Title', 'TransChapter', 'Transcript', 'TransMap', 'TransTitle', -- title-holding parameters
'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators
'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous
'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'MapURL', 'TranscriptURL', 'URL', -- URL-holding parameters
}
local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value
'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID', 'MapURL', 'TranscriptURL', 'URL', -- parameters allowed to hold urls
'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls
}
local function build_skip_table (skip_t, meta_params)
for _, meta_param in ipairs (meta_params) do -- for each meta parameter key
local params = aliases[meta_param]; -- get the parameter or the table of parameters associated with the meta parameter name
if 'string' == type (params) then
skip_t[params] = 1; -- just a single parameter
else
for _, param in ipairs (params) do -- get the parameter name
skip_t[param] = 1; -- add the parameter name to the skip table
local count;
param, count = param:gsub ('#', ''); -- remove enumerator marker from enumerated parameters
if 0 ~= count then -- if removed
skip_t[param] = 1; -- add param name without enumerator marker
end
end
end
end
return skip_t;
end
local punct_skip = {};
local url_skip = {};
--[[--------------------------< U R L _ A C C E S S _ M A P >--------------------------------------------------
this table used by the wikipedia library url test, has_twl_url(), which automatically sets a url-access parameter
to 'subscription' when it discovers a wikipedia library url in any of the url-holding paramters used as keys in
this table.
translators: if your wiki uses parameter names for these url-holding parameters and their matching -access parameters,
add your wiki's parameters to this list. Leave the English parameters in place.
TODO: is there a better way to do this?
]]
local url_access_map_t = {
['chapter-url'] = 'chapter-url-access',
['contribution-url'] = 'contribution-url-access',
['entry-url'] = 'entry-url-access',
['article-url'] = 'article-url-access',
['section-url'] = 'section-url-access',
['map-url'] = 'map-url-access',
['mapurl'] = 'map-url-access',
['url'] = 'url-access',
['URL'] = 'url-access'
}
--[[--------------------------< S I N G L E - L E T T E R S E C O N D - L E V E L D O M A I N S >----------
this is a list of tlds that are known to have single-letter second-level domain names. This list does not include
ccTLDs which are accepted in is_domain_name().
]]
local single_letter_2nd_lvl_domains_t = {'cash', 'company', 'foundation', 'media', 'org', 'today'};
--[[-----------< S P E C I A L C A S E T R A N S L A T I O N S >------------
This table is primarily here to support internationalization. Translations in
this table are used, for example, when an error message, category name, etc.,
is extracted from the English alias key. There may be other cases where
this translation table may be useful.
]]
local is_Latn = 'A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143\225\184\128-\225\187\191';
local special_case_translation = {
author = 'author',
editor = 'editor',
name_list_params = '$1-name-list parameters', -- $1 is 'author' or 'editor'; used with err_redundant_parameters
['AuthorList'] = 'authors list', -- used to assemble maintenance category names
['ContributorList'] = 'contributors list', -- translation of these names plus translation of the base maintenance category names in maint_cats{} table below
['EditorList'] = 'editors list', -- must match the names of the actual categories
['InterviewerList'] = 'interviewers list', -- this group or translations used by name_has_ed_markup() and name_has_mult_names()
['TranslatorList'] = 'translators list',
-- Lua patterns to match pseudo-titles used by InternetArchiveBot and others as placeholder for unknown |title= value
['archived_copy'] = { -- used with CS1 maint: Archive[d] copy as title
['en'] = '^archived?%s+copy$', -- for English; translators: keep this because templates imported from en.wiki
['local'] = nil, -- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language
},
-- Lua patterns to match generic titles; usually created by bots or reference filling tools
-- translators: replace ['local'] = nil with lowercase translation only when bots or tools create generic titles in your language
-- generic titles and patterns in this table should be lowercase only
-- leave ['local'] nil except when there is a matching generic title in your language
-- boolean 'true' for plain-text searches; 'false' for pattern searches
['generic_titles'] = {
['accept'] = {
},
['reject'] = {
{['en'] = {'^wayback%s+machine$', false}, ['local'] = nil},
{['en'] = {'are you a robot', true}, ['local'] = nil},
{['en'] = {'hugedomains', true}, ['local'] = nil},
{['en'] = {'^[%(%[{<]?no +title[>}%]%)]?$', false}, ['local'] = nil},
{['en'] = {'page not found', true}, ['local'] = nil},
{['en'] = {'subscribe to read', true}, ['local'] = nil},
{['en'] = {'^[%(%[{<]?unknown[>}%]%)]?$', false}, ['local'] = nil},
{['en'] = {'website is for sale', true}, ['local'] = nil},
{['en'] = {'^404', false}, ['local'] = nil},
{['en'] = {'error[ %-]404', false}, ['local'] = nil},
{['en'] = {'internet archive wayback machine', true}, ['local'] = nil},
{['en'] = {'log into facebook', true}, ['local'] = nil},
{['en'] = {'login • instagram', true}, ['local'] = nil},
{['en'] = {'redirecting...', true}, ['local'] = nil},
{['en'] = {'usurped title', true}, ['local'] = nil}, -- added by a GreenC bot
{['en'] = {'wayback machine', true}, ['local'] = nil},
{['en'] = {'webcite query result', true}, ['local'] = nil},
{['en'] = {'wikiwix\'s cache', true}, ['local'] = nil},
{['en'] = {'bot verification', true}, ['local'] = nil},
}
},
-- boolean 'true' for plain-text searches, search string must be lowercase only
-- boolean 'false' for pattern searches
-- leave ['local'] nil except when there is a matching generic name in your language
['generic_names'] = {
['accept'] = {
{['en'] = {'%[%[[^|]*%(author%) *|[^%]]*%]%]', false}, ['local'] = nil},
},
['reject'] = {
{['en'] = {'about us', true}, ['local'] = nil},
{['en'] = {'%f[%a][Aa]dvisor%f[%A]', false}, ['local'] = nil},
{['en'] = {'allmusic', true}, ['local'] = nil},
{['en'] = {'%f[%a][Aa]uthor%f[%A]', false}, ['local'] = nil},
{['en'] = {'^[Bb]ureau$', false}, ['local'] = nil},
{['en'] = {'business', true}, ['local'] = nil},
{['en'] = {'cnn', true}, ['local'] = nil},
{['en'] = {'collaborator', true}, ['local'] = nil},
{['en'] = {'^[Cc]ompany$', false}, ['local'] = nil},
{['en'] = {'contributor', true}, ['local'] = nil},
{['en'] = {'contact us', true}, ['local'] = nil},
{['en'] = {'correspondent', true}, ['local'] = nil},
{['en'] = {'^[Dd]esk$', false}, ['local'] = nil},
{['en'] = {'directory', true}, ['local'] = nil},
{['en'] = {'%f[%(%[][%(%[]%s*eds?%.?%s*[%)%]]?$', false}, ['local'] = nil},
{['en'] = {'[,%.%s]%f[e]eds?%.?$', false}, ['local'] = nil},
{['en'] = {'^eds?[%.,;]', false}, ['local'] = nil},
{['en'] = {'^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]dited%f[%A]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]ditors?%f[%A]', false}, ['local'] = nil},
{['en'] = {'%f[%a][Ee]mail%f[%A]', false}, ['local'] = nil},
{['en'] = {'facebook', true}, ['local'] = nil},
{['en'] = {'google', true}, ['local'] = nil},
{['en'] = {'^[Gg]roup$', false}, ['local'] = nil},
{['en'] = {'home page', true}, ['local'] = nil},
{['en'] = {'^[Ii]nc%.?$', false}, ['local'] = nil},
{['en'] = {'instagram', true}, ['local'] = nil},
{['en'] = {'interviewer', true}, ['local'] = nil},
{['en'] = {'^[Ll]imited$', false}, ['local'] = nil},
{['en'] = {'linkedIn', true}, ['local'] = nil},
{['en'] = {'^[Nn]ews$', false}, ['local'] = nil},
{['en'] = {'[Nn]ews[ %-]?[Rr]oom', false}, ['local'] = nil},
{['en'] = {'pinterest', true}, ['local'] = nil},
{['en'] = {'policy', true}, ['local'] = nil},
{['en'] = {'privacy', true}, ['local'] = nil},
{['en'] = {'reuters', true}, ['local'] = nil},
{['en'] = {'translator', true}, ['local'] = nil},
{['en'] = {'tumblr', true}, ['local'] = nil},
{['en'] = {'twitter', true}, ['local'] = nil},
{['en'] = {'site name', true}, ['local'] = nil},
{['en'] = {'statement', true}, ['local'] = nil},
{['en'] = {'submitted', true}, ['local'] = nil},
{['en'] = {'super.?user', false}, ['local'] = nil},
{['en'] = {'%f['..is_Latn..'][Uu]ser%f[^'..is_Latn..']', false}, ['local'] = nil},
{['en'] = {'updated', true}, ['local'] = nil},
{['en'] = {'verfasser', true}, ['local'] = nil},
}
}
}
--[[--------------------------< D A T E _ N A M E S >----------------------------------------------------------
This table of tables lists local language date names and fallback English date names.
The code in Date_validation will look first in the local table for valid date names.
If date names are not found in the local table, the code will look in the English table.
Because citations can be copied to the local wiki from en.wiki, the English is
required when the date-name translation function date_name_xlate() is used.
In these tables, season numbering is defined by
Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard
defines various divisions using numbers 21-41. CS1|2 only supports generic seasons.
EDTF does support the distinction between north and south hemisphere seasons
but CS1|2 has no way to make that distinction.
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
The standard does not address 'named' dates so, for the purposes of CS1|2,
Easter and Christmas are defined here as 98 and 99, which should be out of the
ISO 8601 (EDTF) range of uses for a while.
local_date_names_from_mediawiki is a boolean. When set to:
true – module will fetch local month names from MediaWiki for both date_names['local']['long'] and date_names['local']['short']; this will unconditionally overwrite manual translations
false – module will *not* fetch local month names from MediaWiki
Caveat lector: There is no guarantee that MediaWiki will provide short month names. At your wiki you can test
the results of the MediaWiki fetch in the debug console with this command (the result is alpha sorted):
=mw.dumpObject (p.date_names['local'])
While the module can fetch month names from MediaWiki, it cannot fetch the quarter, season, and named date names
from MediaWiki. Those must be translated manually.
]]
local local_date_names_from_mediawiki = true; -- when false, manual translation required for date_names['local']['long'] and date_names['local']['short']; overwrites manual translations
-- when true, module fetches long and short month names from MediaWiki
local date_names = {
['en'] = { -- English
['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12},
['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12},
['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36},
['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23},
['named'] = {['Easter'] = 98, ['Christmas'] = 99},
},
-- when local_date_names_from_mediawiki = false
['local'] = { -- replace these English date names with the local language equivalents
['long'] = {['January'] = 1, ['February'] = 2, ['March'] = 3, ['April'] = 4, ['May'] = 5, ['June'] = 6, ['July'] = 7, ['August'] = 8, ['September'] = 9, ['October'] = 10, ['November'] = 11, ['December'] = 12},
['short'] = {['Jan'] = 1, ['Feb'] = 2, ['Mar'] = 3, ['Apr'] = 4, ['May'] = 5, ['Jun'] = 6, ['Jul'] = 7, ['Aug'] = 8, ['Sep'] = 9, ['Oct'] = 10, ['Nov'] = 11, ['Dec'] = 12},
['quarter'] = {['First Quarter'] = 33, ['Second Quarter'] = 34, ['Third Quarter'] = 35, ['Fourth Quarter'] = 36},
['season'] = {['Winter'] = 24, ['Spring'] = 21, ['Summer'] = 22, ['Fall'] = 23, ['Autumn'] = 23},
['named'] = {['Easter'] = 98, ['Christmas'] = 99},
},
['inv_local_long'] = {}, -- used in date reformatting & translation; copy of date_names['local'].long where k/v are inverted: [1]='<local name>' etc.
['inv_local_short'] = {}, -- used in date reformatting & translation; copy of date_names['local'].short where k/v are inverted: [1]='<local name>' etc.
['inv_local_quarter'] = {}, -- used in date translation; copy of date_names['local'].quarter where k/v are inverted: [1]='<local name>' etc.
['inv_local_season'] = {}, -- used in date translation; copy of date_names['local'].season where k/v are inverted: [1]='<local name>' etc.
['inv_local_named'] = {}, -- used in date translation; copy of date_names['local'].named where k/v are inverted: [1]='<local name>' etc.
['local_digits'] = {['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7', ['8'] = '8', ['9'] = '9'}, -- used to convert local language digits to Western 0-9
['xlate_digits'] = {},
}
if local_date_names_from_mediawiki then -- if fetching local month names from MediaWiki is enabled
local long_t = {};
local short_t = {};
for i=1, 12 do -- loop 12x and
local name = lang_obj:formatDate('F', '2022-' .. i .. '-1'); -- get long month name for each i
long_t[name] = i; -- save it
name = lang_obj:formatDate('M', '2022-' .. i .. '-1'); -- get short month name for each i
short_t[name] = i; -- save it
end
date_names['local']['long'] = long_t; -- write the long table – overwrites manual translation
date_names['local']['short'] = short_t; -- write the short table – overwrites manual translation
end
-- create inverted date-name tables for reformatting and/or translation
for _, invert_t in pairs {{'long', 'inv_local_long'}, {'short', 'inv_local_short'}, {'quarter', 'inv_local_quarter'}, {'season', 'inv_local_season'}, {'named', 'inv_local_named'}} do
for name, i in pairs (date_names['local'][invert_t[1]]) do -- this table is ['name'] = i
date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd
end
end
if local_digits_from_mediawiki then -- if fetching local digits from MediaWiki is enabled
local digits_t = {};
for i=0, 9 do -- loop 10x and
digits_t [lang_obj:formatNum (i)] = tostring (i); -- format the loop indexer as local lang table index and assign loop indexer (a string) as the value
end
date_names['local_digits'] = digits_t;
end
for ld, ed in pairs (date_names.local_digits) do -- make a digit translation table for simple date translation from en to local language using local_digits table
date_names.xlate_digits [ed] = ld; -- en digit becomes index with local digit as the value
end
local df_template_patterns = { -- table of redirects to {{Use dmy dates}} and {{Use mdy dates}}
'{{ *[Uu]se +(dmy) +dates *[|}]', -- 1159k -- sorted by approximate transclusion count
'{{ *[Uu]se +(mdy) +dates *[|}]', -- 212k
'{{ *[Uu]se +(MDY) +dates *[|}]', -- 788
'{{ *[Uu]se +(DMY) +dates *[|}]', -- 343
'{{ *([Mm]dy) *[|}]', -- 176
'{{ *[Uu]se *(dmy) *[|}]', -- 156 + 18
'{{ *[Uu]se *(mdy) *[|}]', -- 149 + 11
'{{ *([Dd]my) *[|}]', -- 56
'{{ *[Uu]se +(MDY) *[|}]', -- 5
'{{ *([Dd]MY) *[|}]', -- 3
'{{ *[Uu]se(mdy)dates *[|}]', -- 1
'{{ *[Uu]se +(DMY) *[|}]', -- 0
'{{ *([Mm]DY) *[|}]', -- 0
}
local title_object = mw.title.getCurrentTitle();
local content; -- done this way so that unused templates appear in unused-template-reports; self-transcluded makes them look like they are used
if 10 ~= title_object.namespace then -- all namespaces except Template
content = title_object:getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625
end
local function get_date_format ()
if not content then -- nil content when we're in template
return nil; -- auto-formatting does not work in Template space so don't set global_df
end
for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects
local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format
if match then
local use_dates_template = content:match ('%b{}', start); -- get the whole template
if use_dates_template:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length
return match:lower() .. '-' .. use_dates_template:match ('| *cs1%-dates *= *([lsy][sy]?)');
else
return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df=
end
end
end
end
--[[-----------------< V O L U M E , I S S U E , P A G E S >------------------
These tables hold cite class values (from the template invocation) and identify those templates that support
|volume=, |issue=, and |page(s)= parameters. Cite conference and cite map require further qualification which
is handled in the main module.
]]
local templates_using_volume = {'citation', 'audio-visual', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'}
local templates_using_issue = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news', 'podcast'}
local templates_not_using_page = {'audio-visual', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'}
--[[
These tables control when it is appropriate for {{citation}} to render |volume= and/or |issue=. The parameter
names in the tables constrain {{citation}} so that its renderings match the renderings of the equivalent cs1
templates. For example, {{cite web}} does not support |volume= so the equivalent {{citation |website=...}} must
not support |volume=.
]]
local citation_no_volume_t = { -- {{citation}} does not render |volume= when these parameters are used
'website', 'mailinglist', 'script-website',
}
local citation_issue_t = { -- {{citation}} may render |issue= when these parameters are used
'journal', 'magazine', 'newspaper', 'periodical', 'work',
'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work',
}
--[[
Patterns for finding extra text in |volume=, |issue=, |page=, |pages=
]]
local vol_iss_pg_patterns = {
good_ppattern = '^P[^%.PpGg]', -- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123); TODO: this allows 'Pages' which it should not
bad_ppatterns = { -- patterns for |page= and |pages=
'^[Pp][PpGg]?%.?[ %d]',
'^[Pp][Pp]?%. ', -- from {{p.}} and {{pp.}} templates
'^[Pp]ages?',
'^[Pp]gs.?',
},
vi_patterns_t = { -- combined to catch volume-like text in |issue= and issue-like text in |volume=
'^volumes?', -- volume-like text
'^vols?[%.:=]?',
'^issues?', --issue-like text
'^iss[%.:=]?',
'^numbers?',
'^nos?%A', -- don't match 'november' or 'nostradamus'
'^nr[%.:=]?',
'^n[%.:= ]', -- might be a valid issue without separator (space char is sep char here)
'^n°', -- 'n' with degree sign (U+00B0)
'^№', -- precomposed unicode numero character (U+2116)
},
}
--[[--------------------------< K E Y W O R D S >-------------------------------
These tables hold keywords for those parameters that have defined sets of acceptable keywords.
]]
--[[-------------------< K E Y W O R D S T A B L E >--------------------------
this is a list of keywords; each key in the list is associated with a table of
synonymous keywords possibly from different languages.
for I18N: add local-language keywords to value table; do not change the key.
For example, adding the German keyword 'ja':
['affirmative'] = {'yes', 'true', 'y', 'ja'},
Because CS1|2 templates from en.wiki articles are often copied to other local wikis,
it is recommended that the English keywords remain in these tables.
]]
local keywords = {
['amp'] = {'&', 'amp', 'ampersand'}, -- |name-list-style=
['and'] = {'and', 'serial'}, -- |name-list-style=
['affirmative'] = {'yes', 'true', 'y'}, -- |no-tracking=, |no-pp= -- Used by InternetArchiveBot
['afterword'] = {'afterword'}, -- |contribution=
['bot: unknown'] = {'bot: unknown'}, -- |url-status= -- Used by InternetArchiveBot
['cs1'] = {'cs1'}, -- |mode=
['cs2'] = {'cs2'}, -- |mode=
['dead'] = {'dead', 'deviated'}, -- |url-status= -- Used by InternetArchiveBot
['dmy'] = {'dmy'}, -- |df=
['dmy-all'] = {'dmy-all'}, -- |df=
etal = {'etal'}, -- |display-authors=, etc
['foreword'] = {'foreword'}, -- |contribution=
['free'] = {'free'}, -- |<id>-access= -- Used by InternetArchiveBot
['harv'] = {'harv'}, -- |ref=; this no longer supported; is_valid_parameter_value() called with <invert> = true
['introduction'] = {'introduction'}, -- |contribution=
['limited'] = {'limited'}, -- |url-access= -- Used by InternetArchiveBot
['live'] = {'live'}, -- |url-status= -- Used by InternetArchiveBot
['mdy'] = {'mdy'}, -- |df=
['mdy-all'] = {'mdy-all'}, -- |df=
['none'] = {'none'}, -- |postscript=, |ref=, |title=, |type= -- Used by InternetArchiveBot
['off'] = {'off'}, -- |title= (potentially also: |title-link=, |postscript=, |ref=, |type=)
['preface'] = {'preface'}, -- |contribution=
['registration'] = {'registration'}, -- |url-access= -- Used by InternetArchiveBot
['subscription'] = {'subscription'}, -- |url-access= -- Used by InternetArchiveBot
['unfit'] = {'unfit'}, -- |url-status= -- Used by InternetArchiveBot
['usurped'] = {'usurped'}, -- |url-status= -- Used by InternetArchiveBot
['vanc'] = {'vanc'}, -- |name-list-style=
['ymd'] = {'ymd'}, -- |df=
['ymd-all'] = {'ymd-all'}, -- |df=
-- ['yMd'] = {'yMd'}, -- |df=; not supported at en.wiki
-- ['yMd-all'] = {'yMd-all'}, -- |df=; not supported at en.wiki
}
--[[------------------------< X L A T E _ K E Y W O R D S >---------------------
this function builds a list, keywords_xlate{}, of the keywords found in keywords{} where the values from keywords{}
become the keys in keywords_xlate{} and the keys from keywords{} become the values in keywords_xlate{}:
['affirmative'] = {'yes', 'true', 'y'}, -- in keywords{}
becomes
['yes'] = 'affirmative', -- in keywords_xlate{}
['true'] = 'affirmative',
['y'] = 'affirmative',
the purpose of this function is to act as a translator between a non-English keyword and its English equivalent
that may be used in other modules of this suite
]]
local function xlate_keywords ()
local out_table = {}; -- output goes here
for k, keywords_t in pairs (keywords) do -- spin through the keywords table
for _, keyword in ipairs (keywords_t) do -- for each keyword
out_table[keyword] = k; -- create an entry in the output table where keyword is the key
end
end
return out_table;
end
local keywords_xlate = xlate_keywords (); -- the list of translated keywords
--[[----------------< M A K E _ K E Y W O R D S _ L I S T >---------------------
this function assembles, for parameter-value validation, the list of keywords appropriate to that parameter.
keywords_lists{}, is a table of tables from keywords{}
]]
local function make_keywords_list (keywords_lists)
local out_table = {}; -- output goes here
for _, keyword_list in ipairs (keywords_lists) do -- spin through keywords_lists{} and get a table of keywords
for _, keyword in ipairs (keyword_list) do -- spin through keyword_list{} and add each keyword, ...
table.insert (out_table, keyword); -- ... as plain text, to the output list
end
end
return out_table;
end
--[[----------------< K E Y W O R D S _ L I S T S >-----------------------------
this is a list of lists of valid keywords for the various parameters in [key].
Generally the keys in this table are the canonical en.wiki parameter names though
some are contrived because of use in multiple differently named parameters:
['yes_true_y'], ['id-access'].
The function make_keywords_list() extracts the individual keywords from the
appropriate list in keywords{}.
The lists in this table are used to validate the keyword assignment for the
parameters named in this table's keys.
]]
local keywords_lists = {
['yes_true_y'] = make_keywords_list ({keywords.affirmative}),
['contribution'] = make_keywords_list ({keywords.afterword, keywords.foreword, keywords.introduction, keywords.preface}),
['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all']}),
-- ['df'] = make_keywords_list ({keywords.dmy, keywords['dmy-all'], keywords.mdy, keywords['mdy-all'], keywords.ymd, keywords['ymd-all'], keywords.yMd, keywords['yMd-all']}), -- not supported at en.wiki
['mode'] = make_keywords_list ({keywords.cs1, keywords.cs2}),
['name-list-style'] = make_keywords_list ({keywords.amp, keywords['and'], keywords.vanc}),
['ref'] = make_keywords_list ({keywords.harv}), -- inverted check; |ref=harv no longer supported
['url-access'] = make_keywords_list ({keywords.subscription, keywords.limited, keywords.registration}),
['url-status'] = make_keywords_list ({keywords.dead, keywords.live, keywords.unfit, keywords.usurped, keywords['bot: unknown']}),
['id-access'] = make_keywords_list ({keywords.free}),
}
--[[--------------------------< C S 1 _ C O N F I G _ G E T >--------------------------------------------------
fetch and validate values from {{cs1 config}} template to fill <global_cs1_config_t>
no error messages; when errors are detected, the parameter value from {{cs1 config}} is blanked.
Supports all parameters and aliases associated with the metaparameters: DisplayAuthors, DisplayContributors,
DisplayEditors, DisplayInterviewers, DisplayTranslators, NameListStyle, and Mode. The DisplayWhatever metaparameters
accept numeric values only (|display-authors=etal and the like is not supported).
]]
local global_cs1_config_t = {}; -- TODO: add value returned from get_date_format() to this table?
local function get_cs1_config ()
if not content then -- nil content when we're in template
return nil; -- auto-formatting does not work in Template space so don't set global_df
end
local start = content:find('{{ *[Cc][Ss]1 config *[|}]'); -- <start> is offset into <content> when {{cs1 config}} found; nil else
if start then
local cs1_config_template = content:match ('%b{}', start); -- get the whole template
if not cs1_config_template then
return nil;
end
local params_t = mw.text.split (cs1_config_template:gsub ('^{{%s*', ''):gsub ('%s*}}$', ''), '%s*|%s*'); -- remove '{{' and '}}'; make a sequence of parameter/value pairs (split on the pipe)
table.remove (params_t, 1); -- remove the template name because it isn't a parameter/value pair
local config_meta_params_t = {'DisplayAuthors', 'DisplayContributors', 'DisplayEditors', 'DisplayInterviewers', 'DisplayTranslators', 'NameListStyle', 'Mode'};
local meta_param_map_t = {}; -- list of accepted parameter names usable in {{cs1 config}} goes here
for _, meta_param in ipairs (config_meta_params_t) do -- for i18n using <config_meta_params_t>, map template parameter names to their metaparameter equivalents
if 'table' == type (aliases[meta_param]) then -- if <meta_param> is a sequence,
for _, param in ipairs (aliases[meta_param]) do -- extract its contents
meta_param_map_t[param] = meta_param; -- and add to <meta_param_map_t>
end
else
meta_param_map_t[aliases[meta_param]] = meta_param; -- not a sequence so just add the parameter to <meta_param_map_t>
end
end
local keywords_t = {}; -- map valid keywords to their associate metaparameter; reverse form of <keyword_lists[key] for these metaparameters
for _, metaparam_t in ipairs ({{'NameListStyle', 'name-list-style'}, {'Mode', 'mode'}}) do -- only these metaparameter / keywords_lists key pairs
for _, keyword in ipairs (keywords_lists[metaparam_t[2]]) do -- spin through the list of keywords
keywords_t[keyword] = metaparam_t[1]; -- add [keyword] = metaparameter to the map
end
end
for _, param in ipairs (params_t) do -- spin through the {{cs1 config}} parameters and fill <global_cs1_config_t>
local k, v = param:match ('([^=]-)%s*=%s*(.+)'); -- <k> is the parameter name; <v> is parameter's assigned value
if k then
if k:find ('^display') then -- if <k> is one of the |display-<namelist>= parameters
if v:match ('%d+') then -- the assigned value must be digits; doesn't accept 'etal'
global_cs1_config_t[meta_param_map_t[k]]=v; -- add the display param and its value to globals table
end
else
if keywords_t[v] == meta_param_map_t[k] then -- keywords_t[v] returns nil or the metaparam name; these must be the same
global_cs1_config_t[meta_param_map_t[k]]=v; -- add the parameter and its value to globals table
end
end
end
end
end
end
get_cs1_config (); -- fill <global_cs1_config_t>
--[[---------------------< S T R I P M A R K E R S >----------------------------
Common pattern definition location for stripmarkers so that we don't have to go
hunting for them if (when) MediaWiki changes their form.
]]
local stripmarkers = {
['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker
['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker()
}
--[[------------< I N V I S I B L E _ C H A R A C T E R S >---------------------
This table holds non-printing or invisible characters indexed either by name or
by Unicode group. Values are decimal representations of UTF-8 codes. The table
is organized as a table of tables because the Lua pairs keyword returns table
data in an arbitrary order. Here, we want to process the table from top to bottom
because the entries at the top of the table are also found in the ranges specified
by the entries at the bottom of the table.
Also here is a pattern that recognizes stripmarkers that begin and end with the
delete characters. The nowiki stripmarker is not an error but some others are
because the parameter values that include them become part of the template's
metadata before stripmarker replacement.
]]
local invisible_defs = {
del = '\127', -- used to distinguish between stripmarker and del char
zwj = '\226\128\141', -- used with capture because zwj may be allowed
}
local invisible_chars = {
{'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD
{'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed
{'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B
{'hair space', '\226\128\138'}, -- U+200A, E2 80 8A
{'soft hyphen', '\194\173'}, -- U+00AD, C2 AD
{'horizontal tab', '\009'}, -- U+0009 (HT), 09
{'line feed', '\010'}, -- U+000A (LF), 0A
{'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0
{'carriage return', '\013'}, -- U+000D (CR), 0D
{'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type
{'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker
{'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D))
{'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F
-- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF
-- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF
-- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD
-- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD
}
--[[
Indic script makes use of zero width joiner as a character modifier so zwj
characters must be left in. This pattern covers all of the unicode characters
for these languages:
Devanagari 0900–097F – https://unicode.org/charts/PDF/U0900.pdf
Devanagari extended A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf
Bengali 0980–09FF – https://unicode.org/charts/PDF/U0980.pdf
Gurmukhi 0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf
Gujarati 0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf
Oriya 0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf
Tamil 0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf
Telugu 0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf
Kannada 0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf
Malayalam 0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf
plus the not-necessarily Indic scripts for Sinhala and Burmese:
Sinhala 0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf
Myanmar 1000-109F - https://unicode.org/charts/PDF/U1000.pdf
Myanmar extended A AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf
Myanmar extended B A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf
the pattern is used by has_invisible_chars() and coins_cleanup()
]]
local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]';
-- list of emoji that use a zwj character (U+200D) to combine with another emoji
-- from: https://unicode.org/Public/emoji/17.0/emoji-zwj-sequences.txt; version: 17.0; 2025-01-08
-- table created by: [[:en:Module:Make emoji zwj table]]
local emoji_t = { -- indexes are decimal forms of the hex values in U+xxxx
[8596] = true, -- U+2194 ↔ left right arrow
[8597] = true, -- U+2195 ↕ up down arrow
[9760] = true, -- U+2620 ☠ skull and crossbones
[9792] = true, -- U+2640 ♀ female sign
[9794] = true, -- U+2642 ♂ male sign
[9877] = true, -- U+2695 ⚕ staff of aesculapius
[9878] = true, -- U+2696 ⚖ scales
[9895] = true, -- U+26A7 ⚧ male with stroke and male and female sign
[9992] = true, -- U+2708 ✈ airplane
[10052] = true, -- U+2744 ❄ snowflake
[10084] = true, -- U+2764 ❤ heavy black heart
[10145] = true, -- U+27A1 ➡ black rightwards arrow
[11035] = true, -- U+2B1B ⬛ black large square
[127752] = true, -- U+1F308 🌈 rainbow
[127787] = true, -- U+1F32B 🌫 fog
[127806] = true, -- U+1F33E 🌾 ear of rice
[127859] = true, -- U+1F373 🍳 cooking
[127868] = true, -- U+1F37C 🍼 baby bottle
[127876] = true, -- U+1F384 🎄 christmas tree
[127891] = true, -- U+1F393 🎓 graduation cap
[127908] = true, -- U+1F3A4 🎤 microphone
[127912] = true, -- U+1F3A8 🎨 artist palette
[127979] = true, -- U+1F3EB 🏫 school
[127981] = true, -- U+1F3ED 🏭 factory
[128048] = true, -- U+1F430 🐰 rabbit face
[128102] = true, -- U+1F466 👦 boy
[128103] = true, -- U+1F467 👧 girl
[128104] = true, -- U+1F468 👨 man
[128105] = true, -- U+1F469 👩 woman
[128139] = true, -- U+1F48B 💋 kiss mark
[128165] = true, -- U+1F4A5 💥 collision symbol
[128168] = true, -- U+1F4A8 💨 dash symbol
[128171] = true, -- U+1F4AB 💫 dizzy symbol
[128187] = true, -- U+1F4BB 💻 personal computer
[128188] = true, -- U+1F4BC 💼 brief case
[128293] = true, -- U+1F525 🔥 fire
[128295] = true, -- U+1F527 🔧 wrench
[128300] = true, -- U+1F52C 🔬 microscope
[128488] = true, -- U+1F5E8 🗨 left speech bubble
[128640] = true, -- U+1F680 🚀 rocket
[128658] = true, -- U+1F692 🚒 fire engine
[129001] = true, -- U+1F7E9 🟩 large green square
[129003] = true, -- U+1F7EB 🟫 large brown square
[129309] = true, -- U+1F91D 🤝 handshake
[129455] = true, -- U+1F9AF 🦯 probing cane
[129456] = true, -- U+1F9B0 🦰 emoji component red hair
[129457] = true, -- U+1F9B1 🦱 emoji component curly hair
[129458] = true, -- U+1F9B2 🦲 emoji component bald
[129459] = true, -- U+1F9B3 🦳 emoji component white hair
[129466] = true, -- U+1F9BA 🦺 safety vest
[129468] = true, -- U+1F9BC 🦼 motorized wheelchair
[129469] = true, -- U+1F9BD 🦽 manual wheelchair
[129489] = true, -- U+1F9D1 🧑 adult
[129490] = true, -- U+1F9D2 🧒 child
[129648] = true, -- U+1FA70 🩰 ballet shoes
[129657] = true, -- U+1FA79 🩹 adhesive bandage
[129775] = true, -- U+1FAEF fight cloud
[129778] = true, -- U+1FAF2 🫲 leftwards hand
}
--[[----------------------< L A N G U A G E S U P P O R T >-------------------
These tables and constants support various language-specific functionality.
]]
--local this_wiki_code = mw.getContentLanguage():getCode(); -- get this wiki's language code
local this_wiki_code = lang_obj:getCode(); -- get this wiki's language code
if string.match (mw.site.server, 'wikidata') then
this_wiki_code = mw.getCurrentFrame():callParserFunction('int', {'lang'}); -- on Wikidata so use interface language setting instead
end
local mw_languages_by_tag_t = mw.language.fetchLanguageNames (this_wiki_code, 'all'); -- get a table of language tag/name pairs known to Wikimedia; used for interwiki tests
local mw_languages_by_name_t = {};
for k, v in pairs (mw_languages_by_tag_t) do -- build a 'reversed' table name/tag language pairs know to MediaWiki; used for |language=
v = mw.ustring.lower (v); -- lowercase for tag fetch; get name's proper case from mw_languages_by_tag_t[<tag>]
if mw_languages_by_name_t[v] then -- when name already in the table
if 2 == #k or 3 == #k then -- if tag does not have subtags
mw_languages_by_name_t[v] = k; -- prefer the shortest tag for this name
end
else -- here when name not in the table
mw_languages_by_name_t[v] = k; -- so add name and matching tag
end
end
local inter_wiki_map = {}; -- map of interwiki prefixes that are language-code prefixes
for k, v in pairs (mw.site.interwikiMap ('local')) do -- spin through the base interwiki map (limited to local)
if mw_languages_by_tag_t[v["prefix"]] then -- if the prefix matches a known language tag
inter_wiki_map[v["prefix"]] = true; -- add it to our local map
end
end
--[[--------------------< S C R I P T _ L A N G _ C O D E S >-------------------
This table is used to hold ISO 639-1 two-character and ISO 639-3 three-character
language codes that apply only to |script-title= and |script-chapter=
]]
local script_lang_codes = {
'ab', 'am', 'ar', 'as', 'az', 'be', 'bg', 'bn', 'bo', 'bs', 'ce', 'chr',
'cu', 'dv', 'dz', 'el', 'fa', 'grc', 'gu', 'he', 'hi', 'hy', 'ja', 'ka',
'kaa', 'kk', 'km', 'kn', 'ko', 'ku', 'ky', 'lo', 'mk', 'ml', 'mn', 'mni',
'mr', 'my', 'ne', 'or', 'ota', 'pa', 'ps', 'ru', 'sd', 'si', 'sr', 'syc',
'ta', 'te', 'tg', 'th', 'ti', 'tkr', 'tt', 'ug', 'uk', 'ur', 'uz', 'yi',
'yue', 'zh', 'zgh'
};
--[[---------------< L A N G U A G E R E M A P P I N G >----------------------
These tables hold language information that is different (correct) from MediaWiki's definitions
For each ['<tag>'] = 'language name' in lang_code_remap{} there must be a matching ['language name'] = {'language name', '<tag>'} in lang_name_remap{}
lang_tag_remap{}:
key is always lowercase ISO 639-1, -2, -3 language tag or a valid lowercase IETF language tag
value is properly spelled and capitalized language name associated with <tag>
only one language name per <tag>;
key/value pair must have matching entry in lang_name_remap{}
lang_name_remap{}:
key is always lowercase language name
value is a table the holds correctly spelled and capitalized language name [1] and associated tag [2] (tag must match a tag key in lang_tag_remap{})
may have multiple keys referring to a common preferred name and tag; For example:
['kolsch'] and ['kölsch'] both refer to 'Kölsch' and 'ksh'
]]
local lang_tag_remap = { -- used for |language= and |script-title= / |script-chapter=
['als'] = 'Tosk Albanian', -- MediaWiki returns Alemannisch
['bh'] = 'Bihari', -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org
['bla'] = 'Blackfoot', -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name
['bn'] = 'Bengali', -- MediaWiki returns Bangla
['ca-valencia'] = 'Valencian', -- IETF variant of Catalan
['fkv'] = 'Kven', -- MediaWiki returns Kvensk
['gsw'] = 'Swiss German',
['ilo'] = 'Ilocano', -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name
['ksh'] = 'Kölsch', -- MediaWiki: Colognian; use IANA/ISO 639 preferred name
['ksh-x-colog'] = 'Colognian', -- override MediaWiki ksh; no IANA/ISO 639 code for Colognian; IETF private code created at Module:Lang/data
['mis-x-ripuar'] = 'Ripuarian', -- override MediaWiki ksh; no IANA/ISO 639 code for Ripuarian; IETF private code created at Module:Lang/data
['nan-tw'] = 'Taiwanese Hokkien', -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese and support en.wiki preferred name
['sr-ec'] = 'Serbian (Cyrillic script)', -- MediaWiki returns српски (ћирилица)
['sr-el'] = 'Serbian (Latin script)', -- MediaWiki returns srpski (latinica)
}
local lang_name_remap = { -- used for |language=; names require proper capitalization; tags must be lowercase
['alemannic'] = {'Swiss German', 'gsw'}, -- ISO 639-2, -3 alternate for Swiss German; MediaWiki mediawiki returns Alemannic for gsw; en.wiki preferred name
['alemannisch'] = {'Swiss German', 'gsw'}, -- not an ISO or IANA language name; MediaWiki uses 'als' as a subdomain name for Alemannic Wikipedia: als.wikipedia.org
['bangla'] = {'Bengali', 'bn'}, -- MediaWiki returns Bangla (the endonym) but we want Bengali (the exonym); here we remap
['bengali'] = {'Bengali', 'bn'}, -- MediaWiki doesn't use exonym so here we provide correct language name and 639-1 code
['bhojpuri'] = {'Bhojpuri', 'bho'}, -- MediaWiki uses 'bh' as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org
['bihari'] = {'Bihari', 'bh'}, -- MediaWiki replaces 'Bihari' with 'Bhojpuri' so 'Bihari' cannot be found
['blackfoot'] = {'Blackfoot', 'bla'}, -- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name
['colognian'] = {'Colognian', 'ksh-x-colog'}, -- MediaWiki preferred name for ksh
['ilocano'] = {'Ilocano', 'ilo'}, -- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name
['kolsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name (use non-diacritical o instead of umlaut ö)
['kölsch'] = {'Kölsch', 'ksh'}, -- use IANA/ISO 639 preferred name
['kven'] = {'Kven', 'fkv'}, -- Unicode CLDR have decided not to support English language name for these two...
['kvensk'] = {'Kven', 'fkv'}, -- ...they say to refer to IANA registry for English names
['ripuarian'] = {'Ripuarian', 'mis-x-ripuar'}, -- group of dialects; no code in MediaWiki or in IANA/ISO 639
['serbian (cyrillic script)'] = {'Serbian (Cyrillic script)', 'sr-cyrl'}, -- special case to get correct tag when |language=sr-ec
['serbian (latin script)'] = {'Serbian (Latin script)', 'sr-latn'}, -- special case to get correct tag when |language=sr-el
['swiss german'] = {'Swiss German', 'gsw'},
['taiwanese hokkien'] = {'Taiwanese Hokkien', 'nan-tw'}, -- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese
['tosk albanian'] = {'Tosk Albanian', 'als'}, -- MediaWiki replaces 'Tosk Albanian' with 'Alemannisch' so 'Tosk Albanian' cannot be found
['valencian'] = {'Valencian', 'ca-valencia'}, -- variant of Catalan; categorizes as Valencian
}
--[[---------------< P R O P E R T I E S _ C A T E G O R I E S >----------------
Properties categories. These are used for investigating qualities of citations.
]]
local prop_cats = {
['foreign-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is foreign-language name, $2 is ISO639-1 code
['foreign-lang-source-2'] = 'CS1 foreign language sources (ISO 639-2)|$1', -- |language= category; a cat for ISO639-2 languages; $1 is the ISO 639-2 code used as a sort key
['interproj-linked-name'] = 'CS1 interproject-linked names|$1', -- any author, editor, etc that has an interproject link; $1 is interproject tag used as a sort key
['interwiki-linked-name'] = 'CS1 interwiki-linked names|$1', -- any author, editor, etc that has an interwiki link; $1 is interwiki tag used as a sort key; yeilds to interproject
['local-lang-source'] = 'CS1 $1-language sources ($2)', -- |language= categories; $1 is local-language name, $2 is ISO639-1 code; not emitted when local_lang_cat_enable is false
['location-test'] = 'CS1 location test',
['long-vol'] = 'CS1: long volume value', -- probably temporary cat to identify scope of |volume= values longer than 4 characters
['script'] = 'CS1 uses $1-language script ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is language tag
['tracked-param'] = 'CS1 tracked parameter: $1', -- $1 is base (enumerators removed) parameter name
['unfit'] = 'CS1: unfit URL', -- |url-status=unfit or |url-status=usurped; used to be a maint cat
['vanc-accept'] = 'CS1:Vancouver names with accept markup', -- for |vauthors=/|veditors= with accept-as-written markup
['year-range-abbreviated'] = 'CS1: abbreviated year range', -- probably temporary cat to identify scope of |date=, |year= values using YYYY–YY form
}
--[[-------------------< T I T L E _ T Y P E S >--------------------------------
Here we map a template's CitationClass to TitleType (default values for |type= parameter)
]]
local title_types = {
['AV-media-notes'] = 'Media notes',
['document'] = 'Document',
['interview'] = 'Interview',
['mailinglist'] = 'Mailing list',
['map'] = 'Map',
['podcast'] = 'Podcast',
['pressrelease'] = 'Press release',
['report'] = 'Report',
['speech'] = 'Speech',
['techreport'] = 'Technical report',
['thesis'] = 'Thesis',
}
--[[--------------------------< B U I L D _ K N O W N _ F R E E _ D O I _ R E G I S T R A N T S _ T A B L E >--
build a table of doi registrants known to be free-to-read In a doi, the registrant ID is the series of digits
between the '10.' and the first '/': in doi 10.1100/sommat, 1100 is the registrant ID
see §3.2.2 DOI prefix of the Doi Handbook p. 43
https://www.doi.org/doi-handbook/DOI_Handbook_Final.pdf#page=43
]]
local function build_free_doi_registrants_table()
local registrants_t = {};
for _, v in ipairs ({
'1045', '1074', '1096', '1100', '1155', '1186', '1194', '1371', '1613', '1629', '1989', '1999', '2147', '2196', '3114', '3285',
'3389', '3390', '3767', '3906', '3748', '3814', '3847', '3897', '4061', '4089', '4103', '4172', '4175', '4230', '4236', '4239',
'4240', '4249', '4251', '4252', '4253', '4254', '4291', '4292', '4312', '4329', '4330', '4331', '5074', '5086', '5194',
'5210', '5306', '5312', '5313', '5314', '5315', '5316', '5317', '5318', '5319', '5320', '5321', '5334', '5402', '5409',
'5410', '5411', '5412', '5492', '5493', '5494', '5495', '5496', '5497', '5498', '5499', '5500', '5501', '5527', '5528',
'5662', '6064', '6219', '7167', '7217', '7287', '7482', '7490', '7554', '7717', '7759', '7766', '9778',
'11131', '11569', '11647', '11648', '12688', '12703', '12715', '12942', '12998', '13105', '14256', '14293', '14303', '14502', '14720',
'15215', '15227', '15292', '15458', '15347', '15412', '15560', '16995', '17573', '17645', '18553', '18637', '18757', '19080', '19173', '20419',
'20944', '21037', '21105', '21468', '21767', '21425', '22261', '22323', '22459', '24105', '24196', '24404', '24413', '24966', '26529',
'26614', '26775', '26873', '30845', '32545', '34291', '34641', '35711', '35712', '35713', '35995', '36648', '37126', '37532', '37871',
'47128', '47622', '47959', '48438', '51741', '51746', '51935', '51936', '51937', '51938', '51939', '51940', '52165', '52437', '52975',
'53288', '53347', '54081', '54947', '55295', '55667', '55741', '55914', '57009', '58647', '58782', '59081', '59490', '61375', '66183', '70587',
}) do
registrants_t[v] = true; -- build a k/v table of known free-to-read doi registrants
end
return registrants_t;
end
-- known free registrants identifiable by the doi suffix incipit
local extended_registrants_t = { -- doi suffix incipits are evaluated as lua patterns
['1001'] = {'jamanetworkopen'}, -- JAMA Network Open
['1002'] = {'1878-0261', '2056-4538', '2211-5463', '2475-8876', '2688-8319', 'aaai%.', 'aac2%.', 'ache%.', 'acm2%.', 'acn3%.', 'acr2%.', 'admi%.', 'adpr%.', 'adrr%.', 'adsr%.', 'advs%.', 'ael2%.', 'aelm%.', 'aesr%.', 'aff2%.', 'agf2%.', 'agg2%.', 'agm2%.', 'ags3%.', 'agt2%.', 'aidi%.', 'ail2%.', 'aisy%.', 'aiv2%.', 'alz%.', 'ame2%.', 'ams2%.', 'anbr%.', 'ansa%.', 'apj%.', 'app5%.', 'aps3%.', 'apxr%.', 'aro2%.', 'ars2%.', 'asl2%.', 'atn2%.', 'bco2%.', 'bes2%.', 'bmm2%.', 'bod2%.', 'brb3%.', 'brh2%.', 'brx2%.', 'bsa3%.', 'bte2%.', 'btm2%.', 'cai2%.', 'cam4%.', 'cbh2%.', 'ccr3%.', 'ccs3%.', 'cdt3%.', 'celc%.', 'cep4%.', 'ces2%.', 'cesm%.', 'ceur%.', 'cey2%.', 'cfch%.', 'cfp2%.', 'cin4%.', 'clc%.', 'clem%.', 'cli2%.', 'clt2%.', 'cmt2%.', 'cmtd%.', 'cnl2%.', 'cnr2%.', 'cns%.', 'cns3%.', 'cnx2%.', 'cre2%.', 'csc3%.', 'cso2%.', 'ctd2%.', 'cti2%.', 'ctm2%.', 'dad2%.', 'deo2%.', 'dep2%.', 'dni2%.', 'dro2%.', 'dug2%.', 'dvr2%.', 'eas2%.', 'ece2%.', 'ece3%.', 'ecog%.', 'ecs2%.', 'edm2%.', 'edn3%.', 'eem2%.', 'eer3%.', 'efd2%.', 'ejsc%.', 'elsa%.', 'elt2%.', 'eng2%.', 'eom2%.', 'epi4%.', 'epr2%.', 'ese3%.', 'exp%.', 'fbe2%.', 'fci2%.', 'fer3%.', 'fes3%.', 'fft2%.', 'fhu2%.', 'fle2%.', 'flm2%.', 'fob2%.', 'fpf2%.', 'fsh3%.', 'fsn3%.', 'gcb4%.', 'gch2%.', 'gdj3%.', 'geo2%.', 'ggn2%.', 'gin2%.', 'glr2%.', 'gps3%.', 'gtm2%.', 'hbm%.', 'hcs2%.', 'hem3%.', 'hkj2%.', 'hsr2%.', 'ibra%.', 'idm2%.', 'ifm2%.', 'iid3%.', 'iju5%.', 'ila2%.', 'imed%.', 'imm3%.', 'imo2%.', 'imt2%.', 'inc2%.', 'inc3%.', 'inf2%.', 'inm3%.', 'inmd%.', 'ird3%.', 'ise3%.', 'jaa2%.', 'jav%.', 'jbt%.', 'jcc5%.', 'jcla%.', 'jcsm%.', 'jcv2%.', 'jeo2%.', 'jev2%.', 'jex2%.', 'jfa2%.', 'jgf2%.', 'jgh3%.', 'jha2%.', 'jia2%.', 'jmd2%.', 'jmrs%.', 'joa3%.', 'jpr3%.', 'jsf2%.', 'jsp2%.', 'jvc2%.', 'kjm2%.', 'kot2%.', 'lci2%.', 'ldr%.', 'leap%.', 'leg3%.', 'lim2%.', 'lio2%.', 'loe2%.', 'lol2%.', 'lrh2%.', 'mame%.', 'mba2%.', 'mbo3%.', 'mco2%.', 'mdb2%.', 'mdr2%.', 'med4%.', 'mef2%.', 'met%.', 'metm%.', 'mgea%.', 'mgg3%.', 'mhs2%.', 'mlf2%.', 'mmr3%.', 'moda%.', 'mog2%.', 'mpr%.', 'mps2%.', 'msd2%.', 'nam2%.', 'nano%.', 'nap2%.', 'neo2%.', 'nep3%.', 'njb%.', 'nop2%.', 'npp2%.', 'npr2%.', 'ntls%.', 'open%.', 'orm2%.', 'osp4%.', 'oto2%.', 'pan3%.', 'pchj%.', 'pcn5%.', 'pdi3%.', 'ped4%.', 'pei3%.', 'pfm2%.', 'pgr2%.', 'phmt%.', 'pld3%.', 'pls2%.', 'pmf2%.', 'pne2%.', 'pnp%.', 'poh2%.', 'ppj2%.', 'ppp3%.', 'prm2%.', 'pro6%.', 'prp2%.', 'psp4%.', 'puh2%.', 'pul2%.', 'qub2%.', 'rai2%.', 'rar2%.', 'rco2%.', 'rcr2%.', 'rfc2%.', 'rmb2%.', 'rpm2%.', 'rse2%.', 'rvr2%.', 'sae2%.', 'sen2%.', 'sfp2%.', 'smb2%.', 'smm2%.', 'smmd%.', 'smo2%.', 'smsc%.', 'sst2%.', 'sst3%.', 'sstr%.', 'sus2%.', 'tch2%.', 'tcr4%.', 'tpg2%.', 'trc2%.', 'tre%.', 'uar2%.', 'ueg2%.', 'uro2%.', 'viw2%.', 'vms3%.', 'vro2%.', 'vzj2%.', 'we%.', 'wjo2%.', 'wlb3%.', 'wll2%.', 'wsb%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1016'] = {'j%.aace', 'j%.aed', 'j%.aiopen', 'j%.animal', 'j%.apsb', 'j%.addicn', -- AACE Endocrinology and Diabetes, AACE Endocrinology and Diabetes, AI Open, Animal, Acta Pharmaceutica Sinica B, Addiction Neuroscience
'j%.abrep', 'j%.fob', 'j%.gpb', 'j%.heliyon', 'j%.mucimm%.', 'j%.nlp', 'j%.patter', 'j%.proche', -- Addictive Behaviors Reports, FEBS Open Bio, Genomics, Proteomics & Bioinformatics after 2015, Heliyon, Mucosal Immunology, Natural Language Processing, Patterns, Procedia Chemistry
'j%.vgie', 'S1672-0229', 'S1933-0219'}, -- VideoGIE, Genomics, Proteomics & Bioinformatics before 2015, Mucosal Immunology
['1017'] = {'apj%.', 'nlp', 'mdh', 'S15574660'}, -- Natural Language Processing Journal, Medical History, Asia Pacific Journal
['1021'] = {'acscentsci', 'acsomega'}, -- ACS Central Science, ACS Omega
['1029'] = {'2025cn', '2025csj', '2025ea', '2025gc', '2025gh', '2025ms', '2025sw', '2025wr', '2026ef', '2026gl', '2026jh', 'aga2.70129'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1038'] = {'41541%.', '43246%.', 'asiamat%.', 'boneres%.', 'cddis%.', 'cddiscovery%.', 'celldisc%.', 'mi%.', 'nutd%.', 'oncsis%.', 's40494', 's41377', 's41392', 's41396', 's41398', 's41405', 's41407', 's41408', 's41439', 's41467', 's41514', 's41522', 's41523', 's41524', 's41525', 's41526', 's41528', 's41529', 's41531', 's41533', 's41534', 's41535', 's41536', 's41537', 's41538', 's41539', 's41540', 's41545', 's41598', 's41612', 's41698', 's41699', 's41746', 's42003', 's42004', 's42005', 's42949', 's43247', 's43705', 's43856', 's44168', 's44172', 's44182', 's44183', 's44184', 's44185', 's44259', 's44260', 's44264', 's44271', 's44276', 's44294', 's44296', 's44298', 's44303', 's44304', 's44306', 's44310', 's44323', 's44324', 's44325', 's44328', 's44333', 's44334', 's44335', 's44341', 's44355', 's44383', 's44384', 's44385', 's44386', 's44387', 's44400', 's44401', 's44406', 's44407', 's44431', 's44432', 's44433', 's44434', 's44435', 's44440', 's44453', 's44454', 's44455', 's44456', 's44458', 's44459', 's44482', 's44484', 's44485', 's44488', 's44513', 's44528', 'sdata%.'}, -- Nature journals (npj series, Communications series, and many others, see https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&diff=prev&oldid=1368822567 and https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&diff=next&oldid=1368822567)
['1046'] = {'j%.1365-8711', 'j%.1365-246x'}, -- MNRAS, GJI
['1049'] = {'aie2%.', 'blc2%.', 'bme2', 'bsb2%.', 'ccs2%.', 'cds2', 'cdt2', 'cim2%.', 'cit2%.', 'cmu2%.', 'cps2%.', 'csy2%.', 'cth2%.', 'cvi2%.', 'dgt2%.', 'ein2%.', 'ell2%.', 'elp2%.', 'els2', 'ema3%.', 'enb2%.', 'enc2%.', 'esi2%.', 'gtd2%.', 'htl2%.', 'hve2%.', 'ipr2%.', 'ise2', 'itr2%.', 'mia2%.', 'mna2%.', 'nbt2', 'nde2%.', 'ntw2%.', 'ote2%.', 'pel2%.', 'qtc2%.', 'rpg2%.', 'rsn2%.', 'ses2%.', 'sfw2', 'sil2', 'smc2%.', 'smt2%.', 'stg2%.', 'syb2%.', 'tje2%.', 'wss2%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1051'] = {'parasite'}, -- Parasite
['1057'] = {'s41599'}, -- Humanities and Social Sciences Communications
['1093'] = {'mnras', 'mnrasl', 'gji', 'pnasnexus', 'rasti', 'ismeco', 'ismejo'}, -- MNRAS, MNRAS Letters, GJI, PNAS Nexus, RASTI, ISME Communications, ISME Journal
['1096'] = {'fba%.'}, -- FASEB BioAdvances
['1098'] = {'rsbm', 'rsob', 'rsos'}, -- Biographical Memoirs of Fellows of the Royal Society, Open Biology, Royal Society Open Science
['1099'] = {'acmi', 'mic', '00221287', 'mgen'}, -- Access Microbiology, Microbiology, Journal of General Microbiology, Microbial Genomics
['1107'] = {'S20569890', 'S20522525', 'S16005775', 'S24143146'}, -- Acta Crystallographica E, IUCrJ, Journal of Synchrotron Radiation, IUCrData
['1109'] = {'access', 'oa', 'oj'}, -- IEEE Access, IEEE Open Access..., IEEE Open Journal...
['1111'] = {'1365-2435', '1442-1984', '1751-7915', '1753-0407', '1755-0998', '1758-2229', '1759-7714', '2041-210x', 'j%.1365-2966', 'j%.1745-3933', 'j%.1365-246X','acel%.', 'adb%.', 'anec%.', 'aogs%.', 'bor%.', 'bpa%.', 'cas%.', 'con4%.', 'cpr%.', 'crj%.', 'csp2%.', 'cts%.', 'ddi%.', 'ejed%.', 'ene%.', 'eva%.', 'gbb%.', 'gcbb%.', 'hex%.', 'irv%.', 'iwj%.', 'jch%.', 'jcmm%.', 'jdi%.', 'jfr3%.', 'jocd%.', 'jwas%.', 'mcn%.', 'mpp%.', 'myc%.', 'nrm%.', 'os%.', 'pbi%.', 'srt%.'}, -- Elsevier journals https://en.wikipedia.org/w/index.php?title=User_talk:DreamRimmer&oldid=1364310578#Wikipedia:Bot_requests/Archive_88#Web_scrapping_v2
['1112'] = {'tlm3%.'}, -- Transactions of the London Mathematical Society
['1113'] = {'ep'}, -- Experimental Physiology
['1128'] = {'asmcr', 'jmbe', 'mbio', 'mra', 'spectrum', 'msphere', 'msystems'}, --ASM Case Reports, Journal of Microbiology & Biology Education, mBio, Microbiology Resource Announcements, Microbiology Spectrum, mSphere, mSystems
['1136'] = {'bmjopen'}, -- BMJ Open
['1140'] = {'epjconf'}, -- EPJ Web of Conferences
['1161'] = {'jaha%.'},
['1176'] = {'appi%.prcp%.'},
['1192'] = {'bjo'}, -- BJPsych Open
['1210'] = {'jendso','jcemcr'}, -- Journal of the Endocrine Society, JCEM Case Reports
['1215'] = {'21573689', '21573698'}, -- L&O Fluids
['1257'] = {'jep'}, -- Journal of Economic Perspectives
['1590'] = {'0102-3306'}, -- Acta Botanica Brasilica
['2903'] = {'j%.efsa%.'},
['3322'] = {'caac%.'},
['3982'] = {'qw', 'te'},
['4171'] = {'dm','mag'}, -- Documenta Mathematica, EMS Magazine
['4319'] = {'lo%.', 'lol%.', 'lom%.'}, -- L&O, L&O e-Lectures, L&O Methods
['5852'] = {'ejt'}, -- European Journal of Taxonomy
['7155'] = {'jgaa'}, -- Journal of Graph Algorithms and Applications
['7758'] = {'rsf'}, -- RSJ Journal
['11158'] = {'saasp'}, -- Systematic and Applied Acarology Special Publications
['11646'] = {'megataxa', 'mesozoic'}, -- Megataxa, Mesozoic
['14231'] = {'ag'}, -- Algebraic Geometry
['14814'] = {'phy2%.'},
['15302'] = {'vr%.'},
['15446'] = {'abc'}, -- Acta Biológica Colombiana
['17239'] = {'jowr'}, -- Journal of Writing Research
['22073'] = {'pja'}, -- Persian Journal of Acarology
['24310'] = {'abm'}, -- Acta Botanica Malacitana
['24425'] = {'agp'}, -- Acta Geologica Polonica
['35249'] = {'rche'}, -- Revista Chilena de Entomología
['37520'] = {'fi'}, -- Fossil Imprint
['53562'] = {'ajcb'} -- Asian Journal of Conservation Biology
}
--[[===================<< E R R O R M E S S A G I N G >>======================
]]
--[[----------< E R R O R M E S S A G E S U P P L E M E N T S >-------------
I18N for those messages that are supplemented with additional specific text that
describes the reason for the error
TODO: merge this with special_case_translations{}?
]]
local err_msg_supl = {
['char'] = 'invalid character', -- |isbn=, |sbn=
['check'] = 'checksum', -- |isbn=, |sbn=
empty_str = '(empty string)', -- empty unknown parameter check when cite has |=
['flag'] = 'flag', -- |archive-url=
['form'] = 'invalid form', -- |isbn=, |sbn=
['group'] = 'invalid group id', -- |isbn=
['initials'] = 'initials', -- Vancouver
['invalid language code'] = 'invalid language code', -- |script-<param>=
['journal'] = 'journal', -- |bibcode=
['length'] = 'length', -- |isbn=, |bibcode=, |sbn=
['liveweb'] = 'liveweb', -- |archive-url=
['missing comma'] = 'missing comma', -- Vancouver
['missing prefix'] = 'missing prefix', -- |script-<param>=
['missing title part'] = 'missing title part', -- |script-<param>=
['name'] = 'name', -- Vancouver
['non-Latin char'] = 'non-Latin character', -- Vancouver
['path'] = 'path', -- |archive-url=
['prefix'] = 'invalid prefix', -- |isbn=
['punctuation'] = 'punctuation', -- Vancouver
['save'] = 'save command', -- |archive-url=
['suffix'] = 'suffix', -- Vancouver
['timestamp'] = 'timestamp', -- |archive-url=
['unknown language code'] = 'unknown language code', -- |script-<param>=
['value'] = 'value', -- |bibcode=
['year'] = 'year', -- |bibcode=
}
--[[--------------< E R R O R _ C O N D I T I O N S >---------------------------
Error condition table. This table has two sections: errors at the top, maintenance
at the bottom. Maint 'messaging' does not have a 'message' (message=nil)
The following contains a list of IDs for various error conditions defined in the
code. For each ID, we specify a text message to display, an error category to
include, and whether the error message should be wrapped as a hidden comment.
Anchor changes require identical changes to matching anchor in Help:CS1 errors
TODO: rename error_conditions{} to something more generic; create separate error
and maint tables inside that?
]]
local error_conditions = {
err_accessdate_missing_url = {
message = '<code class="cs1-code">|access-date=</code> requires <code class="cs1-code">|url=</code>',
anchor = 'accessdate_missing_url',
category = 'CS1 errors: access-date without URL',
hidden = false
},
err_apostrophe_markup = {
message = 'Italic or bold markup not allowed in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'apostrophe_markup',
category = 'CS1 errors: markup',
hidden = false
},
err_archive_date_missing_url = {
message = '<code class="cs1-code">|archive-date=</code> requires <code class="cs1-code">|archive-url=</code>',
anchor = 'archive_date_missing_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_date_url_ts_mismatch = {
message = '<code class="cs1-code">|archive-date=</code> / <code class="cs1-code">|archive-url=</code> timestamp mismatch; $1 suggested',
anchor = 'archive_date_url_ts_mismatch',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_missing_date = {
message = '<code class="cs1-code">|archive-url=</code> requires <code class="cs1-code">|archive-date=</code>',
anchor = 'archive_missing_date',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_missing_url = {
message = '<code class="cs1-code">|archive-url=</code> requires <code class="cs1-code">|url=</code>',
anchor = 'archive_missing_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_archive_url = {
message = '<code class="cs1-code">|archive-url=</code> is malformed: $1', -- $1 is error message detail
anchor = 'archive_url',
category = 'CS1 errors: archive-url',
hidden = false
},
err_arxiv_missing = {
message = '<code class="cs1-code">|arxiv=</code> required',
anchor = 'arxiv_missing',
category = 'CS1 errors: arXiv', -- same as bad arxiv
hidden = false
},
err_asintld_missing_asin = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|asin=</code>', -- $1 is parameter name
anchor = 'asintld_missing_asin',
category = 'CS1 errors: ASIN TLD',
hidden = false
},
err_bad_arxiv = {
message = 'Check <code class="cs1-code">|arxiv=</code> value',
anchor = 'bad_arxiv',
category = 'CS1 errors: arXiv',
hidden = false
},
err_bad_asin = {
message = 'Check <code class="cs1-code">|asin=</code> value',
anchor = 'bad_asin',
category ='CS1 errors: ASIN',
hidden = false
},
err_bad_asin_tld = {
message = 'Check <code class="cs1-code">|asin-tld=</code> value',
anchor = 'bad_asin_tld',
category ='CS1 errors: ASIN TLD',
hidden = false
},
err_bad_bibcode = {
message = 'Check <code class="cs1-code">|bibcode=</code> $1', -- $1 is error message detail
anchor = 'bad_bibcode',
category = 'CS1 errors: bibcode',
hidden = false
},
err_bad_biorxiv = {
message = 'Check <code class="cs1-code">|biorxiv=</code> value',
anchor = 'bad_biorxiv',
category = 'CS1 errors: bioRxiv',
hidden = false
},
err_bad_citeseerx = {
message = 'Check <code class="cs1-code">|citeseerx=</code> value',
anchor = 'bad_citeseerx',
category = 'CS1 errors: citeseerx',
hidden = false
},
err_bad_date = {
message = 'Check date values in: $1', -- $1 is a parameter name list
anchor = 'bad_date',
category = 'CS1 errors: dates',
hidden = false
},
err_bad_doi = {
message = 'Check <code class="cs1-code">|doi=</code> value',
anchor = 'bad_doi',
category = 'CS1 errors: DOI',
hidden = false
},
err_bad_hdl = {
message = 'Check <code class="cs1-code">|hdl=</code> value',
anchor = 'bad_hdl',
category = 'CS1 errors: HDL',
hidden = false
},
err_bad_isbn = {
message = 'Check <code class="cs1-code">|isbn=</code> value: $1', -- $1 is error message detail
anchor = 'bad_isbn',
category = 'CS1 errors: ISBN',
hidden = false
},
err_bad_ismn = {
message = 'Check <code class="cs1-code">|ismn=</code> value',
anchor = 'bad_ismn',
category = 'CS1 errors: ISMN',
hidden = false
},
err_bad_issn = {
message = 'Check <code class="cs1-code">|$1issn=</code> value', -- $1 is 'e' or '' for eissn or issn
anchor = 'bad_issn',
category = 'CS1 errors: ISSN',
hidden = false
},
err_bad_jfm = {
message = 'Check <code class="cs1-code">|jfm=</code> value',
anchor = 'bad_jfm',
category = 'CS1 errors: JFM',
hidden = false
},
err_bad_jstor = {
message = 'Check <code class="cs1-code">|jstor=</code> value',
anchor = 'bad_jstor',
category = 'CS1 errors: JSTOR',
hidden = false
},
err_bad_lccn = {
message = 'Check <code class="cs1-code">|lccn=</code> value',
anchor = 'bad_lccn',
category = 'CS1 errors: LCCN',
hidden = false
},
err_bad_medrxiv = {
message = 'Check <code class="cs1-code">|medrxiv=</code> value',
anchor = 'bad_medrxiv',
category = 'CS1 errors: medRxiv',
hidden = false
},
err_bad_mr = {
message = 'Check <code class="cs1-code">|mr=</code> value',
anchor = 'bad_mr',
category = 'CS1 errors: MR',
hidden = false
},
err_bad_oclc = {
message = 'Check <code class="cs1-code">|oclc=</code> value',
anchor = 'bad_oclc',
category = 'CS1 errors: OCLC',
hidden = false
},
err_bad_ol = {
message = 'Check <code class="cs1-code">|ol=</code> value',
anchor = 'bad_ol',
category = 'CS1 errors: OL',
hidden = false
},
err_bad_osti = {
message = 'Check <code class="cs1-code">|osti=</code> value',
anchor = 'bad_osti',
category = 'CS1 errors: OSTI',
hidden = false
},
err_bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link=
message = 'Check <code class="cs1-code">|$1=</code> value', -- $1 is parameter name
anchor = 'bad_paramlink',
category = 'CS1 errors: parameter link',
hidden = false
},
err_bad_pmc = {
message = 'Check <code class="cs1-code">|pmc=</code> value',
anchor = 'bad_pmc',
category = 'CS1 errors: PMC',
hidden = false
},
err_bad_pmid = {
message = 'Check <code class="cs1-code">|pmid=</code> value',
anchor = 'bad_pmid',
category = 'CS1 errors: PMID',
hidden = false
},
err_bad_rfc = {
message = 'Check <code class="cs1-code">|rfc=</code> value',
anchor = 'bad_rfc',
category = 'CS1 errors: RFC',
hidden = false
},
err_bad_s2cid = {
message = 'Check <code class="cs1-code">|s2cid=</code> value',
anchor = 'bad_s2cid',
category = 'CS1 errors: S2CID',
hidden = false
},
err_bad_sbn = {
message = 'Check <code class="cs1-code">|sbn=</code> value: $1', -- $1 is error message detail
anchor = 'bad_sbn',
category = 'CS1 errors: SBN',
hidden = false
},
err_bad_ssrn = {
message = 'Check <code class="cs1-code">|ssrn=</code> value',
anchor = 'bad_ssrn',
category = 'CS1 errors: SSRN',
hidden = false
},
err_bad_url = {
message = 'Check $1 value', -- $1 is parameter name
anchor = 'bad_url',
category = 'CS1 errors: URL',
hidden = false
},
err_bad_usenet_id = {
message = 'Check <code class="cs1-code">|message-id=</code> value',
anchor = 'bad_message_id',
category = 'CS1 errors: message-id',
hidden = false
},
err_bad_zbl = {
message = 'Check <code class="cs1-code">|zbl=</code> value',
anchor = 'bad_zbl',
category = 'CS1 errors: Zbl',
hidden = false
},
err_bare_url_missing_title = {
message = '$1 missing title', -- $1 is parameter name
anchor = 'bare_url_missing_title',
category = 'CS1 errors: bare URL',
hidden = false
},
err_biorxiv_missing = {
message = '<code class="cs1-code">|biorxiv=</code> required',
anchor = 'biorxiv_missing',
category = 'CS1 errors: bioRxiv', -- same as bad bioRxiv
hidden = false
},
err_chapter_ignored = {
message = '<code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'chapter_ignored',
category = 'CS1 errors: chapter ignored',
hidden = false
},
err_citation_missing_title = {
message = 'Missing or empty <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'citation_missing_title',
category = 'CS1 errors: missing title',
hidden = false
},
err_citeseerx_missing = {
message = '<code class="cs1-code">|citeseerx=</code> required',
anchor = 'citeseerx_missing',
category = 'CS1 errors: citeseerx', -- same as bad citeseerx
hidden = false
},
err_cite_web_url = { -- this error applies to cite web and to cite podcast
message = 'Missing or empty <code class="cs1-code">|url=</code>',
anchor = 'cite_web_url',
category = 'CS1 errors: requires URL',
hidden = false
},
err_class_ignored = {
message = '<code class="cs1-code">|class=</code> ignored',
anchor = 'class_ignored',
category = 'CS1 errors: class',
hidden = false
},
err_contributor_ignored = {
message = '<code class="cs1-code">|contributor=</code> ignored',
anchor = 'contributor_ignored',
category = 'CS1 errors: contributor',
hidden = false
},
err_contributor_missing_required_param = {
message = '<code class="cs1-code">|contributor=</code> requires <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'contributor_missing_required_param',
category = 'CS1 errors: contributor',
hidden = false
},
err_deprecated_params = {
message = 'Cite uses deprecated parameter <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'deprecated_params',
category = 'CS1 errors: deprecated parameters',
hidden = false
},
err_disp_name = {
message = 'Invalid <code class="cs1-code">|$1=$2</code>', -- $1 is parameter name; $2 is the assigned value
anchor = 'disp_name',
category = 'CS1 errors: display-names',
hidden = false,
},
err_doibroken_missing_doi = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|doi=</code>', -- $1 is parameter name
anchor = 'doibroken_missing_doi',
category = 'CS1 errors: DOI',
hidden = false
},
err_embargo_missing_pmc = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|pmc=</code>', -- $1 is parameter name
anchor = 'embargo_missing_pmc',
category = 'CS1 errors: PMC embargo',
hidden = false
},
err_empty_citation = {
message = 'Empty citation',
anchor = 'empty_citation',
category = 'CS1 errors: empty citation',
hidden = false
},
err_etal = {
message = 'Explicit use of et al. in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'explicit_et_al',
category = 'CS1 errors: explicit use of et al.',
hidden = false
},
err_extra_text_edition = {
message = '<code class="cs1-code">|edition=</code> has extra text',
anchor = 'extra_text_edition',
category = 'CS1 errors: extra text: edition',
hidden = false,
},
err_extra_text_issue = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_issue',
category = 'CS1 errors: extra text: issue',
hidden = false,
},
err_extra_text_pages = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_pages',
category = 'CS1 errors: extra text: pages',
hidden = false,
},
err_extra_text_volume = {
message = '<code class="cs1-code">|$1=</code> has extra text', -- $1 is parameter name
anchor = 'extra_text_volume',
category = 'CS1 errors: extra text: volume',
hidden = false,
},
err_first_missing_last = {
message = '<code class="cs1-code">|$1=</code> missing <code class="cs1-code">|$2=</code>', -- $1 is first alias, $2 is matching last alias
anchor = 'first_missing_last',
category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator
hidden = false
},
err_format_missing_url = {
message = '<code class="cs1-code">|$1=</code> requires <code class="cs1-code">|$2=</code>', -- $1 is format parameter $2 is url parameter
anchor = 'format_missing_url',
category = 'CS1 errors: format without URL',
hidden = false
},
err_generic_name = {
message = '<code class="cs1-code">|$1=</code> has generic name', -- $1 is parameter name
anchor = 'generic_name',
category = 'CS1 errors: generic name',
hidden = false,
},
err_generic_title = {
message = 'Cite uses generic title',
anchor = 'generic_title',
category = 'CS1 errors: generic title',
hidden = false,
},
err_invalid_isbn_date = {
message = 'ISBN / Date incompatibility',
anchor = 'invalid_isbn_date',
category = 'CS1 errors: ISBN date',
hidden = true
},
err_invalid_param_val = {
message = 'Invalid <code class="cs1-code">|$1=$2</code>', -- $1 is parameter name $2 is parameter value
anchor = 'invalid_param_val',
category = 'CS1 errors: invalid parameter value',
hidden = false
},
err_invisible_char = {
message = '$1 in $2 at position $3', -- $1 is invisible char $2 is parameter name $3 is position number
anchor = 'invisible_char',
category = 'CS1 errors: invisible characters',
hidden = false
},
err_medrxiv_missing = {
message = '<code class="cs1-code">|medrxiv=</code> required',
anchor = 'medrxiv_missing',
category = 'CS1 errors: medRxiv', -- same as bad medRxiv
hidden = false
},
err_missing_name = {
message = 'Missing <code class="cs1-code">|$1$2=</code>', -- $1 is modified NameList; $2 is enumerator
anchor = 'missing_name',
category = 'CS1 errors: missing name', -- author, contributor, editor, interviewer, translator
hidden = false
},
err_missing_periodical = {
message = 'Cite $1 requires <code class="cs1-code">|$2=</code>', -- $1 is cs1 template name; $2 is canonical periodical parameter name for cite $1
anchor = 'missing_periodical',
category = 'CS1 errors: missing periodical',
hidden = false
},
err_missing_pipe = {
message = 'Missing pipe in: <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'missing_pipe',
category = 'CS1 errors: missing pipe',
hidden = false
},
err_missing_publisher = {
message = 'Cite $1 requires <code class="cs1-code">|$2=</code>', -- $1 is cs1 template name; $2 is canonical publisher parameter name for cite $1
anchor = 'missing_publisher',
category = 'CS1 errors: missing publisher',
hidden = false
},
err_numeric_names = {
message = '<code class="cs1-code">|$1=</code> has numeric name', -- $1 is parameter name',
anchor = 'numeric_names',
category = 'CS1 errors: numeric name',
hidden = false,
},
err_param_access_requires_param = {
message = '<code class="cs1-code">|$1-access=</code> requires <code class="cs1-code">|$1=</code>', -- $1 is parameter name
anchor = 'param_access_requires_param',
category = 'CS1 errors: param-access',
hidden = false
},
err_param_has_ext_link = {
message = 'External link in <code class="cs1-code">$1</code>', -- $1 is parameter name
anchor = 'param_has_ext_link',
category = 'CS1 errors: external links',
hidden = false
},
err_param_has_twl_url = {
message = 'Wikipedia Library link in <code class="cs1-code">$1</code>', -- $1 is parameter name
anchor = 'param_has_twl_url',
category = 'CS1 errors: URL',
hidden = false
},
err_parameter_ignored = {
message = 'Unknown parameter <code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'parameter_ignored',
category = 'CS1 errors: unsupported parameter',
hidden = false
},
err_parameter_ignored_suggest = {
message = 'Unknown parameter <code class="cs1-code">|$1=</code> ignored (<code class="cs1-code">|$2=</code> suggested)', -- $1 is unknown parameter $2 is suggested parameter name
anchor = 'parameter_ignored_suggest',
category = 'CS1 errors: unsupported parameter',
hidden = false
},
err_periodical_ignored = {
message = '<code class="cs1-code">|$1=</code> ignored', -- $1 is parameter name
anchor = 'periodical_ignored',
category = 'CS1 errors: periodical ignored',
hidden = false
},
err_redundant_parameters = {
message = 'More than one of $1 specified', -- $1 is error message detail
anchor = 'redundant_parameters',
category = 'CS1 errors: redundant parameter',
hidden = false
},
err_script_parameter = {
message = 'Invalid <code class="cs1-code">|$1=</code>: $2', -- $1 is parameter name $2 is script language code or error detail
anchor = 'script_parameter',
category = 'CS1 errors: script parameters',
hidden = false
},
err_ssrn_missing = {
message = '<code class="cs1-code">|ssrn=</code> required',
anchor = 'ssrn_missing',
category = 'CS1 errors: SSRN',
hidden = false
},
err_text_ignored = {
message = 'Text "$1" ignored', -- $1 is ignored text
anchor = 'text_ignored',
category = 'CS1 errors: unrecognized parameter',
hidden = false
},
err_trans_missing_title = {
message = '<code class="cs1-code">|trans-$1=</code> requires <code class="cs1-code">|$1=</code> or <code class="cs1-code">|script-$1=</code>', -- $1 is base parameter name
anchor = 'trans_missing_title',
category = 'CS1 errors: translated title',
hidden = false
},
err_param_unknown_empty = {
message = 'Cite has empty unknown parameter$1: $2', -- $1 is 's' or empty space; $2 is emty unknown param list
anchor = 'param_unknown_empty',
category = 'CS1 errors: empty unknown parameters',
hidden = false
},
err_vancouver = {
message = 'Vancouver style error: $1 in name $2', -- $1 is error detail, $2 is the nth name
anchor = 'vancouver',
category = 'CS1 errors: Vancouver style',
hidden = false
},
err_wikilink_in_url = {
message = 'URL–wikilink conflict', -- uses ndash
anchor = 'wikilink_in_url',
category = 'CS1 errors: URL–wikilink conflict', -- uses ndash
hidden = false
},
--[[--------------------------< M A I N T >-------------------------------------
maint messages do not have a message (message = nil); otherwise the structure
is the same as error messages
]]
maint_archive_origin = {
message = nil,
anchor = 'archive_origin',
category = 'CS1 maint: archive origin',
hidden = true,
},
maint_archived_copy = {
message = nil,
anchor = 'archived_copy',
category = 'CS1 maint: archived copy as title',
hidden = true,
},
maint_bibcode = {
message = nil,
anchor = 'bibcode',
category = 'CS1 maint: bibcode',
hidden = true,
},
maint_location_no_publisher = { -- cite book, conference, encyclopedia; citation as book cite or encyclopedia cite
message = nil,
anchor = 'location_no_publisher',
category = 'CS1 maint: location missing publisher',
hidden = true,
},
maint_bot_unknown = {
message = nil,
anchor = 'bot:_unknown',
category = 'CS1 maint: bot: original URL status unknown',
hidden = true,
},
maint_date_auto_xlated = { -- date auto-translation not supported by en.wiki
message = nil,
anchor = 'date_auto_xlated',
category = 'CS1 maint: date auto-translated',
hidden = true,
},
maint_date_format = {
message = nil,
anchor = 'date_format',
category = 'CS1 maint: date format',
hidden = true,
},
maint_date_year = {
message = nil,
anchor = 'date_year',
category = 'CS1 maint: date and year',
hidden = true,
},
maint_deprecated_archive = {
message = nil,
anchor = 'deprecated_archive',
category = 'CS1 maint: deprecated archival service',
hidden = true,
},
maint_doi_ignore = {
message = nil,
anchor = 'doi_ignore',
category = 'CS1 maint: ignored DOI errors',
hidden = true,
},
maint_doi_inactive = {
message = nil,
anchor = 'doi_inactive',
category = 'CS1 maint: DOI inactive',
hidden = true,
},
maint_doi_inactive_dated = {
message = nil,
anchor = 'doi_inactive_dated',
category = 'CS1 maint: DOI inactive as of $2$3$1', -- $1 is year, $2 is month-name or empty string, $3 is space or empty string
hidden = true,
},
maint_doi_unflagged_free = {
message = nil,
anchor = 'doi_unflagged_free',
category = 'CS1 maint: unflagged free DOI',
hidden = true,
},
maint_extra_punct = {
message = nil,
anchor = 'extra_punct',
category = 'CS1 maint: extra punctuation',
hidden = true,
},
maint_id_limit_load_fail = { -- applies to all cs1|2 templates on a page;
message = nil, -- maint message (category link) never emitted
anchor = 'id_limit_load_fail',
category = 'CS1 maint: ID limit load fail',
hidden = true,
},
maint_isbn_ignore = {
message = nil,
anchor = 'ignore_isbn_err',
category = 'CS1 maint: ignored ISBN errors',
hidden = true,
},
maint_issn_ignore = {
message = nil,
anchor = 'ignore_issn',
category = 'CS1 maint: ignored ISSN errors',
hidden = true,
},
maint_jfm_format = {
message = nil,
anchor = 'jfm_format',
category = 'CS1 maint: JFM format',
hidden = true,
},
maint_location = {
message = nil,
anchor = 'location',
category = 'CS1 maint: location',
hidden = true,
},
maint_misc_url = {
message = nil,
anchor = 'misc_url',
category = 'CS1 maint: miscellaneous url',
hidden = true,
},
maint_missing_class = {
message = nil,
anchor = 'missing_class',
category = 'CS1 maint: missing class',
hidden = true,
},
maint_mr_format = {
message = nil,
anchor = 'mr_format',
category = 'CS1 maint: MR format',
hidden = true,
},
maint_mult_names = {
message = nil,
anchor = 'mult_names',
category = 'CS1 maint: multiple names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table
hidden = true,
},
maint_numeric_names = {
message = nil,
anchor = 'numeric_names',
category = 'CS1 maint: numeric names: $1', -- $1 is '<name>s list'; gets value from special_case_translation table
hidden = true,
},
maint_others = {
message = nil,
anchor = 'others',
category = 'CS1 maint: others',
hidden = true,
},
maint_others_avm = {
message = nil,
anchor = 'others_avm',
category = 'CS1 maint: others in cite AV media (notes)',
hidden = true,
},
maint_overridden_setting = {
message = nil,
anchor = 'overridden',
category = 'CS1 maint: overridden setting',
hidden = true,
},
maint_page_art_num = {
message = nil,
anchor = 'page_art_num',
category = 'CS1 maint: article number as page number',
hidden = true,
},
maint_periodical_has_isbn = {
message = nil,
anchor = 'periodical_has_isbn',
category = 'CS1 maint: periodical has ISBN',
hidden = true,
},
maint_pmc_embargo = {
message = nil,
anchor = 'embargo',
category = 'CS1 maint: PMC embargo expired',
hidden = true,
},
maint_pmc_format = {
message = nil,
anchor = 'pmc_format',
category = 'CS1 maint: PMC format',
hidden = true,
},
maint_postscript = {
message = nil,
anchor = 'postscript',
category = 'CS1 maint: postscript',
hidden = true,
},
maint_publisher_location = {
message = nil,
anchor = 'publisher_location',
category = 'CS1 maint: publisher location',
hidden = true,
},
maint_ref_duplicates_default = {
message = nil,
anchor = 'ref_default',
category = 'CS1 maint: ref duplicates default',
hidden = true,
},
maint_shortened_archive_url = {
message = nil,
anchor = 'shortened_archive_url',
category = 'CS1 maint: shortened archive url',
hidden = true,
},
maint_unknown_lang = {
message = nil,
anchor = 'unknown_lang',
category = 'CS1 maint: unrecognized language',
hidden = true,
},
maint_untitled = {
message = nil,
anchor = 'untitled',
category = 'CS1 maint: untitled periodical',
hidden = true,
},
maint_url_status = {
message = nil,
anchor = 'url_status',
category = 'CS1 maint: url-status',
hidden = true,
},
maint_work_isbn = {
message = nil,
anchor = 'work_isbn',
category = 'CS1 maint: work parameter with ISBN',
hidden = true,
},
maint_year= {
message = nil,
anchor = 'year',
category = 'CS1 maint: year',
hidden = true,
},
maint_zbl = {
message = nil,
anchor = 'zbl',
category = 'CS1 maint: Zbl',
hidden = true,
},
}
--[[--------------------------< I D _ L I M I T S _ D A T A _ T >----------------------------------------------
fetch id limits for certain identifiers from c:Data:CS1/Identifier limits.tab. This source is a json tabular
data file maintained at wikipedia commons. Convert the json format to a table of k/v pairs.
The values from <id_limits_data_t> are used to set handle.id_limit.
From 2025-02-21, MediaWiki is broken. Use this link to edit the tablular data file:
https://commons.wikimedia.org/w/index.php?title=Data:CS1/Identifier_limits.tab&action=edit
See Phab:T389105
]]
local id_limits_data_t;
local id_limits_data_load_fail = false; -- flag; assume that we will be successful when loading json id limit tabular data
local use_commons_data = true; -- set to false if your wiki does not have access to mediawiki commons; then,
if false == use_commons_data then -- update this table from https://commons.wikimedia.org/wiki/Data:CS1/Identifier_limits.tab; last update: 2026-08-02
id_limits_data_t = {['OCLC'] = 11160000000, ['OSTI'] = 23010000, ['PMC'] = 13500000, ['PMID'] = 42900000, ['RFC'] = 9300, ['SSRN'] = 7500000, ['S2CID'] = 290000000}; -- this table must be maintained locally
else -- here for wikis that do have access to mediawiki commons
local load_fail_limit = 99999999999; -- very high number to avoid error messages on load failure
id_limits_data_t = {['OCLC'] = load_fail_limit, ['OSTI'] = load_fail_limit, ['PMC'] = load_fail_limit, ['PMID'] = load_fail_limit, ['RFC'] = load_fail_limit, ['SSRN'] = load_fail_limit, ['S2CID'] = load_fail_limit};
if mw.ext.data == nil then
id_limits_data_load_fail = true; -- safeguard against Lua errors if mw.ext.data is not available for some reason
else
local tab_data_t = mw.ext.data.get ('CS1/Identifier limits.tab'); -- attempt to load the tabular data from commons into <tab_data_t>
if false == tab_data_t then -- undocumented 'feature': mw.ext.data.get() sometimes returns false
id_limits_data_load_fail = true; -- set the flag so that Module:Citation/CS1 can create an unannotated maint category
else
for _, limit_t in ipairs (tab_data_t.data) do -- overwrite default <load_fail_limit> values from the data table in the tabular data
id_limits_data_t[limit_t[1]] = limit_t[2]; -- <limit[1]> is identifier; <limit[2]> is upper limit for that identifier
end
end
end
end
--[[--------------------------< I D _ H A N D L E R S >--------------------------------------------------------
The following contains a list of values for various defined identifiers. For each
identifier we specify a variety of information necessary to properly render the
identifier in the citation.
parameters: a list of parameter aliases for this identifier; first in the list is the canonical form
link: Wikipedia article name
redirect: a local redirect to a local Wikipedia article name; at en.wiki, 'ISBN (identifier)' is a redirect to 'International Standard Book Number'
q: Wikidata q number for the identifier
label: the label preceding the identifier; label is linked to a Wikipedia article (in this order):
redirect from id_handlers['<id>'].redirect when use_identifier_redirects is true
Wikidata-supplied article name for the local wiki from id_handlers['<id>'].q
local article name from id_handlers['<id>'].link
prefix: the first part of a URL that will be concatenated with a second part which usually contains the identifier
suffix: optional third part to be added after the identifier
encode: true if URI should be percent-encoded; otherwise false
COinS: identifier link or keyword for use in COinS:
for identifiers registered at info-uri.info use: info:.... where '...' is the appropriate identifier label
for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn
for |asin= and |ol=, which require assembly, use the keyword: url
for others make a URL using the value in prefix/suffix and #label, use the keyword: pre (not checked; any text other than 'info', 'rft', or 'url' works here)
set to nil to leave the identifier out of the COinS
separator: character or text between label and the identifier in the rendered citation
id_limit: for those identifiers with established limits, this property holds the upper limit
access: use this parameter to set the access level for all instances of this identifier.
the value must be a valid access level for an identifier (see ['id-access'] in this file).
custom_access: to enable custom access level for an identifier, set this parameter
to the parameter that should control it (normally 'id-access')
]]
local id_handlers = {
['ARXIV'] = {
parameters = {'arxiv', 'eprint'},
link = 'arXiv',
redirect = 'arXiv (identifier)',
q = 'Q118398',
label = 'arXiv',
prefix = 'https://arxiv.org/abs/',
encode = false,
COinS = 'info:arxiv',
separator = ':',
access = 'free', -- free to read
},
['ASIN'] = {
parameters = { 'asin', 'ASIN' },
link = 'Amazon Standard Identification Number',
redirect = 'ASIN (identifier)',
q = 'Q1753278',
label = 'ASIN',
prefix = 'https://www.amazon.',
COinS = 'url',
separator = ' ',
encode = false;
},
['BIBCODE'] = {
parameters = {'bibcode'},
link = 'Bibcode',
redirect = 'Bibcode (identifier)',
q = 'Q25754',
label = 'Bibcode',
prefix = 'https://ui.adsabs.harvard.edu/abs/',
encode = false,
COinS = 'info:bibcode',
separator = ':',
custom_access = 'bibcode-access',
},
['BIORXIV'] = {
parameters = {'biorxiv'},
link = 'bioRxiv',
redirect = 'bioRxiv (identifier)',
q = 'Q19835482',
label = 'bioRxiv',
prefix = 'https://doi.org/',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['CITESEERX'] = {
parameters = {'citeseerx'},
link = 'CiteSeerX',
redirect = 'CiteSeerX (identifier)',
q = 'Q2715061',
label = 'CiteSeerX',
prefix = 'https://citeseerx.ist.psu.edu/viewdoc/summary?doi=',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['DOI'] = { -- Used by InternetArchiveBot
parameters = { 'doi', 'DOI'},
link = 'Digital object identifier',
redirect = 'doi (identifier)',
q = 'Q25670',
label = 'doi',
prefix = 'https://doi.org/',
COinS = 'info:doi',
separator = ':',
encode = true,
custom_access = 'doi-access',
},
['EISSN'] = {
parameters = {'eissn', 'EISSN'},
link = 'International Standard Serial Number#Electronic ISSN',
redirect = 'eISSN (identifier)',
q = 'Q46339674',
label = 'eISSN',
prefix = 'https://search.worldcat.org/issn/',
COinS = 'rft.eissn',
encode = false,
separator = ' ',
},
['HDL'] = {
parameters = { 'hdl', 'HDL' },
link = 'Handle System',
redirect = 'hdl (identifier)',
q = 'Q3126718',
label = 'hdl',
prefix = 'https://hdl.handle.net/',
COinS = 'info:hdl',
separator = ':',
encode = true,
custom_access = 'hdl-access',
},
['ISBN'] = { -- Used by InternetArchiveBot
parameters = {'isbn', 'ISBN'},
link = 'International Standard Book Number',
redirect = 'ISBN (identifier)',
q = 'Q33057',
label = 'ISBN',
prefix = 'Special:BookSources/',
COinS = 'rft.isbn',
separator = ' ',
},
['ISMN'] = {
parameters = {'ismn', 'ISMN'},
link = 'International Standard Music Number',
redirect = 'ISMN (identifier)',
q = 'Q1666938',
label = 'ISMN',
prefix = '', -- not currently used;
COinS = nil, -- nil because we can't use pre or rft or info:
separator = ' ',
},
['ISSN'] = {
parameters = {'issn', 'ISSN'},
link = 'International Standard Serial Number',
redirect = 'ISSN (identifier)',
q = 'Q131276',
label = 'ISSN',
prefix = 'https://search.worldcat.org/issn/',
COinS = 'rft.issn',
encode = false,
separator = ' ',
},
['JFM'] = {
parameters = {'jfm', 'JFM'},
link = 'Jahrbuch über die Fortschritte der Mathematik',
redirect = 'JFM (identifier)',
q = '',
label = 'JFM',
prefix = 'https://zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['JSTOR'] = {
parameters = {'jstor', 'JSTOR'},
link = 'JSTOR',
redirect = 'JSTOR (identifier)',
q = 'Q1420342',
label = 'JSTOR',
prefix = 'https://www.jstor.org/stable/',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
custom_access = 'jstor-access',
},
['LCCN'] = {
parameters = {'lccn', 'LCCN'},
link = 'Library of Congress Control Number',
redirect = 'LCCN (identifier)',
q = 'Q620946',
label = 'LCCN',
prefix = 'https://lccn.loc.gov/',
COinS = 'info:lccn',
encode = false,
separator = ' ',
},
['MEDRXIV'] = {
parameters = {'medrxiv'},
link = 'medRxiv',
redirect = 'medRxiv (identifier)',
q = 'Q58465838',
label = 'medRxiv',
prefix = 'https://www.medrxiv.org/content/',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = false,
separator = ' ',
},
['MR'] = {
parameters = {'mr', 'MR'},
link = 'Mathematical Reviews',
redirect = 'MR (identifier)',
q = 'Q211172',
label = 'MR',
prefix = 'https://mathscinet.ams.org/mathscinet-getitem?mr=',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['OCLC'] = {
parameters = {'oclc', 'OCLC'},
link = 'OCLC',
redirect = 'OCLC (identifier)',
q = 'Q190593',
label = 'OCLC',
prefix = 'https://search.worldcat.org/oclc/',
COinS = 'info:oclcnum',
encode = true,
separator = ' ',
id_limit = id_limits_data_t.OCLC or 0,
},
['OL'] = {
parameters = { 'ol', 'OL' },
link = 'Open Library',
redirect = 'OL (identifier)',
q = 'Q1201876',
label = 'OL',
prefix = 'https://openlibrary.org/',
COinS = 'url',
separator = ' ',
encode = true,
custom_access = 'ol-access',
},
['OSTI'] = {
parameters = {'osti', 'OSTI'},
link = 'Office of Scientific and Technical Information',
redirect = 'OSTI (identifier)',
q = 'Q2015776',
label = 'OSTI',
prefix = 'https://www.osti.gov/biblio/',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.OSTI or 0,
custom_access = 'osti-access',
},
['PMC'] = {
parameters = {'pmc', 'PMC'},
link = 'PubMed Central',
redirect = 'PMC (identifier)',
q = 'Q229883',
label = 'PMC',
prefix = 'https://www.ncbi.nlm.nih.gov/pmc/articles/PMC',
suffix = '',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.PMC or 0,
access = 'free', -- free to read
},
['PMID'] = {
parameters = {'pmid', 'PMID'},
link = 'PubMed Identifier',
redirect = 'PMID (identifier)',
q = 'Q2082879',
label = 'PMID',
prefix = 'https://pubmed.ncbi.nlm.nih.gov/',
COinS = 'info:pmid',
encode = false,
separator = ' ',
id_limit = id_limits_data_t.PMID or 0,
},
['RFC'] = {
parameters = {'rfc', 'RFC'},
link = 'Request for Comments',
redirect = 'RFC (identifier)',
q = 'Q212971',
label = 'RFC',
prefix = 'https://tools.ietf.org/html/rfc',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
id_limit = id_limits_data_t.RFC or 0,
access = 'free', -- free to read
},
['SBN'] = {
parameters = {'sbn', 'SBN'},
link = 'Standard Book Number', -- redirect to International_Standard_Book_Number#History
redirect = 'SBN (identifier)',
label = 'SBN',
prefix = 'Special:BookSources/0-', -- prefix has leading zero necessary to make 9-digit sbn a 10-digit isbn
COinS = nil, -- nil because we can't use pre or rft or info:
separator = ' ',
},
['SSRN'] = {
parameters = {'ssrn', 'SSRN'},
link = 'Social Science Research Network',
redirect = 'SSRN (identifier)',
q = 'Q7550801',
label = 'SSRN',
prefix = 'https://papers.ssrn.com/sol3/papers.cfm?abstract_id=',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
id_limit = id_limits_data_t.SSRN or 0,
custom_access = 'ssrn-access',
},
['S2CID'] = {
parameters = {'s2cid', 'S2CID'},
link = 'Semantic Scholar',
redirect = 'S2CID (identifier)',
q = 'Q22908627',
label = 'S2CID',
prefix = 'https://api.semanticscholar.org/CorpusID:',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
id_limit = id_limits_data_t.S2CID or 0,
custom_access = 's2cid-access',
},
['USENETID'] = {
parameters = {'message-id'},
link = 'Usenet',
redirect = 'Usenet (identifier)',
q = 'Q193162',
label = 'Usenet:',
prefix = 'news:',
encode = false,
COinS = 'pre', -- use prefix value
separator = ' ',
},
['ZBL'] = {
parameters = {'zbl', 'ZBL' },
link = 'Zentralblatt MATH',
redirect = 'Zbl (identifier)',
q = 'Q190269',
label = 'Zbl',
prefix = 'https://zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
}
--[[--------------------------< E X P O R T S >---------------------------------
]]
return {
use_identifier_redirects = use_identifier_redirects, -- booleans defined in the settings at the top of this module
local_lang_cat_enable = local_lang_cat_enable,
date_name_auto_xlate_enable = date_name_auto_xlate_enable,
date_digit_auto_xlate_enable = date_digit_auto_xlate_enable,
enable_sort_keys = enable_sort_keys,
suppress_archive_today_urls = suppress_archive_today_urls,
-- tables and variables created when this module is loaded
dependencies_t = dependencies_t, -- used to suppress parameters dependent on url-holding parameters holding archive.today urls
enum_needs_xlation = '1' ~= date_names.xlate_digits['1'], -- to avoid unnecessary enumerator translation
global_df = get_date_format (), -- this line can be replaced with "global_df = 'dmy-all'," to have all dates auto translated to dmy format.
global_cs1_config_t = global_cs1_config_t, -- global settings from {{cs1 config}}
id_limits_data_load_fail = id_limits_data_load_fail, -- true when commons tabular identifier-limit data fails to load
known_free_doi_registrants_t = build_free_doi_registrants_table(),
punct_skip = build_skip_table (punct_skip, punct_meta_params),
url_skip = build_skip_table (url_skip, url_meta_params),
archive_today_tlds_t = {['today'] = true, ['ph'] = true, ['is'] = true, ['md'] = true, ['li'] = true, ['fo'] = true, ['vn'] = true}; -- used by is_archive_today_url()
name_space_sort_keys = name_space_sort_keys,
aliases = aliases,
special_case_translation = special_case_translation,
date_names = date_names,
err_msg_supl = err_msg_supl,
error_conditions = error_conditions,
et_al_patterns = et_al_patterns,
extended_registrants_t = extended_registrants_t,
id_handlers = id_handlers,
keywords_lists = keywords_lists,
keywords_xlate = keywords_xlate,
stripmarkers = stripmarkers,
invisible_chars = invisible_chars,
invisible_defs = invisible_defs,
indic_script = indic_script,
emoji_t = emoji_t,
messages = messages,
presentation = presentation,
prop_cats = prop_cats,
script_lang_codes = script_lang_codes,
lang_tag_remap = lang_tag_remap,
lang_name_remap = lang_name_remap,
this_wiki_code = this_wiki_code,
title_types = title_types,
uncategorized_namespaces = uncategorized_namespaces_t,
uncategorized_subpages = uncategorized_subpages,
templates_using_volume = templates_using_volume,
templates_using_issue = templates_using_issue,
templates_not_using_page = templates_not_using_page,
vol_iss_pg_patterns = vol_iss_pg_patterns,
single_letter_2nd_lvl_domains_t = single_letter_2nd_lvl_domains_t,
url_access_map_t = url_access_map_t,
inter_wiki_map = inter_wiki_map,
mw_languages_by_tag_t = mw_languages_by_tag_t,
mw_languages_by_name_t = mw_languages_by_name_t,
citation_class_map_t = citation_class_map_t,
citation_issue_t = citation_issue_t,
citation_no_volume_t = citation_no_volume_t,
}
e7w2jpc8m3hf485c54y7d0wmq4zi17p
Module:Citation/CS1/Whitelist
828
926
9005
2026-08-08T13:56:52Z
en>Trappist the monk
0
synch from sandbox;
9005
Scribunto
text/plain
--[[--------------------------< S U P P O R T E D P A R A M E T E R S >--------------------------------------
Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values:
true - these parameters are valid and supported parameters
false - these parameters are deprecated but still supported
tracked - these parameters are valid and supported parameters tracked in an eponymous properties category
nil - these parameters are no longer supported. remove entirely
]]
local basic_arguments_t = {
['accessdate'] = true,
['access-date'] = true,
['agency'] = true,
['archivedate'] = true,
['archive-date'] = true,
['archive-format'] = true,
['archiveurl'] = true,
['archive-url'] = true,
['article'] = true,
['article-format'] = true,
['article-number'] = true, -- {{cite journal}}, {{cite conference}}; {{citation}} when |journal= has a value
['article-url'] = true,
['article-url-access'] = true,
['arxiv'] = true, -- cite arxiv; here because allowed in cite ... as identifier
['asin'] = true,
['ASIN'] = true,
['asin-tld'] = true,
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-given'] = true,
['author-last'] = true,
['author-surname'] = true,
['authorlink'] = true,
['author-link'] = true,
['author-mask'] = true,
['bibcode'] = true,
['bibcode-access'] = true,
['biorxiv'] = true, -- cite biorxiv; here because allowed in cite ... as identifier
['chapter'] = true,
['chapter-format'] = true,
['chapter-url'] = true,
['chapter-url-access'] = true,
['citeseerx'] = false, -- cite citeseerx; here because allowed in cite ... as identifier
['collaboration'] = true,
['contribution'] = true,
['contribution-format'] = true,
['contribution-url'] = true,
['contribution-url-access'] = true,
['contributor'] = true,
['contributor-first'] = true,
['contributor-given'] = true,
['contributor-last'] = true,
['contributor-surname'] = true,
['contributor-link'] = true,
['contributor-mask'] = true,
['date'] = true,
['department'] = true,
['df'] = true,
['dictionary'] = true,
['display-authors'] = true,
['display-contributors'] = true,
['display-editors'] = true,
['display-interviewers'] = true,
['display-subjects'] = true,
['display-translators'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken-date'] = true,
['edition'] = true,
['editor'] = true,
['editor-first'] = true,
['editor-given'] = true,
['editor-last'] = true,
['editor-surname'] = true,
['editor-link'] = true,
['editor-mask'] = true,
['eissn'] = true,
['EISSN'] = true,
['encyclopaedia'] = true,
['encyclopedia'] = true,
['entry'] = true,
['entry-format'] = true,
['entry-url'] = true,
['entry-url-access'] = true,
['eprint'] = true, -- cite arxiv; here because allowed in cite ... as identifier
['first'] = true,
['format'] = true,
['given'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['host'] = true, -- unique to certain templates?
['id'] = true,
['ID'] = true,
['institution'] = true, -- constrain to cite thesis?
['interviewer'] = true,
['interviewer-first'] = true,
['interviewer-given'] = true,
['interviewer-last'] = true,
['interviewer-surname'] = true,
['interviewer-link'] = true,
['interviewer-mask'] = true,
['isbn'] = true,
['ISBN'] = true,
['ismn'] = true,
['ISMN'] = true,
['issn'] = true,
['ISSN'] = true,
['issue'] = true,
['jfm'] = true,
['JFM'] = true,
['journal'] = true,
['jstor'] = true,
['JSTOR'] = true,
['jstor-access'] = true,
['lang'] = true,
['language'] = true,
['last'] = true,
['lccn'] = true,
['LCCN'] = true,
['location'] = true,
['magazine'] = true,
['medium'] = true,
['medrxiv'] = true, -- cite medrxiv; here because allowed in cite ... as identifier
['minutes'] = true, -- constrain to cite AV media and podcast?
['mode'] = true,
['mr'] = true,
['MR'] = true,
['name-list-style'] = true,
['newspaper'] = true,
['no-pp'] = true,
['no-tracking'] = true,
['number'] = true,
['oclc'] = true,
['OCLC'] = true,
['ol'] = true,
['OL'] = true,
['ol-access'] = true,
['orig-date'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['others'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['periodical'] = true,
['place'] = true,
['pmc'] = true,
['PMC'] = true,
['pmc-embargo-date'] = true,
['pmid'] = true,
['PMID'] = true,
['postscript'] = true,
['pp'] = true,
['publication-date'] = true,
['publication-place'] = true,
['publisher'] = true,
['quotation'] = true,
['quote'] = true,
['quote-page'] = true,
['quote-pages'] = true,
['ref'] = true,
['rfc'] = true,
['RFC'] = true,
['sbn'] = true,
['SBN'] = true,
['scale'] = true,
['script-article'] = true,
['script-chapter'] = true,
['script-contribution'] = true,
['script-encyclopaedia'] = true,
['script-encyclopedia'] = true,
['script-entry'] = true,
['script-journal'] = true,
['script-magazine'] = true,
['script-newspaper'] = true,
['script-periodical'] = true,
['script-quote'] = true,
['script-section'] = true,
['script-title'] = true,
['script-website'] = true,
['script-work'] = true,
['section'] = true,
['section-format'] = true,
['section-url'] = true,
['section-url-access'] = true,
['series'] = true,
['ssrn'] = true, -- cite ssrn; these three here because allowed in cite ... as identifier
['SSRN'] = true,
['ssrn-access'] = true,
['subject'] = true,
['subject-first'] = true,
['subject-given'] = true,
['subject-last'] = true,
['subject-link'] = true,
['subject-mask'] = true,
['subject-surname'] = true,
['surname'] = true,
['s2cid'] = true,
['S2CID'] = true,
['s2cid-access'] = true,
['template-doc-demo'] = true,
['time'] = true, -- constrain to cite av media and podcast?
['time-caption'] = true, -- constrain to cite av media and podcast?
['title'] = true,
['title-link'] = true,
['title-note'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-given'] = true,
['translator-last'] = true,
['translator-surname'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['trans-article'] = true,
['trans-chapter'] = true,
['trans-contribution'] = true,
['trans-encyclopaedia'] = true,
['trans-encyclopedia'] = true,
['trans-entry'] = true,
['trans-journal'] = true,
['trans-magazine'] = true,
['trans-newspaper'] = true,
['trans-periodical'] = true,
['trans-quote'] = true,
['trans-section'] = true,
['trans-title'] = true,
['trans-website'] = true,
['trans-work'] = true,
['type'] = true,
['url'] = true,
['URL'] = true,
['url-access'] = true,
['url-status'] = true,
['vauthors'] = true,
['veditors'] = true,
['version'] = true,
['via'] = true,
['volume'] = true,
['website'] = true,
['work'] = true,
['year'] = true,
['zbl'] = true,
['ZBL'] = true,
}
local numbered_arguments_t = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-given#'] = true,
['author#-given'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-surname#'] = true,
['author#-surname'] = true,
['author-link#'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author#link'] = true,
['author-mask#'] = true,
['author#-mask'] = true,
['contributor#'] = true,
['contributor-first#'] = true,
['contributor#-first'] = true,
['contributor-given#'] = true,
['contributor#-given'] = true,
['contributor-last#'] = true,
['contributor#-last'] = true,
['contributor-surname#'] = true,
['contributor#-surname'] = true,
['contributor-link#'] = true,
['contributor#-link'] = true,
['contributor-mask#'] = true,
['contributor#-mask'] = true,
['editor#'] = true,
['editor-first#'] = true,
['editor#-first'] = true,
['editor-given#'] = true,
['editor#-given'] = true,
['editor-last#'] = true,
['editor#-last'] = true,
['editor-surname#'] = true,
['editor#-surname'] = true,
['editor-link#'] = true,
['editor#-link'] = true,
['editor-mask#'] = true,
['editor#-mask'] = true,
['first#'] = true,
['given#'] = true,
['host#'] = true,
['interviewer#'] = true,
['interviewer-first#'] = true,
['interviewer#-first'] = true,
['interviewer-given#'] = true,
['interviewer#-given'] = true,
['interviewer-last#'] = true,
['interviewer#-last'] = true,
['interviewer-surname#'] = true,
['interviewer#-surname'] = true,
['interviewer-link#'] = true,
['interviewer#-link'] = true,
['interviewer-mask#'] = true,
['interviewer#-mask'] = true,
['last#'] = true,
['subject#'] = true,
['subject-first#'] = true,
['subject#-first'] = true,
['subject-given#'] = true,
['subject#-given'] = true,
['subject-last#'] = true,
['subject#-last'] = true,
['subject-link#'] = true,
['subject#-link'] = true,
['subject-mask#'] = true,
['subject#-mask'] = true,
['subject-surname#'] = true,
['subject#-surname'] = true,
['surname#'] = true,
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-given#'] = true,
['translator#-given'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-surname#'] = true,
['translator#-surname'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
--[[--------------------------< P R E P R I N T S U P P O R T E D P A R A M E T E R S >--------------------
Cite arXiv, cite biorxiv, cite citeseerx, cite medrxiv, and cite ssrn are preprint templates that use the limited
set of parameters defined in the limited_basic_arguments and limited_numbered_arguments tables. Those lists are
supplemented with a template-specific list of parameters that are required by the particular template and may be
exclusive to one of the preprint templates. Some of these parameters may also be available to the general cs1|2
templates.
Same conventions for true/false/tracked/nil as above.
]]
local preprint_arguments_t = {
arxiv = {
['arxiv'] = true, -- cite arxiv and arxiv identifiers
['class'] = true,
['eprint'] = true, -- cite arxiv and arxiv identifiers
},
biorxiv = {
['biorxiv'] = true,
},
citeseerx = {
['citeseerx'] = false,
},
medrxiv = {
['medrxiv'] = true,
},
ssrn = {
['ssrn'] = true,
['SSRN'] = true,
['ssrn-access'] = true,
},
}
--[[--------------------------< L I M I T E D S U P P O R T E D P A R A M E T E R S >----------------------
cite arxiv, cite biorxiv, cite citeseerx, cite medrxiv, and cite ssrn templates are preprint templates so are
allowed only a limited subset of parameters allowed to all other cs1|2 templates. The limited subset is defined
here.
This list of parameters also used by {{cite document}}
Same conventions for true/false/tracked/nil as above.
]]
local limited_basic_arguments_t = {
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-given'] = true,
['author-last'] = true,
['author-surname'] = true,
['author-link'] = true,
['authorlink'] = true,
['author-mask'] = true,
['collaboration'] = true,
['date'] = true,
['df'] = true,
['display-authors'] = true,
['first'] = true,
['given'] = true,
['language'] = true,
['last'] = true,
['mode'] = true,
['name-list-style'] = true,
['no-tracking'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['postscript'] = true,
['pp'] = true,
['quotation'] = true,
['quote'] = true,
['ref'] = true,
['surname'] = true,
['template-doc-demo'] = true,
['title'] = true,
['trans-title'] = true,
['vauthors'] = true,
['year'] = true,
}
local limited_numbered_arguments_t = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-given#'] = true,
['author#-given'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-surname#'] = true,
['author#-surname'] = true,
['author-link#'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author#link'] = true,
['author-mask#'] = true,
['author#-mask'] = true,
['first#'] = true,
['given#'] = true,
['last#'] = true,
['surname#'] = true,
}
--[[--------------------------< U N I Q U E _ A R G U M E N T S >----------------------------------------------
Some templates have unique parameters. Those templates and their unique parameters are listed here. Keys in this
table are the template's CitationClass parameter value
Same conventions for true/false/tracked/nil as above.
]]
local unique_arguments_t = {
['audio-visual'] = {
['people'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcript-url'] = true,
},
conference = {
['book-title'] = true,
['conference'] = true,
['conference-format'] = true,
['conference-url'] = true,
['event'] = true,
},
episode = {
['airdate'] = true,
['air-date'] = true,
['credits'] = true,
['episode-link'] = true, -- alias of |title-link=
['network'] = true,
['people'] = true,
['season'] = true,
['series-link'] = true,
['series-no'] = true,
['series-number'] = true,
['station'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcript-url'] = true,
},
mailinglist = {
['mailing-list'] = true,
},
map = {
['cartography'] = true,
['inset'] = true,
['map'] = true,
['map-format'] = true,
['map-url'] = true,
['map-url-access'] = true,
['script-map'] = true,
['sections'] = true,
['sheet'] = true,
['sheets'] = true,
['trans-map'] = true,
},
newsgroup = {
['message-id'] = true,
['newsgroup'] = true,
},
report = {
['docket'] = true,
},
serial = {
['airdate'] = true,
['air-date'] = true,
['credits'] = true,
['episode'] = true, -- cite serial only TODO: make available to cite episode?
['episode-link'] = true, -- alias of |title-link=
['network'] = true,
['people'] = true,
['series-link'] = true,
['station'] = true,
},
speech = {
['conference'] = true,
['conference-format'] = true,
['conference-url'] = true,
['event'] = true,
},
thesis = {
['degree'] = true,
['docket'] = true,
},
}
--[[--------------------------< C I T E _ D O C U M E N T >----------------------------------------------------
Special case for cite document. This template takes the limited basic and limited enumerated parameters plus
others that are apply only to standalone published sources that cannot be cited any other way; no url, book,
periodical, etc parameters; limited support for name lists and named identifiers.
when validating parameters in {{cite document}} templates, the basic and
]]
local document_arguments_t = {
['bibcode'] = true,
['bibcode-access'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken-date'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['id'] = true,
['ID'] = true,
['jfm'] = true,
['JFM'] = true,
['lang'] = true,
['location'] = true,
['mr'] = true,
['MR'] = true,
['no-pp'] = true,
['orig-date'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['place'] = true,
['publisher'] = true,
['quote-page'] = true,
['quote-pages'] = true,
['script-quote'] = true,
['script-title'] = true,
['title-link'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-given'] = true,
['translator-last'] = true,
['translator-surname'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['trans-quote'] = true,
['type'] = true,
['zbl'] = true,
['ZBL'] = true,
}
local document_numbered_arguments_t = {
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-given#'] = true,
['translator#-given'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-surname#'] = true,
['translator#-surname'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
--[[--------------------------< L I S T _ C O M B I N E >------------------------------------------------------
makes one table from a list of tables. <lists_t> is a sequence of tables to be combined
]]
local function list_combine (lists_t)
local out_t = {};
for _, list_t in ipairs (lists_t) do -- for each list in <lists_t>
for k, v in pairs (list_t) do -- extract each k/v pair
out_t[k] = v; -- add to <out_t>
end
end
return out_t; -- and done
end
--[[--------------------------< T E M P L A T E _ L I S T _ G E T >--------------------------------------------
gets a list of the templates from table t
]]
local function template_list_get (t)
local out_t = {}; -- a table for output
for k, _ in pairs (t) do -- spin through the table and collect the keys
table.insert (out_t, k) -- add each key to the output table
end
return out_t; -- and done
end
--[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------
]]
return {
preprint_arguments_t = preprint_arguments_t,
preprint_template_list_t = template_list_get (preprint_arguments_t), -- make a template list from preprint_arguments{} table
unique_arguments_t = unique_arguments_t,
unique_param_template_list_t = template_list_get (unique_arguments_t), -- make a template list from unique_arguments{} table
document_parameters_t = list_combine ({limited_basic_arguments_t, limited_numbered_arguments_t, document_arguments_t, document_numbered_arguments_t});
common_parameters_t = list_combine ({basic_arguments_t, numbered_arguments_t});
limited_parameters_t = list_combine ({limited_basic_arguments_t, limited_numbered_arguments_t});
};
1livvij6p41ygpz0myvp2ov8j5lfzcj
9006
8257
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/Whitelist]]
8257
Scribunto
text/plain
--[[--------------------------< S U P P O R T E D P A R A M E T E R S >--------------------------------------
Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values:
true - these parameters are valid and supported parameters
false - these parameters are deprecated but still supported
tracked - these parameters are valid and supported parameters tracked in an eponymous properties category
nil - these parameters are no longer supported. remove entirely
]]
local basic_arguments_t = {
['accessdate'] = true,
['access-date'] = true,
['agency'] = true,
['archivedate'] = true,
['archive-date'] = true,
['archive-format'] = true,
['archiveurl'] = true,
['archive-url'] = true,
['article'] = true,
['article-format'] = true,
['article-number'] = true, -- {{cite journal}}, {{cite conference}}; {{citation}} when |journal= has a value
['article-url'] = true,
['article-url-access'] = true,
['arxiv'] = true, -- cite arxiv; here because allowed in cite ... as identifier
['asin'] = true,
['ASIN'] = true,
['asin-tld'] = true,
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-given'] = true,
['author-last'] = true,
['author-surname'] = true,
['authorlink'] = true,
['author-link'] = true,
['author-mask'] = true,
['bibcode'] = true,
['bibcode-access'] = true,
['biorxiv'] = true, -- cite biorxiv; here because allowed in cite ... as identifier
['chapter'] = true,
['chapter-format'] = true,
['chapter-url'] = true,
['chapter-url-access'] = true,
['citeseerx'] = false, -- cite citeseerx; here because allowed in cite ... as identifier
['collaboration'] = true,
['contribution'] = true,
['contribution-format'] = true,
['contribution-url'] = true,
['contribution-url-access'] = true,
['contributor'] = true,
['contributor-first'] = true,
['contributor-given'] = true,
['contributor-last'] = true,
['contributor-surname'] = true,
['contributor-link'] = true,
['contributor-mask'] = true,
['date'] = true,
['department'] = true,
['df'] = true,
['dictionary'] = true,
['display-authors'] = true,
['display-contributors'] = true,
['display-editors'] = true,
['display-interviewers'] = true,
['display-subjects'] = true,
['display-translators'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken-date'] = true,
['edition'] = true,
['editor'] = true,
['editor-first'] = true,
['editor-given'] = true,
['editor-last'] = true,
['editor-surname'] = true,
['editor-link'] = true,
['editor-mask'] = true,
['eissn'] = true,
['EISSN'] = true,
['encyclopaedia'] = true,
['encyclopedia'] = true,
['entry'] = true,
['entry-format'] = true,
['entry-url'] = true,
['entry-url-access'] = true,
['eprint'] = true, -- cite arxiv; here because allowed in cite ... as identifier
['first'] = true,
['format'] = true,
['given'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['host'] = true, -- unique to certain templates?
['id'] = true,
['ID'] = true,
['institution'] = true, -- constrain to cite thesis?
['interviewer'] = true,
['interviewer-first'] = true,
['interviewer-given'] = true,
['interviewer-last'] = true,
['interviewer-surname'] = true,
['interviewer-link'] = true,
['interviewer-mask'] = true,
['isbn'] = true,
['ISBN'] = true,
['ismn'] = true,
['ISMN'] = true,
['issn'] = true,
['ISSN'] = true,
['issue'] = true,
['jfm'] = true,
['JFM'] = true,
['journal'] = true,
['jstor'] = true,
['JSTOR'] = true,
['jstor-access'] = true,
['lang'] = true,
['language'] = true,
['last'] = true,
['lccn'] = true,
['LCCN'] = true,
['location'] = true,
['magazine'] = true,
['medium'] = true,
['medrxiv'] = true, -- cite medrxiv; here because allowed in cite ... as identifier
['minutes'] = true, -- constrain to cite AV media and podcast?
['mode'] = true,
['mr'] = true,
['MR'] = true,
['name-list-style'] = true,
['newspaper'] = true,
['no-pp'] = true,
['no-tracking'] = true,
['number'] = true,
['oclc'] = true,
['OCLC'] = true,
['ol'] = true,
['OL'] = true,
['ol-access'] = true,
['orig-date'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['others'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['periodical'] = true,
['place'] = true,
['pmc'] = true,
['PMC'] = true,
['pmc-embargo-date'] = true,
['pmid'] = true,
['PMID'] = true,
['postscript'] = true,
['pp'] = true,
['publication-date'] = true,
['publication-place'] = true,
['publisher'] = true,
['quotation'] = true,
['quote'] = true,
['quote-page'] = true,
['quote-pages'] = true,
['ref'] = true,
['rfc'] = true,
['RFC'] = true,
['sbn'] = true,
['SBN'] = true,
['scale'] = true,
['script-article'] = true,
['script-chapter'] = true,
['script-contribution'] = true,
['script-encyclopaedia'] = true,
['script-encyclopedia'] = true,
['script-entry'] = true,
['script-journal'] = true,
['script-magazine'] = true,
['script-newspaper'] = true,
['script-periodical'] = true,
['script-quote'] = true,
['script-section'] = true,
['script-title'] = true,
['script-website'] = true,
['script-work'] = true,
['section'] = true,
['section-format'] = true,
['section-url'] = true,
['section-url-access'] = true,
['series'] = true,
['ssrn'] = true, -- cite ssrn; these three here because allowed in cite ... as identifier
['SSRN'] = true,
['ssrn-access'] = true,
['subject'] = true,
['subject-first'] = true,
['subject-given'] = true,
['subject-last'] = true,
['subject-link'] = true,
['subject-mask'] = true,
['subject-surname'] = true,
['surname'] = true,
['s2cid'] = true,
['S2CID'] = true,
['s2cid-access'] = true,
['template-doc-demo'] = true,
['time'] = true, -- constrain to cite av media and podcast?
['time-caption'] = true, -- constrain to cite av media and podcast?
['title'] = true,
['title-link'] = true,
['title-note'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-given'] = true,
['translator-last'] = true,
['translator-surname'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['trans-article'] = true,
['trans-chapter'] = true,
['trans-contribution'] = true,
['trans-encyclopaedia'] = true,
['trans-encyclopedia'] = true,
['trans-entry'] = true,
['trans-journal'] = true,
['trans-magazine'] = true,
['trans-newspaper'] = true,
['trans-periodical'] = true,
['trans-quote'] = true,
['trans-section'] = true,
['trans-title'] = true,
['trans-website'] = true,
['trans-work'] = true,
['type'] = true,
['url'] = true,
['URL'] = true,
['url-access'] = true,
['url-status'] = true,
['vauthors'] = true,
['veditors'] = true,
['version'] = true,
['via'] = true,
['volume'] = true,
['website'] = true,
['work'] = true,
['year'] = true,
['zbl'] = true,
['ZBL'] = true,
}
local numbered_arguments_t = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-given#'] = true,
['author#-given'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-surname#'] = true,
['author#-surname'] = true,
['author-link#'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author#link'] = true,
['author-mask#'] = true,
['author#-mask'] = true,
['contributor#'] = true,
['contributor-first#'] = true,
['contributor#-first'] = true,
['contributor-given#'] = true,
['contributor#-given'] = true,
['contributor-last#'] = true,
['contributor#-last'] = true,
['contributor-surname#'] = true,
['contributor#-surname'] = true,
['contributor-link#'] = true,
['contributor#-link'] = true,
['contributor-mask#'] = true,
['contributor#-mask'] = true,
['editor#'] = true,
['editor-first#'] = true,
['editor#-first'] = true,
['editor-given#'] = true,
['editor#-given'] = true,
['editor-last#'] = true,
['editor#-last'] = true,
['editor-surname#'] = true,
['editor#-surname'] = true,
['editor-link#'] = true,
['editor#-link'] = true,
['editor-mask#'] = true,
['editor#-mask'] = true,
['first#'] = true,
['given#'] = true,
['host#'] = true,
['interviewer#'] = true,
['interviewer-first#'] = true,
['interviewer#-first'] = true,
['interviewer-given#'] = true,
['interviewer#-given'] = true,
['interviewer-last#'] = true,
['interviewer#-last'] = true,
['interviewer-surname#'] = true,
['interviewer#-surname'] = true,
['interviewer-link#'] = true,
['interviewer#-link'] = true,
['interviewer-mask#'] = true,
['interviewer#-mask'] = true,
['last#'] = true,
['subject#'] = true,
['subject-first#'] = true,
['subject#-first'] = true,
['subject-given#'] = true,
['subject#-given'] = true,
['subject-last#'] = true,
['subject#-last'] = true,
['subject-link#'] = true,
['subject#-link'] = true,
['subject-mask#'] = true,
['subject#-mask'] = true,
['subject-surname#'] = true,
['subject#-surname'] = true,
['surname#'] = true,
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-given#'] = true,
['translator#-given'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-surname#'] = true,
['translator#-surname'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
--[[--------------------------< P R E P R I N T S U P P O R T E D P A R A M E T E R S >--------------------
Cite arXiv, cite biorxiv, cite citeseerx, cite medrxiv, and cite ssrn are preprint templates that use the limited
set of parameters defined in the limited_basic_arguments and limited_numbered_arguments tables. Those lists are
supplemented with a template-specific list of parameters that are required by the particular template and may be
exclusive to one of the preprint templates. Some of these parameters may also be available to the general cs1|2
templates.
Same conventions for true/false/tracked/nil as above.
]]
local preprint_arguments_t = {
arxiv = {
['arxiv'] = true, -- cite arxiv and arxiv identifiers
['class'] = true,
['eprint'] = true, -- cite arxiv and arxiv identifiers
},
biorxiv = {
['biorxiv'] = true,
},
citeseerx = {
['citeseerx'] = false,
},
medrxiv = {
['medrxiv'] = true,
},
ssrn = {
['ssrn'] = true,
['SSRN'] = true,
['ssrn-access'] = true,
},
}
--[[--------------------------< L I M I T E D S U P P O R T E D P A R A M E T E R S >----------------------
cite arxiv, cite biorxiv, cite citeseerx, cite medrxiv, and cite ssrn templates are preprint templates so are
allowed only a limited subset of parameters allowed to all other cs1|2 templates. The limited subset is defined
here.
This list of parameters also used by {{cite document}}
Same conventions for true/false/tracked/nil as above.
]]
local limited_basic_arguments_t = {
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-given'] = true,
['author-last'] = true,
['author-surname'] = true,
['author-link'] = true,
['authorlink'] = true,
['author-mask'] = true,
['collaboration'] = true,
['date'] = true,
['df'] = true,
['display-authors'] = true,
['first'] = true,
['given'] = true,
['language'] = true,
['last'] = true,
['mode'] = true,
['name-list-style'] = true,
['no-tracking'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['postscript'] = true,
['pp'] = true,
['quotation'] = true,
['quote'] = true,
['ref'] = true,
['surname'] = true,
['template-doc-demo'] = true,
['title'] = true,
['trans-title'] = true,
['vauthors'] = true,
['year'] = true,
}
local limited_numbered_arguments_t = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-given#'] = true,
['author#-given'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-surname#'] = true,
['author#-surname'] = true,
['author-link#'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author#link'] = true,
['author-mask#'] = true,
['author#-mask'] = true,
['first#'] = true,
['given#'] = true,
['last#'] = true,
['surname#'] = true,
}
--[[--------------------------< U N I Q U E _ A R G U M E N T S >----------------------------------------------
Some templates have unique parameters. Those templates and their unique parameters are listed here. Keys in this
table are the template's CitationClass parameter value
Same conventions for true/false/tracked/nil as above.
]]
local unique_arguments_t = {
['audio-visual'] = {
['people'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcript-url'] = true,
},
conference = {
['book-title'] = true,
['conference'] = true,
['conference-format'] = true,
['conference-url'] = true,
['event'] = true,
},
episode = {
['airdate'] = true,
['air-date'] = true,
['credits'] = true,
['episode-link'] = true, -- alias of |title-link=
['network'] = true,
['people'] = true,
['season'] = true,
['series-link'] = true,
['series-no'] = true,
['series-number'] = true,
['station'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcript-url'] = true,
},
mailinglist = {
['mailing-list'] = true,
},
map = {
['cartography'] = true,
['inset'] = true,
['map'] = true,
['map-format'] = true,
['map-url'] = true,
['map-url-access'] = true,
['script-map'] = true,
['sections'] = true,
['sheet'] = true,
['sheets'] = true,
['trans-map'] = true,
},
newsgroup = {
['message-id'] = true,
['newsgroup'] = true,
},
report = {
['docket'] = true,
},
serial = {
['airdate'] = true,
['air-date'] = true,
['credits'] = true,
['episode'] = true, -- cite serial only TODO: make available to cite episode?
['episode-link'] = true, -- alias of |title-link=
['network'] = true,
['people'] = true,
['series-link'] = true,
['station'] = true,
},
speech = {
['conference'] = true,
['conference-format'] = true,
['conference-url'] = true,
['event'] = true,
},
thesis = {
['degree'] = true,
['docket'] = true,
},
}
--[[--------------------------< C I T E _ D O C U M E N T >----------------------------------------------------
Special case for cite document. This template takes the limited basic and limited enumerated parameters plus
others that are apply only to standalone published sources that cannot be cited any other way; no url, book,
periodical, etc parameters; limited support for name lists and named identifiers.
when validating parameters in {{cite document}} templates, the basic and
]]
local document_arguments_t = {
['bibcode'] = true,
['bibcode-access'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken-date'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['id'] = true,
['ID'] = true,
['jfm'] = true,
['JFM'] = true,
['lang'] = true,
['location'] = true,
['mr'] = true,
['MR'] = true,
['no-pp'] = true,
['orig-date'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['place'] = true,
['publisher'] = true,
['quote-page'] = true,
['quote-pages'] = true,
['script-quote'] = true,
['script-title'] = true,
['title-link'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-given'] = true,
['translator-last'] = true,
['translator-surname'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['trans-quote'] = true,
['type'] = true,
['zbl'] = true,
['ZBL'] = true,
}
local document_numbered_arguments_t = {
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-given#'] = true,
['translator#-given'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-surname#'] = true,
['translator#-surname'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
--[[--------------------------< L I S T _ C O M B I N E >------------------------------------------------------
makes one table from a list of tables. <lists_t> is a sequence of tables to be combined
]]
local function list_combine (lists_t)
local out_t = {};
for _, list_t in ipairs (lists_t) do -- for each list in <lists_t>
for k, v in pairs (list_t) do -- extract each k/v pair
out_t[k] = v; -- add to <out_t>
end
end
return out_t; -- and done
end
--[[--------------------------< T E M P L A T E _ L I S T _ G E T >--------------------------------------------
gets a list of the templates from table t
]]
local function template_list_get (t)
local out_t = {}; -- a table for output
for k, _ in pairs (t) do -- spin through the table and collect the keys
table.insert (out_t, k) -- add each key to the output table
end
return out_t; -- and done
end
--[[--------------------------< E X P O R T E D T A B L E S >------------------------------------------------
]]
return {
preprint_arguments_t = preprint_arguments_t,
preprint_template_list_t = template_list_get (preprint_arguments_t), -- make a template list from preprint_arguments{} table
unique_arguments_t = unique_arguments_t,
unique_param_template_list_t = template_list_get (unique_arguments_t), -- make a template list from unique_arguments{} table
document_parameters_t = list_combine ({limited_basic_arguments_t, limited_numbered_arguments_t, document_arguments_t, document_numbered_arguments_t});
common_parameters_t = list_combine ({basic_arguments_t, numbered_arguments_t});
limited_parameters_t = list_combine ({limited_basic_arguments_t, limited_numbered_arguments_t});
};
1livvij6p41ygpz0myvp2ov8j5lfzcj
Module:Citation/CS1/Utilities
828
927
9007
2026-08-08T13:56:45Z
en>Trappist the monk
0
synch from sandbox;
9007
Scribunto
text/plain
local z = {
error_cats_t = {}; -- for categorizing citations that contain errors
error_ids_t = {}; -- list of error identifiers; used to prevent duplication of certain errors; local to this module
error_msgs_t = {}; -- sequence table of error messages
maint_cats_t = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
prop_cats_t = {}; -- for categorizing citations based on certain properties, language of source for instance
prop_keys_t = {}; -- for adding classes to the citation's <cite> tag
};
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
]]
local function is_set (var)
return not (var == nil or var == '');
end
--[[--------------------------< I N _ A R R A Y >--------------------------------------------------------------
Whether needle is in haystack
]]
local function in_array (needle, haystack)
if needle == nil then
return false;
end
for n, v in ipairs (haystack) do
if v == needle then
return n;
end
end
return false;
end
--[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------
When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else
with allow_empty = false, <str> must have at least one character inside the markup
with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context.
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.
]]
local function has_accept_as_written (str, allow_empty)
if not is_set (str) then
return str, false;
end
local count;
if true == allow_empty then
str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set
else
str, count = str:gsub ('^%(%((.+)%)%)$', '%1');
end
return str, 0 ~= count;
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Populates numbered arguments in a message string using an argument table. <args> may be a single string or a
sequence table of multiple strings.
]]
local function substitute (msg, args)
return args and mw.message.newRawMessage (msg, args):plain() or msg;
end
--[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------
Wraps error messages with CSS markup according to the state of hidden. <content> may be a single string or a
sequence table of multiple strings.
]]
local function error_comment (content, hidden)
return substitute (hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content);
end
--[[--------------------------< H Y P H E N _ T O _ D A S H >--------------------------------------------------
Converts a hyphen, endash, emdash to endash under certain conditions. The hyphen/en/em must separate
like items; unlike items are returned unmodified. These forms are modified:
letter - letter (A-B)
digit - digit (4-5)
digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5)
letterdigit - letterdigit (A1-A5) (an optional separator between letter and
digit is supported – a.1-a.5 or a-1-a-5)
digitletter - digitletter (5a-5d) (an optional separator between letter and
digit is supported – 5.a-5.d or 5-a-5-d)
any other forms are returned unmodified.
str may be a comma- or semicolon-separated list of page ranges with/without single pages
]]
local function hyphen_to_dash (str)
if not is_set (str) then
return str;
end
str = str:gsub ("(%(%(.-%)%))", function(m) return m:gsub(",", ","):gsub(";", ";") end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they'll be ignored during the split
str = str:gsub ('&[nm]dash;', {['–'] = '–', ['—'] = '—'}); -- replace — and – entities with their characters; semicolon mucks up the text.split
str = str:gsub ('-', '-'); -- replace HTML numeric entity with hyphen character
str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character
local out = {};
local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any
local accept; -- boolean
for _, item in ipairs (list) do -- for each item in the list
item, accept = has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[—–-]%s*%w*[%.%-]?%w+$') then -- if pagination uses <hyphen|dot> separators with hyphen/endash/emdash <range separator>
if mw.ustring.match (item, '^%a+[%.%-]%d+%s*[—–-]%s*%a+[%.%-]%d+$') or -- letter<hyphen|dot>digit <range separator> letter<hyphen|dot>digit (requires <hyphen|dot> separator between letter and digit)
mw.ustring.match (item, '^%d+[%.%-]%a+%s*[—–-]%s*%d+[%.%-]%a+$') or -- digit<hyphen|dot>letter <range separator> digit<hyphen|dot>letter (requires <hyphen|dot> separator between digit and letter)
mw.ustring.match (item, '^%d+[%.%-]%d+%s*[—–-]%s*%d+[%.%-]%d+$') then -- digit<hyphen|dot>digit <range separator> digit<hyphen|dot>digit (requires <hyphen|dot> separator between digit and digit)
item = mw.ustring.gsub (item, '(%w*[%.%-]%w+)%s*[—–-]%s*(%w*[%.%-]%w+)', '<span class="nowrap">%1 –</span> <span class="nowrap">%2</span>'); -- replace <range separator>, with spaced endash
elseif mw.ustring.match (item, '^%d+%a+%s*[—–-]%s*%d+%a+$') or -- digitletter <range separator> digitletter
mw.ustring.match (item, '^%a+%d+%s*[—–-]%s*%a+%d+$') or -- letterdigit <range separator> letterdigit
mw.ustring.match (item, '^%d+%s*[—–-]%s*%d+$') or -- digit <range separator> digit
mw.ustring.match (item, '^%a+%s*[—–-]%s*%a+$') then -- letter<range separator> letter
item = mw.ustring.gsub (item, '(%w+)%s*[—–-]%s*(%w+)', '<span class="nowrap">%1–</span>%2'); -- replace <range separator> with endash, remove extraneous space characters
else
-- item = mw.ustring.gsub (item, '%s*[—–-]%s*', '–'); -- disabled; here when 'unlike' items so return <item> as is
end
end
table.insert (out, item); -- add the (possibly modified) item to the output table
end
local temp_str; -- concatenate the output table into a comma separated string
temp_str, accept = has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out
if accept then
temp_str = has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value
return temp_str:gsub(",", ","):gsub(";", ";");
else
return temp_str:gsub(",", ","):gsub(";", ";"); -- else, return assembled temp_str
end
end
--[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are
provided or link is omitted, returns an empty string.
]=]
local function make_wikilink (link, display)
if not is_set (link) then return '' end
if is_set (display) and link ~= display then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
end
--[[--------------------------< S E T _ M E S S A G E >----------------------------------------------------------
Sets an error message using the ~/Configuration error_conditions{} table along with arguments supplied in the function
call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message.
<error_id> – key value for appropriate error handler in ~/Configuration error_conditions{} table
<arguments> – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message
<raw> – boolean
true – causes this function to return the error message not wrapped in visible-error, hidden-error span tag;
returns error_conditions[error_id].hidden as a second return value
does not add message to z.error_msgs_t sequence table
false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t
returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value
<prefix> – string to be prepended to <message> -- TODO: remove support for these unused(?) arguments?
<suffix> – string to be appended to <message>
TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true? this to avoid dups without having to have an extra table
]]
local added_maint_cats = {} -- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table
local function set_message (error_id, arguments, raw, prefix, suffix)
local error_state = cfg.error_conditions[error_id];
prefix = prefix or '';
suffix = suffix or '';
if error_state == nil then
error (cfg.messages['undefined_error'] .. ': ' .. error_id); -- because missing error handler in Module:Citation/CS1/Configuration
elseif is_set (error_state.category) then
if error_state.message then -- when error_state.message defined, this is an error message
table.insert (z.error_cats_t, error_state.category);
else
if not added_maint_cats[error_id] then
added_maint_cats[error_id] = true; -- note that we've added this category
table.insert (z.maint_cats_t, substitute (error_state.category, arguments)); -- make cat name then add to table
end
return; -- because no message, nothing more to do
end
end
local message = substitute (error_state.message, arguments);
message = table.concat (
{
message,
' (',
make_wikilink (
table.concat (
{
cfg.messages['help page link'],
'#',
error_state.anchor
}),
cfg.messages['help page label']),
')'
});
z.error_ids_t[error_id] = true;
if z.error_ids_t['err_citation_missing_title'] and -- if missing-title error already noted
in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these
return '', false; -- don't bother because one flavor of missing title is sufficient
end
message = table.concat ({prefix, message, suffix});
if true == raw then
return message, error_state.hidden; -- return message not wrapped in visible-error, hidden-error span tag
end
message = error_comment (message, error_state.hidden); -- wrap message in visible-error, hidden-error span tag
table.insert (z.error_msgs_t, message); -- add it to the messages sequence table
return message; -- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers
end
--[[-------------------------< I S _ A L I A S _ U S E D >-----------------------------------------------------
This function is used by select_one() to determine if one of a list of alias parameters is in the argument list
provided by the template.
Input:
args – pointer to the arguments table from calling template
alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
index – for enumerated parameters, identifies which one
enumerated – true/false flag used to choose how enumerated aliases are examined
value – value associated with an alias that has previously been selected; nil if not yet selected
selected – the alias that has previously been selected; nil if not yet selected
error_list – list of aliases that are duplicates of the alias already selected
Returns:
value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected
selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected
]]
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)
if enumerated then -- is this a test for an enumerated parameters?
alias = alias:gsub ('#', index); -- replace '#' with the value in index
else
alias = alias:gsub ('#', ''); -- remove '#' if it exists
end
if is_set (args[alias]) then -- alias is in the template's argument list
if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
local skip;
for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias
if v == alias then
skip = true;
break; -- has been added so stop looking
end
end
if not skip then -- has not been added so
table.insert (error_list, alias); -- add error alias to the error list
end
else
value = args[alias]; -- not yet selected an alias, so select this one
selected = alias;
end
end
return value, selected; -- return newly selected alias, or previously selected alias
end
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
Adds a category to z.maint_cats_t using names from the configuration file with additional text if any.
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t.
]]
local function add_maint_cat (key, arguments)
if not added_maint_cats [key] then
added_maint_cats [key] = true; -- note that we've added this category
table.insert (z.maint_cats_t, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table
end
end
--[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
Adds a category to z.prop_cats_t using names from the configuration file with additional text if any.
foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages
may be categorized but multiples of the same language are not categorized.
added_prop_cats is a table declared in page scope variables above
]]
local added_prop_cats = {}; -- list of property categories that have been added to z.prop_cats_t
local function add_prop_cat (key, arguments, key_modifier)
local key_modified = key .. ((key_modifier and key_modifier) or ''); -- modify <key> with <key_modifier> if present and not nil
if not added_prop_cats [key_modified] then
added_prop_cats [key_modified] = true; -- note that we've added this category
table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table
table.insert (z.prop_keys_t, 'cs1-prop-' .. key); -- convert key to class for use in the citation's <cite> tag
end
end
--[[--------------------------< S A F E _ F O R _ I T A L I C S >----------------------------------------------
Protects a string that will be wrapped in wiki italic markup '' ... ''
Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that
they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact
poorly under Mediawiki's HTML tidy.
]]
local function safe_for_italics (str)
if not is_set (str) then return str end
if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end
if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end
return str:gsub ('\n', ' '); -- Remove newlines as they break italics.
end
--[[--------------------------< W R A P _ S T Y L E >----------------------------------------------------------
Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one
argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason
this function is similar to but separate from wrap_msg().
]]
local function wrap_style (key, str)
if not is_set (str) then
return "";
elseif in_array (key, {'italic-title', 'trans-italic-title'}) then
str = safe_for_italics (str);
end
return substitute (cfg.presentation[key], {str});
end
--[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------
make a separated list of items using provided separators.
<sep_list> - typically '<comma><space>'
<sep_list_pair> - typically '<space>and<space>'
<sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>'
defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']
if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied
]]
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)
local list = '';
if not sep_list then -- set the defaults
sep_list = cfg.presentation['sep_list'];
sep_list_pair = cfg.presentation['sep_list_pair'];
sep_list_end = cfg.presentation['sep_list_end'];
end
if 2 >= count then
list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item
elseif 2 < count then
list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator
list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator
end
return list;
end
--[[--------------------------< S E L E C T _ O N E >----------------------------------------------------------
Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just
names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified
by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'.
Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities.
Generates an error if more than one match is present.
]]
local function select_one (args, aliases_list, error_condition, index)
local value = nil; -- the value assigned to the selected parameter
local selected = ''; -- the name of the parameter we have chosen
local error_list = {};
if index ~= nil then index = tostring(index); end
for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list
if alias:match ('#') then -- if this alias can be enumerated
if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
end
value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
else
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- test for non-enumerated alias
end
end
if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
for i, v in ipairs (error_list) do
error_list[i] = wrap_style ('parameter', v);
end
table.insert (error_list, wrap_style ('parameter', selected));
set_message (error_condition, {make_sep_list (#error_list, error_list)});
end
return value, selected;
end
--[=[-------------------------< R E M O V E _ W I K I _ L I N K >----------------------------------------------
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label
if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match
in the initial gsub, the replacement function l() doesn't get called.
]=]
local function remove_wiki_link (str)
return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l)
return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1");
end));
end
--[=[-------------------------< I S _ W I K I L I N K >--------------------------------------------------------
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.
If str is a complex wikilink ([[L|D]]):
returns wl_type 2 and D and L from [[L|D]];
if str is a simple wikilink ([[D]])
returns wl_type 1 and D from [[D]] and L as empty string;
if not a wikilink:
returns wl_type 0, str as D, and L as empty string.
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).
]=]
local function is_wikilink (str)
local D, L
local wl_type = 2; -- assume that str is a complex wikilink [[L|D]]
if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content)
return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L
end
L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]]
if not is_set (D) then -- if no separate display
D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]]
wl_type = 1;
end
D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters
return wl_type, D, L or '';
end
--[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >--------------------------------
Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata.
This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to
markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind.
Returns the argument without wiki markup and a number; the number is more-or-less meaningless except as a flag
to indicate that markup was replaced; do not rely on it as an indicator of how many of any kind of markup was
removed; returns the argument and nil when no markup removed
]]
local function strip_apostrophe_markup (argument)
if not is_set (argument) then
return argument, nil; -- no argument, nothing to do
end
if nil == argument:find ( "''", 1, true ) then -- Is there at least one double apostrophe? If not, exit.
return argument, nil;
end
local flag;
while true do
if argument:find ("'''''", 1, true) then -- bold italic (5)
argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it
elseif argument:find ("''''", 1, true) then -- italic start and end without content (4)
argument, flag=argument:gsub ("%'%'%'%'", "");
elseif argument:find ("'''", 1, true) then -- bold (3)
argument, flag=argument:gsub ("%'%'%'", "");
elseif argument:find ("''", 1, true) then -- italic (2)
argument, flag = argument:gsub ("%'%'", "");
else
break;
end
end
return argument, flag; -- done
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr)
cfg = cfg_table_ptr;
end
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
add_maint_cat = add_maint_cat, -- exported functions
add_prop_cat = add_prop_cat,
error_comment = error_comment,
has_accept_as_written = has_accept_as_written,
hyphen_to_dash = hyphen_to_dash,
in_array = in_array,
is_set = is_set,
is_wikilink = is_wikilink,
make_sep_list = make_sep_list,
make_wikilink = make_wikilink,
remove_wiki_link = remove_wiki_link,
safe_for_italics = safe_for_italics,
select_one = select_one,
set_message = set_message,
set_selected_modules = set_selected_modules,
strip_apostrophe_markup = strip_apostrophe_markup,
substitute = substitute,
wrap_style = wrap_style,
z = z, -- exported table
}
bvyfrlfh7kkrrt2v6jk2f3z13girav4
9008
8258
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/Utilities]]
8258
Scribunto
text/plain
local z = {
error_cats_t = {}; -- for categorizing citations that contain errors
error_ids_t = {}; -- list of error identifiers; used to prevent duplication of certain errors; local to this module
error_msgs_t = {}; -- sequence table of error messages
maint_cats_t = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
prop_cats_t = {}; -- for categorizing citations based on certain properties, language of source for instance
prop_keys_t = {}; -- for adding classes to the citation's <cite> tag
};
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
]]
local function is_set (var)
return not (var == nil or var == '');
end
--[[--------------------------< I N _ A R R A Y >--------------------------------------------------------------
Whether needle is in haystack
]]
local function in_array (needle, haystack)
if needle == nil then
return false;
end
for n, v in ipairs (haystack) do
if v == needle then
return n;
end
end
return false;
end
--[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------
When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else
with allow_empty = false, <str> must have at least one character inside the markup
with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context.
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.
]]
local function has_accept_as_written (str, allow_empty)
if not is_set (str) then
return str, false;
end
local count;
if true == allow_empty then
str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set
else
str, count = str:gsub ('^%(%((.+)%)%)$', '%1');
end
return str, 0 ~= count;
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Populates numbered arguments in a message string using an argument table. <args> may be a single string or a
sequence table of multiple strings.
]]
local function substitute (msg, args)
return args and mw.message.newRawMessage (msg, args):plain() or msg;
end
--[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------
Wraps error messages with CSS markup according to the state of hidden. <content> may be a single string or a
sequence table of multiple strings.
]]
local function error_comment (content, hidden)
return substitute (hidden and cfg.presentation['hidden-error'] or cfg.presentation['visible-error'], content);
end
--[[--------------------------< H Y P H E N _ T O _ D A S H >--------------------------------------------------
Converts a hyphen, endash, emdash to endash under certain conditions. The hyphen/en/em must separate
like items; unlike items are returned unmodified. These forms are modified:
letter - letter (A-B)
digit - digit (4-5)
digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5)
letterdigit - letterdigit (A1-A5) (an optional separator between letter and
digit is supported – a.1-a.5 or a-1-a-5)
digitletter - digitletter (5a-5d) (an optional separator between letter and
digit is supported – 5.a-5.d or 5-a-5-d)
any other forms are returned unmodified.
str may be a comma- or semicolon-separated list of page ranges with/without single pages
]]
local function hyphen_to_dash (str)
if not is_set (str) then
return str;
end
str = str:gsub ("(%(%(.-%)%))", function(m) return m:gsub(",", ","):gsub(";", ";") end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they'll be ignored during the split
str = str:gsub ('&[nm]dash;', {['–'] = '–', ['—'] = '—'}); -- replace — and – entities with their characters; semicolon mucks up the text.split
str = str:gsub ('-', '-'); -- replace HTML numeric entity with hyphen character
str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character
local out = {};
local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any
local accept; -- boolean
for _, item in ipairs (list) do -- for each item in the list
item, accept = has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[—–-]%s*%w*[%.%-]?%w+$') then -- if pagination uses <hyphen|dot> separators with hyphen/endash/emdash <range separator>
if mw.ustring.match (item, '^%a+[%.%-]%d+%s*[—–-]%s*%a+[%.%-]%d+$') or -- letter<hyphen|dot>digit <range separator> letter<hyphen|dot>digit (requires <hyphen|dot> separator between letter and digit)
mw.ustring.match (item, '^%d+[%.%-]%a+%s*[—–-]%s*%d+[%.%-]%a+$') or -- digit<hyphen|dot>letter <range separator> digit<hyphen|dot>letter (requires <hyphen|dot> separator between digit and letter)
mw.ustring.match (item, '^%d+[%.%-]%d+%s*[—–-]%s*%d+[%.%-]%d+$') then -- digit<hyphen|dot>digit <range separator> digit<hyphen|dot>digit (requires <hyphen|dot> separator between digit and digit)
item = mw.ustring.gsub (item, '(%w*[%.%-]%w+)%s*[—–-]%s*(%w*[%.%-]%w+)', '<span class="nowrap">%1 –</span> <span class="nowrap">%2</span>'); -- replace <range separator>, with spaced endash
elseif mw.ustring.match (item, '^%d+%a+%s*[—–-]%s*%d+%a+$') or -- digitletter <range separator> digitletter
mw.ustring.match (item, '^%a+%d+%s*[—–-]%s*%a+%d+$') or -- letterdigit <range separator> letterdigit
mw.ustring.match (item, '^%d+%s*[—–-]%s*%d+$') or -- digit <range separator> digit
mw.ustring.match (item, '^%a+%s*[—–-]%s*%a+$') then -- letter<range separator> letter
item = mw.ustring.gsub (item, '(%w+)%s*[—–-]%s*(%w+)', '<span class="nowrap">%1–</span>%2'); -- replace <range separator> with endash, remove extraneous space characters
else
-- item = mw.ustring.gsub (item, '%s*[—–-]%s*', '–'); -- disabled; here when 'unlike' items so return <item> as is
end
end
table.insert (out, item); -- add the (possibly modified) item to the output table
end
local temp_str; -- concatenate the output table into a comma separated string
temp_str, accept = has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out
if accept then
temp_str = has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value
return temp_str:gsub(",", ","):gsub(";", ";");
else
return temp_str:gsub(",", ","):gsub(";", ";"); -- else, return assembled temp_str
end
end
--[=[-------------------------< M A K E _ W I K I L I N K >----------------------------------------------------
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are
provided or link is omitted, returns an empty string.
]=]
local function make_wikilink (link, display)
if not is_set (link) then return '' end
if is_set (display) and link ~= display then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
end
--[[--------------------------< S E T _ M E S S A G E >----------------------------------------------------------
Sets an error message using the ~/Configuration error_conditions{} table along with arguments supplied in the function
call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message.
<error_id> – key value for appropriate error handler in ~/Configuration error_conditions{} table
<arguments> – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message
<raw> – boolean
true – causes this function to return the error message not wrapped in visible-error, hidden-error span tag;
returns error_conditions[error_id].hidden as a second return value
does not add message to z.error_msgs_t sequence table
false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t
returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value
<prefix> – string to be prepended to <message> -- TODO: remove support for these unused(?) arguments?
<suffix> – string to be appended to <message>
TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true? this to avoid dups without having to have an extra table
]]
local added_maint_cats = {} -- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table
local function set_message (error_id, arguments, raw, prefix, suffix)
local error_state = cfg.error_conditions[error_id];
prefix = prefix or '';
suffix = suffix or '';
if error_state == nil then
error (cfg.messages['undefined_error'] .. ': ' .. error_id); -- because missing error handler in Module:Citation/CS1/Configuration
elseif is_set (error_state.category) then
if error_state.message then -- when error_state.message defined, this is an error message
table.insert (z.error_cats_t, error_state.category);
else
if not added_maint_cats[error_id] then
added_maint_cats[error_id] = true; -- note that we've added this category
table.insert (z.maint_cats_t, substitute (error_state.category, arguments)); -- make cat name then add to table
end
return; -- because no message, nothing more to do
end
end
local message = substitute (error_state.message, arguments);
message = table.concat (
{
message,
' (',
make_wikilink (
table.concat (
{
cfg.messages['help page link'],
'#',
error_state.anchor
}),
cfg.messages['help page label']),
')'
});
z.error_ids_t[error_id] = true;
if z.error_ids_t['err_citation_missing_title'] and -- if missing-title error already noted
in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then -- and this error is one of these
return '', false; -- don't bother because one flavor of missing title is sufficient
end
message = table.concat ({prefix, message, suffix});
if true == raw then
return message, error_state.hidden; -- return message not wrapped in visible-error, hidden-error span tag
end
message = error_comment (message, error_state.hidden); -- wrap message in visible-error, hidden-error span tag
table.insert (z.error_msgs_t, message); -- add it to the messages sequence table
return message; -- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers
end
--[[-------------------------< I S _ A L I A S _ U S E D >-----------------------------------------------------
This function is used by select_one() to determine if one of a list of alias parameters is in the argument list
provided by the template.
Input:
args – pointer to the arguments table from calling template
alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
index – for enumerated parameters, identifies which one
enumerated – true/false flag used to choose how enumerated aliases are examined
value – value associated with an alias that has previously been selected; nil if not yet selected
selected – the alias that has previously been selected; nil if not yet selected
error_list – list of aliases that are duplicates of the alias already selected
Returns:
value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected
selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected
]]
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)
if enumerated then -- is this a test for an enumerated parameters?
alias = alias:gsub ('#', index); -- replace '#' with the value in index
else
alias = alias:gsub ('#', ''); -- remove '#' if it exists
end
if is_set (args[alias]) then -- alias is in the template's argument list
if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
local skip;
for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias
if v == alias then
skip = true;
break; -- has been added so stop looking
end
end
if not skip then -- has not been added so
table.insert (error_list, alias); -- add error alias to the error list
end
else
value = args[alias]; -- not yet selected an alias, so select this one
selected = alias;
end
end
return value, selected; -- return newly selected alias, or previously selected alias
end
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
Adds a category to z.maint_cats_t using names from the configuration file with additional text if any.
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t.
]]
local function add_maint_cat (key, arguments)
if not added_maint_cats [key] then
added_maint_cats [key] = true; -- note that we've added this category
table.insert (z.maint_cats_t, substitute (cfg.maint_cats [key], arguments)); -- make name then add to table
end
end
--[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
Adds a category to z.prop_cats_t using names from the configuration file with additional text if any.
foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages
may be categorized but multiples of the same language are not categorized.
added_prop_cats is a table declared in page scope variables above
]]
local added_prop_cats = {}; -- list of property categories that have been added to z.prop_cats_t
local function add_prop_cat (key, arguments, key_modifier)
local key_modified = key .. ((key_modifier and key_modifier) or ''); -- modify <key> with <key_modifier> if present and not nil
if not added_prop_cats [key_modified] then
added_prop_cats [key_modified] = true; -- note that we've added this category
table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table
table.insert (z.prop_keys_t, 'cs1-prop-' .. key); -- convert key to class for use in the citation's <cite> tag
end
end
--[[--------------------------< S A F E _ F O R _ I T A L I C S >----------------------------------------------
Protects a string that will be wrapped in wiki italic markup '' ... ''
Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that
they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact
poorly under Mediawiki's HTML tidy.
]]
local function safe_for_italics (str)
if not is_set (str) then return str end
if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end
if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end
return str:gsub ('\n', ' '); -- Remove newlines as they break italics.
end
--[[--------------------------< W R A P _ S T Y L E >----------------------------------------------------------
Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one
argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason
this function is similar to but separate from wrap_msg().
]]
local function wrap_style (key, str)
if not is_set (str) then
return "";
elseif in_array (key, {'italic-title', 'trans-italic-title'}) then
str = safe_for_italics (str);
end
return substitute (cfg.presentation[key], {str});
end
--[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------
make a separated list of items using provided separators.
<sep_list> - typically '<comma><space>'
<sep_list_pair> - typically '<space>and<space>'
<sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>'
defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']
if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied
]]
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)
local list = '';
if not sep_list then -- set the defaults
sep_list = cfg.presentation['sep_list'];
sep_list_pair = cfg.presentation['sep_list_pair'];
sep_list_end = cfg.presentation['sep_list_end'];
end
if 2 >= count then
list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item
elseif 2 < count then
list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator
list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator
end
return list;
end
--[[--------------------------< S E L E C T _ O N E >----------------------------------------------------------
Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just
names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified
by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'.
Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities.
Generates an error if more than one match is present.
]]
local function select_one (args, aliases_list, error_condition, index)
local value = nil; -- the value assigned to the selected parameter
local selected = ''; -- the name of the parameter we have chosen
local error_list = {};
if index ~= nil then index = tostring(index); end
for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list
if alias:match ('#') then -- if this alias can be enumerated
if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
end
value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
else
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- test for non-enumerated alias
end
end
if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
for i, v in ipairs (error_list) do
error_list[i] = wrap_style ('parameter', v);
end
table.insert (error_list, wrap_style ('parameter', selected));
set_message (error_condition, {make_sep_list (#error_list, error_list)});
end
return value, selected;
end
--[=[-------------------------< R E M O V E _ W I K I _ L I N K >----------------------------------------------
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label
if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match
in the initial gsub, the replacement function l() doesn't get called.
]=]
local function remove_wiki_link (str)
return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l)
return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1");
end));
end
--[=[-------------------------< I S _ W I K I L I N K >--------------------------------------------------------
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.
If str is a complex wikilink ([[L|D]]):
returns wl_type 2 and D and L from [[L|D]];
if str is a simple wikilink ([[D]])
returns wl_type 1 and D from [[D]] and L as empty string;
if not a wikilink:
returns wl_type 0, str as D, and L as empty string.
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).
]=]
local function is_wikilink (str)
local D, L
local wl_type = 2; -- assume that str is a complex wikilink [[L|D]]
if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content)
return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L
end
L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]]
if not is_set (D) then -- if no separate display
D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]]
wl_type = 1;
end
D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters
return wl_type, D, L or '';
end
--[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >--------------------------------
Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata.
This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to
markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind.
Returns the argument without wiki markup and a number; the number is more-or-less meaningless except as a flag
to indicate that markup was replaced; do not rely on it as an indicator of how many of any kind of markup was
removed; returns the argument and nil when no markup removed
]]
local function strip_apostrophe_markup (argument)
if not is_set (argument) then
return argument, nil; -- no argument, nothing to do
end
if nil == argument:find ( "''", 1, true ) then -- Is there at least one double apostrophe? If not, exit.
return argument, nil;
end
local flag;
while true do
if argument:find ("'''''", 1, true) then -- bold italic (5)
argument, flag = argument:gsub ("%'%'%'%'%'", ""); -- remove all instances of it
elseif argument:find ("''''", 1, true) then -- italic start and end without content (4)
argument, flag=argument:gsub ("%'%'%'%'", "");
elseif argument:find ("'''", 1, true) then -- bold (3)
argument, flag=argument:gsub ("%'%'%'", "");
elseif argument:find ("''", 1, true) then -- italic (2)
argument, flag = argument:gsub ("%'%'", "");
else
break;
end
end
return argument, flag; -- done
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr)
cfg = cfg_table_ptr;
end
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
add_maint_cat = add_maint_cat, -- exported functions
add_prop_cat = add_prop_cat,
error_comment = error_comment,
has_accept_as_written = has_accept_as_written,
hyphen_to_dash = hyphen_to_dash,
in_array = in_array,
is_set = is_set,
is_wikilink = is_wikilink,
make_sep_list = make_sep_list,
make_wikilink = make_wikilink,
remove_wiki_link = remove_wiki_link,
safe_for_italics = safe_for_italics,
select_one = select_one,
set_message = set_message,
set_selected_modules = set_selected_modules,
strip_apostrophe_markup = strip_apostrophe_markup,
substitute = substitute,
wrap_style = wrap_style,
z = z, -- exported table
}
bvyfrlfh7kkrrt2v6jk2f3z13girav4
Module:Citation/CS1/Date validation
828
928
9009
2026-08-08T13:56:49Z
en>Trappist the monk
0
synch from sandbox;
9009
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local add_prop_cat, is_set, in_array, set_message, substitute, wrap_style; -- imported functions from selected Module:Citation/CS1/Utilities
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< F I L E - S C O P E D E C L A R A T I O N S >--------------------------------
File-scope variables are declared here
]]
local lang_obj = mw.getContentLanguage(); -- used by is_valid_accessdate(), is_valid_year(), date_name_xlate();
local year_limit; -- used by is_valid_year()
--[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
returns true if:
Wikipedia start date <= accessdate < today + 2 days
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)
accessdate is the date provided in |access-date= at time 00:00:00 UTC
today is the current date at time 00:00:00 UTC plus 48 hours
if today is 2015-01-01T00:00:00 then
adding 24 hours gives 2015-01-02T00:00:00 – one second more than today
adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow
This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser
apparently doesn't understand non-English date month names. This function will always return false when the date
contains a non-English month name because good1 is false after the call to lang.formatDate(). To get around that
call this function with YYYY-MM-DD format dates.
]=]
local function is_valid_accessdate (accessdate)
local good1, good2;
local access_ts, tomorrow_ts; -- to hold Unix time stamps representing the dates
good1, access_ts = pcall (lang_obj.formatDate, lang_obj, 'U', accessdate ); -- convert accessdate value to Unix timestamp
good2, tomorrow_ts = pcall (lang_obj.formatDate, lang_obj, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which which tonumber() may not understand
access_ts = tonumber (access_ts) or lang_obj:parseFormattedNumber (access_ts); -- convert to numbers for the comparison;
tomorrow_ts = tonumber (tomorrow_ts) or lang_obj:parseFormattedNumber (tomorrow_ts);
else
return false; -- one or both failed to convert to Unix time stamp
end
if 979516800 <= access_ts and access_ts < tomorrow_ts then -- Wikipedia start date <= accessdate < tomorrow's date
return true;
else
return false; -- accessdate out of range
end
end
--[[--------------------------< G E T _ M O N T H _ N U M B E R >----------------------------------------------
returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct.
If not a valid month, returns 0
]]
local function get_month_number (month)
return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first
cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names
0; -- not a recognized month name
end
--[[--------------------------< G E T _ S E A S O N _ N U M B E R >--------------------------------------------
returns a number according to the sequence of seasons in a year: 21 for Spring, etc. Capitalization and spelling
must be correct. If not a valid season, returns 0.
21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere”
returns 0 when <param> is not |date=
Season numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons. EDTF does support the distinction between north and south
hemisphere seasons but cs1|2 has no way to make that distinction.
These additional divisions not currently supported:
25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere
29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)
]]
local function get_season_number (season, param)
if 'date' ~= param then
return 0; -- season dates only supported by |date=
end
return cfg.date_names['local'].season[season] or -- look for local names first
cfg.date_names['en'].season[season] or -- failing that, look for English names
0; -- not a recognized season name
end
--[[--------------------------< G E T _ Q U A R T E R _ N U M B E R >------------------------------------------
returns a number according to the sequence of quarters in a year: 33 for first quarter, etc. Capitalization and spelling
must be correct. If not a valid quarter, returns 0.
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
returns 0 when <param> is not |date=
Quarter numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons and quarters.
These additional divisions not currently supported:
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)
]]
local function get_quarter_number (quarter, param)
if 'date' ~= param then
return 0; -- quarter dates only supported by |date=
end
quarter = mw.ustring.gsub (quarter, ' +', ' '); -- special case replace multiple space chars with a single space char
return cfg.date_names['local'].quarter[quarter] or -- look for local names first
cfg.date_names['en'].quarter[quarter] or -- failing that, look for English names
0; -- not a recognized quarter name
end
--[[--------------------------< G E T _ P R O P E R _ N A M E _ N U M B E R >----------------------------------
returns a non-zero number if date contains a recognized proper-name. Capitalization and spelling must be correct.
returns 0 when <param> is not |date=
]]
local function get_proper_name_number (name, param)
if 'date' ~= param then
return 0; -- proper-name dates only supported by |date=
end
return cfg.date_names['local'].named[name] or -- look for local names dates first
cfg.date_names['en'].named[name] or -- failing that, look for English names
0; -- not a recognized named date
end
--[[--------------------------< G E T _ E L E M E N T _ N U M B E R <------------------------------------------
returns true if month or season or quarter or proper name is valid (properly spelled, capitalized, abbreviated)
]]
local function get_element_number (element, param)
local num;
local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number}; -- list of functions to execute in order
for _, func in ipairs (funcs) do -- spin through the function list
num = func (element, param); -- call the function and get the returned number
if 0 ~= num then -- non-zero when valid month season quarter
return num; -- return that number
end
end
return nil; -- not valid
end
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
Function gets current year from the server and compares it to year from a citation parameter. Years more than one
year in the future are not acceptable.
Special case for |pmc-embargo-date=: years more than two years in the future are not acceptable
]]
local function is_valid_year (year, param)
if not is_set (year_limit) then
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once
end
year = tonumber (year) or lang_obj:parseFormattedNumber (year); -- convert to number for the comparison
if year and (100 > year) then -- years less than 100 not supported
return false;
end
if 'pmc-embargo-date' == param then -- special case for |pmc-embargo-date=
return year and (year <= tonumber(os.date("%Y"))+2) or false; -- years more than two years in the future are not accepted
end
return year and (year <= year_limit) or false;
end
--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------
Returns true if day is less than or equal to the number of days in month and year is no farther into the future
than next year; else returns false.
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately
1923) dates are assumed to be Gregorian.
]]
local function is_valid_date (year, month, day, param)
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
if not is_valid_year (year, param) then -- no farther into the future than next year except |pmc-embargo-date= no more than two years in the future
return false;
end
month = tonumber (month); -- required for YYYY-MM-DD dates
if (2 == month) then -- if February
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0 == (year%4) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
else -- Gregorian calendar
if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
end
else
month_length = days_in_month[month] or 0; -- invalid month number is nil so default <month_length> to 0
end
if tonumber (day) > month_length then
return false;
end
return true;
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >--------------------------
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August.
This function looks in cfg.date_names{} to see if both month names are listed in the long subtable or both are
listed in the short subtable. When both have the same style (both are listed in the same table), returns true; false else
]]
local function is_valid_month_range_style (month1, month2)
if (cfg.date_names.en.long[month1] and cfg.date_names.en.long[month2]) or -- are both English names listed in the long subtable?
(cfg.date_names.en.short[month1] and cfg.date_names.en.short[month2]) or -- are both English names listed in the short subtable?
(cfg.date_names['local'].long[month1] and cfg.date_names['local'].long[month2]) or -- are both local names listed in the long subtable?
(cfg.date_names['local'].short[month1] and cfg.date_names['local'].short[month2]) then -- are both local names listed in the short subtable?
return true;
end
return false; -- names are mixed
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------
Check a pair of months or seasons to see if both are valid members of a month or season pair.
Month pairs are expected to be left to right, earliest to latest in time.
All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue, hence treat as ok
]]
local function is_valid_month_season_range(range_start, range_end, param)
local range_start_number = get_month_number (range_start);
local range_end_number;
if 0 == range_start_number then -- is this a month range?
range_start_number = get_season_number (range_start, param); -- not a month; is it a season? get start season number
range_end_number = get_season_number (range_end, param); -- get end season number
if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then
return true; -- any season pairing is accepted except when both are the same
end
return false; -- range_start and/or range_end is not a season
end
-- here when range_start is a month
range_end_number = get_month_number (range_end); -- get end month number
if range_start_number < range_end_number and -- range_start is a month; does range_start precede range_end?
is_valid_month_range_style (range_start, range_end) then -- do months have the same style?
return true; -- proper order and same style
end
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month
end
--[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------
This function receives a table of date parts for one or two dates and an empty table reference declared in
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is
determined to be a valid date format. The question of what to do with invalid date formats is not answered here.
The date parts in the input table are converted to an ISO 8601 conforming date string:
single whole dates: yyyy-mm-dd
month and year dates: yyyy-mm
year dates: yyyy
ranges: yyyy-mm-dd/yyyy-mm-dd
yyyy-mm/yyyy-mm
yyyy/yyyy
Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from
Julian to Proleptic Gregorian.
The input table has:
year, year2 – always present; if before 1582, ignore months and days if present
month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas
day, day2 – 0 if not provided, 1-31 for days
the output table receives:
rftdate: an ISO 8601 formatted date
rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates)
rftssn: one of four season keywords: winter, spring, summer, fall (lowercase)
rftquarter: one of four values: 1, 2, 3, 4
]]
local function make_COinS_date (input, COinS_date_t)
local date; -- one date or first date in a range
local date2 = ''; -- end of range date
input.year = tonumber (input.year) or lang_obj:parseFormattedNumber (input.year); -- language-aware tonumber()
input.year2 = tonumber (input.year2) or lang_obj:parseFormattedNumber (input.year2); -- COinS dates are pseudo-ISO 8601 so convert to Arabic numerals
if ((1582 == input.year) and (10 > tonumber(input.month))) or (1582 > input.year) then -- if a Julian calendar date
COinS_date_t.rftdate = tostring (input.year); -- &rft.date gets year only
return; -- done
end
-- here for all forms of Gregorian dates
if 20 < tonumber (input.month) then -- if season, quarter, or proper-name date
date = input.year; -- &rft.date gets year only
if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year
date = string.format ('%.4d/%.4d', input.year, input.year2) -- assemble the date range
end
local season = {[24] = 'winter', [21] = 'spring', [22] = 'summer', [23] = 'fall', [33] = '1', [34] = '2', [35] = '3', [36] = '4', [98] = 'Easter', [99] = 'Christmas'}; -- seasons lowercase, no autumn; proper-names use title case
if 0 == input.month2 then -- single season, quarter, or proper-name date
if 40 < tonumber(input.month) then
COinS_date_t.rftchron = season[input.month]; -- proper-name date; used in journal metadata only
elseif 30 < tonumber(input.month) then
COinS_date_t.rftquarter = season[input.month]; -- quarter date; used in journal metadata only
else
COinS_date_t.rftssn = season[input.month]; -- season date; used in journal metadata only
end
else -- season ranges are lumped into &rft.chron; &rft.ssn and &rft.quarter are left blank
if input.year ~= input.year2 then -- season year – season year range or season year–year
if 0 ~= input.month2 then
COinS_date_t.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2); -- used in journal metadata only
end
else -- season–season year range
COinS_date_t.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range; used in journal metadata only
end
end
COinS_date_t.rftdate = tostring (date);
return; -- done
end
-- here for gregorian calendar dates
if 0 ~= input.day then
date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date
elseif 0 ~= input.month then
date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month
else
date = string.format ('%s', input.year); -- just year
end
if 0 ~= input.year2 then
if 0 ~= input.day2 then
date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date
elseif 0 ~= input.month2 then
date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month
else
date2 = string.format ('/%s', input.year2); -- just year
end
end
COinS_date_t.rftdate = date .. date2; -- date2 has the '/' separator
return;
end
--[[--------------------------< P A T T E R N S _ T >----------------------------------------------------------
this is the list of patterns for date formats that this module recognizes. Approximately the first half of these
patterns represent formats that might be reformatted into another format. Those that might be reformatted have
'indicator' letters that identify the content of the matching capture: 'd' (day), 'm' (month), 'a' (anchor year),
'y' (year); second day, month, year have a '2' suffix.
These patterns are used for both date validation and for reformatting. This table should not be moved to ~/Configuration
because changes to this table require changes to check_date() and to reformatter() and reformat_date()
]]
local patterns_t = {
-- year-initial numerical year-month-day
['ymd'] = {'^([1-9]%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'},
-- month-initial: month day, year
['Mdy'] = {'^(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'a', 'y'},
-- month-initial day range: month day–day, year; days are separated by endash
['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'd2', 'a', 'y'},
-- day-initial: day month year
['dMy'] = {'^([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'a', 'y'},
-- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki
-- ['yMd'] = {'^(([1-9]%d%d%d?)%l?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'},
-- day-range-initial: day–day month year; days are separated by endash
['d-dMy'] = {'^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'd2', 'm', 'a', 'y'},
-- day initial month-day-range: day month - day month year; uses spaced endash
['dM-dMy'] = {'^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'd2', 'm2', 'a', 'y'},
-- month initial month-day-range: month day – month day, year; uses spaced endash
['Md-Mdy'] = {'^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$','m', 'd', 'm2', 'd2', 'a', 'y'},
-- day initial month-day-year-range: day month year - day month year; uses spaced endash
['dMy-dMy'] = {'^([1-9]%d?) +(%D-) +([1-9]%d%d%d?) +[%-–] +([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'y', 'd2', 'm2', 'a', 'y2'},
-- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
['Mdy-Mdy'] = {'^(%D-) +([1-9]%d?), +([1-9]%d%d%d?) +[%-–] +(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'y', 'm2', 'd2', 'a', 'y2'},
-- these date formats cannot be converted, per se, but month name can be rendered short or long
-- month/season year - month/season year; separated by spaced endash
['My-My'] = {'^(%D-) +([1-9]%d%d%d?) +[%-–] +(%D-) +(([1-9]%d%d%d?)%l?)$', 'm', 'y', 'm2', 'a', 'y2'},
-- month/season range year; months separated by endash
['M-My'] = {'^(%D-)[%-–](%D-) +(([1-9]%d%d%d?)%l?)$', 'm', 'm2', 'a', 'y'},
-- month/season year or proper-name year; quarter year when First Quarter YYYY etc.
['My'] = {'^([^%d–]-) +(([1-9]%d%d%d?)%l?)$', 'm', 'a', 'y'}, -- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't
-- these date formats cannot be converted
['Sy4-y2'] = {'^(%D-) +(([1-9]%d)%d%d)[%-–]((%d%d)%l?)$'}, -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
['Sy-y'] = {'^(%D-) +([1-9]%d%d%d?)[%-–](([1-9]%d%d%d?)%l?)$'}, -- special case Winter/Summer year-year; year separated with unspaced endash
['y-y'] = {'^([1-9]%d%d%d?)[%-–](([1-9]%d%d%d?)%l?)$'}, -- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
['y4-y2'] = {'^(([1-9]%d)%d%d)[%-–]((%d%d)%l?)$'}, -- year range: YYYY–YY; separated by unspaced endash
['y'] = {'^(([1-9]%d%d%d?)%l?)$'}, -- year; here accept either YYY or YYYY
-- these date formats cannot be converted
['n.d.'] = {'^((n%.d%.)%l?)$'}, -- no date with dots
['nd'] = {'^((nd)%l?)$'}, -- no date
}
--[[--------------------------< I S _ V A L I D _ E M B A R G O _ D A T E >------------------------------------
returns true and date value if that value has proper dmy, mdy, ymd format.
returns false and 9999 (embargoed forever) when date value is not proper format; assumes that when |pmc-embargo-date= is
set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date.
]]
local function is_valid_embargo_date (v)
if v:match (patterns_t['ymd'][1]) or -- ymd
v:match (patterns_t['Mdy'][1]) or -- dmy
v:match (patterns_t['dMy'][1]) then -- mdy
return true, v;
end
return false, '9999'; -- if here not good date so return false and set embargo date to long time in future
end
--[[--------------------------< C H E C K _ D A T E >----------------------------------------------------------
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only
allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day
months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons
must be spelled correctly. Future years beyond next year are not allowed.
If the date fails the format tests, this function returns false and does not return values for anchor_year and
COinS_date. When this happens, the date parameter is (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets
its year from the year parameter if present otherwise CITEREF does not get a date value.
Inputs:
date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date)
Returns:
false if date string is not a real date; else
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is ISO 8601 format date; see make_COInS_date()
]]
local function check_date (date_string, param, COinS_date_t)
local year; -- assume that year2, months, and days are not used;
local year2 = 0; -- second year in a year range
local month = 0;
local month2 = 0; -- second month in a month range
local day = 0;
local day2 = 0; -- second day in a day range
local anchor_year;
-- local coins_date;
if date_string:match (patterns_t['ymd'][1]) then -- year-initial numerical year month day format
year, month, day = date_string:match (patterns_t['ymd'][1]);
if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar
anchor_year = year;
elseif mw.ustring.match(date_string, patterns_t['Mdy'][1]) then -- month-initial: month day, year
month, day, anchor_year, year = mw.ustring.match(date_string, patterns_t['Mdy'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif mw.ustring.match(date_string, patterns_t['Md-dy'][1]) then -- month-initial day range: month day–day, year; days are separated by endash
month, day, day2, anchor_year, year = mw.ustring.match(date_string, patterns_t['Md-dy'][1]);
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dMy'][1]) then -- day-initial: day month year
day, month, anchor_year, year = mw.ustring.match(date_string, patterns_t['dMy'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
--[[ NOT supported at en.wiki
elseif mw.ustring.match(date_string, patterns_t['yMd'][1]) then -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed
anchor_year, year, month, day = mw.ustring.match(date_string, patterns_t['yMd'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
-- end NOT supported at en.wiki ]]
elseif mw.ustring.match(date_string, patterns_t['d-dMy'][1]) then -- day-range-initial: day–day month year; days are separated by endash
day, day2, month, anchor_year, year = mw.ustring.match(date_string, patterns_t['d-dMy'][1]);
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2 = month; -- for metadata
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dM-dMy'][1]) then -- day initial month-day-range: day month - day month year; uses spaced endash
day, month, day2, month2, anchor_year, year = mw.ustring.match(date_string, patterns_t['dM-dMy'][1]);
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later;
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['Md-Mdy'][1]) then -- month initial month-day-range: month day – month day, year; uses spaced endash
month, day, month2, day2, anchor_year, year = mw.ustring.match(date_string, patterns_t['Md-Mdy'][1]);
if (not is_valid_month_season_range(month, month2, param)) or not is_valid_year(year) then return false; end
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dMy-dMy'][1]) then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
day, month, year, day2, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['dMy-dMy'][1]);
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
if 0 == month or 0 == month2 then return false; end -- both must be valid
elseif mw.ustring.match(date_string, patterns_t['Mdy-Mdy'][1]) then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
month, day, year, month2, day2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Mdy-Mdy'][1]);
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number(month2);
if 0 == month or 0 == month2 then return false; end -- both must be valid
elseif mw.ustring.match(date_string, patterns_t['Sy4-y2'][1]) then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
local century;
month, year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Sy4-y2'][1]);
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
year2 = century..year2; -- add the century to year2 for comparisons
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number(month, param);
elseif mw.ustring.match(date_string, patterns_t['Sy-y'][1]) then -- special case Winter/Summer year-year; year separated with unspaced endash
month, year, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Sy-y'][1]);
month = get_season_number (month, param); -- <month> can only be winter or summer; also for metadata
if (month ~= cfg.date_names['en'].season['Winter']) and (month ~= cfg.date_names['en'].season['Summer']) then
return false; -- not Summer or Winter; abandon
end
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif mw.ustring.match(date_string, patterns_t['My-My'][1]) then -- month/season year - month/season year; separated by spaced endash
month, year, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['My-My'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style
month = get_month_number(month);
month2 = get_month_number(month2);
elseif 0 ~= get_season_number(month, param) and 0 ~= get_season_number(month2, param) then -- both must be season year, not mixed
month = get_season_number(month, param);
month2 = get_season_number(month2, param);
else
return false;
end
elseif mw.ustring.match(date_string, patterns_t['M-My'][1]) then -- month/season range year; months separated by endash
month, month2, anchor_year, year = mw.ustring.match(date_string, patterns_t['M-My'][1]);
if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
month2 = get_month_number(month2);
if 0 == month or 0 == month2 then return false; end
else
month = get_season_number(month, param);
month2 = get_season_number(month2, param);
end
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['My'][1]) then -- month/season/quarter/proper-name year
month, anchor_year, year = mw.ustring.match(date_string, patterns_t['My'][1]);
if not is_valid_year(year) then return false; end
month = get_element_number(month, param); -- get month season quarter proper-name number or nil
if not month then return false; end -- not valid whatever it is
elseif mw.ustring.match(date_string, patterns_t['y-y'][1]) then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
year, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['y-y'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif mw.ustring.match(date_string, patterns_t['y4-y2'][1]) then -- Year range: YYYY–YY; separated by unspaced endash
local century;
year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['y4-y2'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years
if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003
year2 = century .. year2; -- add the century to year2 for comparisons
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if in_array (param, {'date', 'publication-date', 'year'}) then -- here when 'valid' abbreviated year range; if one of these parameters
add_prop_cat ('year-range-abbreviated'); -- add properties cat
end
elseif mw.ustring.match(date_string, patterns_t['y'][1]) then -- year; here accept either YYY or YYYY
anchor_year, year = mw.ustring.match(date_string, patterns_t['y'][1]);
if false == is_valid_year(year) then
return false;
end
else
return false; -- date format not one of the MOS:DATE approved formats
end
if param ~= 'date' then -- CITEREF disambiguation only allowed in |date=; |year= & |publication-date= promote to date
if anchor_year:match ('%l$') then
return false;
end
end
if 'access-date' == param then -- test access-date here because we have numerical date parts
if 0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required
0 == year2 and 0 == month2 and 0 == day2 then -- none of these; access-date must not be a range
if not is_valid_accessdate(year .. '-' .. month .. '-' .. day) then
return false; -- return false when access-date out of bounds
end
else
return false; -- return false when access-date is a range of two dates
end
end
if 'archive-date' == param then -- test archive-date here because we have numerical date parts
if not (0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required
0 == year2 and 0 == month2 and 0 == day2) then -- none of these; archive-date must not be a range
return false; -- return false when archive-date is a range of two dates
end
end
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date)
result = is_valid_date (year, month, day, param); -- <param> for |pmc-embargo-date=
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range)
result = is_valid_date (year, month, day);
result = result and is_valid_date (year, month, day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range)
result = is_valid_date (year, month, day);
result = result and is_valid_date (year, month2, day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range)
result = is_valid_date(year, month, day);
result = result and is_valid_date(year2, month2, day2);
end
if false == result then return false; end
if nil ~= COinS_date_t then -- this table only passed into this function when testing |date= parameter values
make_COinS_date ({year = year, month = month, day = day, year2 = year2, month2 = month2, day2 = day2}, COinS_date_t); -- make an ISO 8601 date string for COinS
end
return true, anchor_year; -- format is good and date string represents a real date
end
--[[--------------------------< D A T E S >--------------------------------------------------------------------
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns
true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in
the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes).
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,
parameters with errors are added to the <error_list> sequence table as the dates are tested.
]]
local function dates(date_parameters_list, COinS_date_t, error_list)
local anchor_year; -- will return as nil if the date being tested is not |date=
local embargo_date; -- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999
local good_date;
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v.val) then -- if the parameter has a value
v.val = mw.ustring.gsub(v.val, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9
if v.val:match("^c%. [1-9]%d%d%d?%l?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
local year = v.val:match("c%. ([1-9]%d%d%d?)%l?"); -- get the year portion so it can be tested
if 'date' == k then
anchor_year = v.val:match ('(c%. [1-9]%d%d%d?%l?)'); -- anchor year only from |date= parameter
good_date = is_valid_year(year);
elseif 'year' == k then
good_date = is_valid_year(year);
else
good_date = false;
end
elseif 'date' == k then -- if the parameter is |date=
if v.val:match (patterns_t['n.d.'][1]) then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match (patterns_t['n.d.'][1]); -- "n.d."; no error when date parameter is set to no date
elseif v.val:match (patterns_t.nd[1]) then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match (patterns_t.nd[1]); -- "nd"; no error when date parameter is set to no date
else
good_date, anchor_year = check_date (v.val, k, COinS_date_t); -- go test the date
end
elseif 'year' == k then -- if the parameter is |year= it should hold only a year value
if v.val:match("^[1-9]%d%d%d?%l?$") then -- if |year = 3 or 4 digits only with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match ("((%d+)%l?)");
else
good_date = false;
end
elseif 'pmc-embargo-date' == k then -- if the parameter is |pmc-embargo-date=
good_date = check_date (v.val, k); -- go test the date
if true == good_date then -- if the date is a valid date
good_date, embargo_date = is_valid_embargo_date (v.val); -- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo date; no: returns 9999
end
else -- any other date-holding parameter
good_date = check_date (v.val, k); -- go test the date
end
if false == good_date then -- assemble one error message so we don't add the tracking category multiple times
table.insert (error_list, wrap_style ('parameter', v.name)); -- make parameter name suitable for error message list
end
end
end
return anchor_year, embargo_date; -- and done
end
--[[--------------------------< Y E A R _ C H E C K >----------------------------------------------------------
Temporary function to test |year= for acceptable values:
YYY, YYYY, year-only ranges, their circa forms, with or without CITEREF disambiguators.
When |year= holds some form of date that is not one of these year-only dates, emit a maintenance message.
This function necessary because many non-cs1|2 templates have a |year= parameter so cirrus searches are more-or-
less useless
]]
local function year_check (year)
year = year:gsub ('c%. *', ''); -- remove circa annotation (if present) before testing <year>
for _, index in ipairs ({'y-y', 'y4-y2', 'y'}) do -- spin through these indexes into patterns_t
if mw.ustring.match (year, patterns_t[index][1]) then
return; -- if a match then |year= holds a valid 'year'
end
end
set_message ('maint_year'); -- if here, |year= value is not an accepted value; add a maint cat
end
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------
Compare the value provided in |year= with the year value(s) provided in |date=. This function sets a local numeric value:
0 - year value does not match the year value in date
1 - (default) year value matches the year value in date or one of the year values when date contains two years
2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)
the numeric value in <result> determines the 'output' if any from this function:
0 – adds error message to error_list sequence table
1 – adds maint cat
2 – does nothing
]]
local function year_date_check (year_string, year_origin, date_string, date_origin, error_list)
local year;
local date1;
local date2;
local result = 1; -- result of the test; assume that the test passes
year = year_string:match ('(%d%d%d%d?)');
if date_string:match ('%d%d%d%d%-%d%d%-%d%d') then --special case where both date and year are required YYYY-MM-DD and YYYYx
date1 = date_string:match ('(%d%d%d%d)');
year = year_string:match ('(%d%d%d%d)');
if year ~= date1 then
result = 0; -- years don't match
elseif year_string:match ('%d%d%d%d%a') then
result = 2; -- years match; but because disambiguated, don't add to maint cat
end
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard range formats of date with two three- or four-digit years
date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)");
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif mw.ustring.match(date_string, "%d%d%d%d[%-–]%d%d") then -- YYYY-YY date ranges
local century;
date1, century, date2 = mw.ustring.match(date_string, "((%d%d)%d%d)[%-–]+(%d%d)");
date2 = century..date2; -- convert YY to YYYY
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year
date1 = date_string:match ("(%d%d%d%d?)");
if year ~= date1 then
result = 0;
end
else -- should never get here; this function called only when no other date errors
result = 0; -- no recognizable year in date
end
if 0 == result then -- year / date mismatch
table.insert (error_list, substitute (cfg.messages['mismatch'], {year_origin, date_origin})); -- add error message to error_list sequence table
elseif 1 == result then -- redundant year / date
set_message ('maint_date_year'); -- add a maint cat
end
end
--[[--------------------------< R E F O R M A T T E R >--------------------------------------------------------
reformat 'date' into new format specified by format_param if pattern_idx (the current format of 'date') can be
reformatted. Does the grunt work for reformat_dates().
The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds:
format string used by string.format()
identifier letters ('d', 'm', 'y', 'd2', 'm2', 'y2') that serve as indexes into a table t{} that holds captures
from mw.ustring.match() for the various date parts specified by patterns_t[pattern_idx][1]
Items in patterns_t{} have the general form:
['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, where:
['ymd'] is pattern_idx
patterns_t['ymd'][1] is the match pattern with captures for mw.ustring.match()
patterns_t['ymd'][2] is an indicator letter identifying the content of the first capture
patterns_t['ymd'][3] ... the second capture etc.
when a pattern matches a date, the captures are loaded into table t{} in capture order using the idemtifier
characters as indexes into t{} For the above, a ymd date is in t{} as:
t.y = first capture (year), t.m = second capture (month), t.d = third capture (day)
To reformat, this function is called with the pattern_idx that matches the current format of the date and with
format_param set to the desired format. This function loads table t{} as described and then calls string.format()
with the format string specified by re_format[pattern_idx][format_param][1] using values taken from t{} according
to the capture identifier letters specified by patterns_t[pattern_idx][format_param][n] where n is 2..
]]
local re_formats = {
['ymd'] = { -- date format is ymd; reformat to:
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['Mdy'] = { -- date format is Mdy; reformat to:
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- for long/short reformatting
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['dMy'] = { -- date format is dMy; reformat to:
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['Md-dy'] = { -- date format is Md-dy; reformat to:
['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- for long/short reformatting
['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- |df=dmy -> d-dMy
},
['d-dMy'] = { -- date format is d-d>y; reformat to:
['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- |df=mdy -> Md-dy
},
['dM-dMy'] = { -- date format is dM-dMy; reformat to:
['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- |df=mdy -> Md-Mdy
},
['Md-Mdy'] = { -- date format is Md-Mdy; reformat to:
['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- for long/short reformatting
['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- |df=dmy -> dM-dMy
},
['dMy-dMy'] = { -- date format is dMy-dMy; reformat to:
['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- for long/short reformatting
['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- |df=mdy -> Mdy-Mdy
},
['Mdy-Mdy'] = { -- date format is Mdy-Mdy; reformat to:
['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- for long/short reformatting
['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- |df=dmy -> dMy-dMy
},
['My-My'] = { -- these for long/short reformatting
['any'] = {'%s %s – %s %s', 'm', 'y', 'm2', 'y2'}, -- dmy/mdy agnostic
},
['M-My'] = { -- these for long/short reformatting
['any'] = {'%s–%s %s', 'm', 'm2', 'y'}, -- dmy/mdy agnostic
},
['My'] = { -- these for long/short reformatting
['any'] = {'%s %s', 'm', 'y'}, -- dmy/mdy agnostic
},
-- ['yMd'] = { -- not supported at en.wiki
-- ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
-- ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
-- ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- },
}
local function reformatter (date, pattern_idx, format_param, mon_len)
if not in_array (pattern_idx, {'ymd', 'Mdy', 'Md-dy', 'dMy', 'yMd', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then
return; -- not in this set of date format patterns_t then not a reformattable date
end
if 'ymd' == format_param and in_array (pattern_idx, {'ymd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then
return; -- ymd date ranges not supported at en.wiki; no point in reformatting ymd to ymd
end
if in_array (pattern_idx, {'My', 'M-My', 'My-My'}) then -- these are not dmy/mdy so can't be 'reformatted' into either
format_param = 'any'; -- so format-agnostic
end
-- yMd is not supported at en.wiki; when yMd is supported at your wiki, uncomment the next line
-- if 'yMd' == format_param and in_array (pattern_idx, {'yMd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy'}) then -- these formats not convertable; yMd not supported at en.wiki
if 'yMd' == format_param then -- yMd not supported at en.wiki; when yMd is supported at your wiki, remove or comment-out this line
return; -- not a reformattable date
end
local c1, c2, c3, c4, c5, c6, c7; -- these hold the captures specified in patterns_t[pattern_idx][1]
c1, c2, c3, c4, c5, c6, c7 = mw.ustring.match (date, patterns_t[pattern_idx][1]); -- get the captures
local t = { -- table that holds k/v pairs of date parts from the captures and patterns_t[pattern_idx][2..]
[patterns_t[pattern_idx][2]] = c1; -- at minimum there is always one capture with a matching indicator letter
[patterns_t[pattern_idx][3] or 'x'] = c2; -- patterns_t can have a variable number of captures; each capture requires an indicator letter;
[patterns_t[pattern_idx][4] or 'x'] = c3; -- where there is no capture, there is no indicator letter so n in patterns_t[pattern_idx][n] will be nil;
[patterns_t[pattern_idx][5] or 'x'] = c4; -- the 'x' here spoofs an indicator letter to prevent 'table index is nil' error
[patterns_t[pattern_idx][6] or 'x'] = c5;
[patterns_t[pattern_idx][7] or 'x'] = c6;
[patterns_t[pattern_idx][8] or 'x'] = c7;
};
if t.a then -- if this date has an anchor year capture (all convertable date formats except ymd)
if t.y2 then -- for year range date formats
t.y2 = t.a; -- use the anchor year capture when reassembling the date
else -- here for single date formats (except ymd)
t.y = t.a; -- use the anchor year capture when reassembling the date
end
end
if tonumber(t.m) then -- if raw month is a number (converting from ymd)
if 's' == mon_len then -- if we are to use abbreviated month names
t.m = cfg.date_names['inv_local_short'][tonumber(t.m)]; -- convert it to a month name
else
t.m = cfg.date_names['inv_local_long'][tonumber(t.m)]; -- convert it to a month name
end
t.d = t.d:gsub ('0(%d)', '%1'); -- strip leading '0' from day if present
elseif 'ymd' == format_param then -- when converting to ymd
t.y = t.y:gsub ('%a', ''); -- strip CITREF disambiguator if present; anchor year already known so process can proceed; TODO: maint message?
if 1582 > tonumber (t.y) then -- ymd format dates not allowed before 1582
return;
end
t.m = string.format ('%02d', get_month_number (t.m)); -- make sure that month and day are two digits
t.d = string.format ('%02d', t.d);
elseif mon_len then -- if mon_len is set to either 'short' or 'long'
for _, mon in ipairs ({'m', 'm2'}) do -- because there can be two month names, check both
if t[mon] then
t[mon] = get_month_number (t[mon]); -- get the month number for this month (is length agnostic)
if 0 == t[mon] then return; end -- seasons and named dates can't be converted
t[mon] = (('s' == mon_len) and cfg.date_names['inv_local_short'][t[mon]]) or cfg.date_names['inv_local_long'][t[mon]]; -- fetch month name according to length
end
end
end
local new_date = string.format (re_formats[pattern_idx][format_param][1], -- format string
t[re_formats[pattern_idx][format_param][2]], -- named captures from t{}
t[re_formats[pattern_idx][format_param][3]],
t[re_formats[pattern_idx][format_param][4]],
t[re_formats[pattern_idx][format_param][5]],
t[re_formats[pattern_idx][format_param][6]],
t[re_formats[pattern_idx][format_param][7]],
t[re_formats[pattern_idx][format_param][8]]
);
return new_date;
end
--[[-------------------------< R E F O R M A T _ D A T E S >--------------------------------------------------
Reformats existing dates into the format specified by format.
format is one of several manual keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all. The -all version includes
access- and archive-dates; otherwise these dates are not reformatted.
This function allows automatic date formatting. In ~/Configuration, the article source is searched for one of
the {{use xxx dates}} templates. If found, xxx becomes the global date format as xxx-all. If |cs1-dates= in
{{use xxx dates}} has legitimate value then that value determines how cs1|2 dates will be rendered. Legitimate
values for |cs1-dates= are:
l - all dates are rendered with long month names
ls - publication dates use long month names; access-/archive-dates use abbreviated month names
ly - publication dates use long month names; access-/archive-dates rendered in ymd format
s - all dates are rendered with abbreviated (short) month names
sy - publication dates use abbreviated month names; access-/archive-dates rendered in ymd format
y - all dates are rendered in ymd format
the format argument for automatic date formatting will be the format specified by {{use xxx dates}} with the
value supplied by |cs1-dates so one of: xxx-l, xxx-ls, xxx-ly, xxx-s, xxx-sy, xxx-y, or simply xxx (|cs1-dates=
empty, omitted, or invalid) where xxx shall be either of dmy or mdy.
dates are extracted from date_parameters_list, reformatted (if appropriate), and then written back into the
list in the new format. Dates in date_parameters_list are presumed here to be valid (no errors). This function
returns true when a date has been reformatted, false else. Actual reformatting is done by reformatter().
]]
local function reformat_dates (date_parameters_list, format)
local all = false; -- set to false to skip access- and archive-dates
local len_p = 'l'; -- default publication date length shall be long
local len_a = 'l'; -- default access-/archive-date length shall be long
local result = false;
local new_date;
if format:match('%a+%-all') then -- manual df keyword; auto df keyword when length not specified in {{use xxx dates}};
format = format:match('(%a+)%-all'); -- extract the format
all = true; -- all dates are long format dates because this keyword doesn't specify length
elseif format:match('%a+%-[lsy][sy]?') then -- auto df keywords; internal only
all = true; -- auto df applies to all dates; use length specified by capture len_p for all dates
format, len_p, len_a = format:match('(%a+)%-([lsy])([sy]?)'); -- extract the format and length keywords
if 'y' == len_p then -- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted
format = 'ymd'; -- override {{use xxx dates}}
elseif (not is_set(len_a)) or (len_p == len_a) then -- no access-/archive-date length specified or same length as publication dates then
len_a = len_p; -- in case len_a not set
end
end -- else only publication dates and they are long
for param_name, param_val in pairs (date_parameters_list) do -- for each date-holding parameter in the list
if is_set (param_val.val) then -- if the parameter has a value
if not (not all and in_array (param_name, {'access-date', 'archive-date'})) then -- skip access- or archive-date unless format is xxx-all; yeah, ugly; TODO: find a better way
for pattern_idx, pattern in pairs (patterns_t) do
if mw.ustring.match (param_val.val, pattern[1]) then
if all and in_array (param_name, {'access-date', 'archive-date'}) then -- if this date is an access- or archive-date
new_date = reformatter (param_val.val, pattern_idx, (('y' == len_a) and 'ymd') or format, len_a); -- choose ymd or dmy/mdy according to len_a setting
else -- all other dates
new_date = reformatter (param_val.val, pattern_idx, format, len_p);
end
if new_date then -- set when date was reformatted
date_parameters_list[param_name].val = new_date; -- update date in date list
result = true; -- and announce that changes have been made
break;
end
end -- if
end -- for
end -- if
end -- if
end -- for
return result; -- declare boolean result and done
end
--[[--------------------------< D A T E _ H Y P H E N _ T O _ D A S H >----------------------------------------
Loops through the list of date-holding parameters and converts any hyphen to an ndash. Not called if the cs1|2
template has any date errors.
Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false.
]]
local function date_hyphen_to_dash (date_parameters_list)
local result = false;
local n;
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set (param_val.val) and
not mw.ustring.match (param_val.val, patterns_t.ymd[1]) then -- for those that are not ymd dates (ustring because here digits may not be Western)
param_val.val, n = param_val.val:gsub ('%-', '–'); -- replace any hyphen with ndash
if 0 ~= n then
date_parameters_list[param_name].val = param_val.val; -- update the list
result = true;
end
end
end
return result; -- so we know if any hyphens were replaced
end
--[[-------------------------< D A T E _ N A M E _ X L A T E >------------------------------------------------
Attempts to translate English date names to local-language date names using names supplied by MediaWiki's
date parser function. This is simple name-for-name replacement and may not work for all languages.
if xlat_dig is true, this function will also translate Western (English) digits to the local language's digits.
This will also translate ymd dates.
]]
local function date_name_xlate (date_parameters_list, xlt_dig)
local xlate;
local modified = false;
local date;
local sources_t = {
{cfg.date_names.en.long, cfg.date_names.inv_local_long}, -- for translating long English month names to long local month names
{cfg.date_names.en.short, cfg.date_names.inv_local_short}, -- short month names
{cfg.date_names.en.quarter, cfg.date_names.inv_local_quarter}, -- quarter date names
{cfg.date_names.en.season, cfg.date_names.inv_local_season}, -- season date nam
{cfg.date_names.en.named, cfg.date_names.inv_local_named}, -- named dates
}
local function is_xlateable (month) -- local function to get local date name that replaces existing English-language date name
for _, date_names_t in ipairs (sources_t) do -- for each sequence table in date_names_t
if date_names_t[1][month] then -- if date name is English month (long or short), quarter, season or named and
if date_names_t[2][date_names_t[1][month]] then -- if there is a matching local date name
return date_names_t[2][date_names_t[1][month]]; -- return the local date name
end
end
end
end
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(param_val.val) then -- if the parameter has a value
date = param_val.val;
for month in mw.ustring.gmatch (date, '[%a ]+') do -- iterate through all date names in the date (single date or date range)
month = mw.text.trim (month); -- this because quarterly dates contain whitespace
xlate = is_xlateable (month); -- get translate <month>; returns translation or nil
if xlate then
date = mw.ustring.gsub (date, month, xlate); -- replace the English with the translation
date_parameters_list[param_name].val = date; -- save the translated date
modified = true;
end
end
if xlt_dig then -- shall we also translate digits?
date = date:gsub ('%d', cfg.date_names.xlate_digits); -- translate digits from Western to 'local digits'
date_parameters_list[param_name].val = date; -- save the translated date
modified = true;
end
end
end
return modified;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
add_prop_cat = utilities_page_ptr.add_prop_cat ; -- import functions from selected Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
set_message = utilities_page_ptr.set_message;
substitute = utilities_page_ptr.substitute;
wrap_style = utilities_page_ptr.wrap_style;
cfg = cfg_table_ptr; -- import tables from selected Module:Citation/CS1/Configuration
end
--[[--------------------------< A R C H I V E _ D A T E _ C H E C K >------------------------------------------
Compare value in |archive-date= with the timestamp in Wayback machine urls. Emits an error message with suggested
date from the |archive-url= timestamp in an appropriate format when the value in |archive-date= does not match
the timestamp.
this function never called when any date in a cs1|2 template has errors
error message suggests new |archive-date= value in an appropriate format specified by <df>. <df> is either
|df= or cfg.global_df in that order. If <df> is nil, suggested date has format from |archive-date=. There is
a caveat: when |df=dmy or |df=mdy, the reformatter leaves |access-date= and |archive-date= formats as they are.
The error message suggested date is passed to the formatter as YYYY-MM-DD so when |df=dmy or |df=mdy, the format
is not changed.
]]
local function archive_date_check (archive_date, archive_url_timestamp, df)
local archive_date_format = 'dmy-y'; -- holds the date format of date in |archive-date; default to ymd; 'dmy' used here to spoof reformat_dates()
for _, v_t in ipairs ({{'dMy', 'dmy-all'}, {'Mdy', 'mdy-all'}}) do -- is |archive-date= format dmy or mdy?
if archive_date:match (patterns_t[v_t[1]][1]) then -- does the pattern match?
archive_date_format = cfg.keywords_xlate[v_t[2]]; -- get appropriate |df= supported keyword from the i18n translator table
break;
end
end
local dates_t = {};
dates_t['archive-date'] = {val=archive_date, name=''}; -- setup to call reformat_dates(); never called when errors so <name> unset as not needed
reformat_dates (dates_t, 'dmy-y'); -- reformat |archive-date= to ymd; 'dmy' used here to spoof reformat_dates()
local archive_url_date = archive_url_timestamp:gsub ('(%d%d%d%d)(%d%d)(%d%d)%d*', '%1-%2-%3'); -- make ymd format date from timestamp
if dates_t['archive-date'].val == archive_url_date then -- are the two dates the same
return; -- yes, done
else
dates_t['archive-date'] = {val=archive_url_date, name=''}; -- setup to call reformat_dates() with the timestamp date
reformat_dates (dates_t, df or archive_date_format); -- reformat timestamp to format specified by <df> or format used in |archive-date=
archive_url_date = dates_t['archive-date'].val;
set_message ('err_archive_date_url_ts_mismatch', archive_url_date); -- emit an error message
end
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return { -- return exported functions
archive_date_check = archive_date_check,
date_hyphen_to_dash = date_hyphen_to_dash,
date_name_xlate = date_name_xlate,
dates = dates,
is_valid_date = is_valid_date,
reformat_dates = reformat_dates,
set_selected_modules = set_selected_modules,
year_check = year_check,
year_date_check = year_date_check,
}
t2d5ocm3ym8yza0dgkl1tstgc2yr6dq
9010
8259
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/Date_validation]]
8259
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local add_prop_cat, is_set, in_array, set_message, substitute, wrap_style; -- imported functions from selected Module:Citation/CS1/Utilities
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< F I L E - S C O P E D E C L A R A T I O N S >--------------------------------
File-scope variables are declared here
]]
local lang_obj = mw.getContentLanguage(); -- used by is_valid_accessdate(), is_valid_year(), date_name_xlate();
local year_limit; -- used by is_valid_year()
--[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
returns true if:
Wikipedia start date <= accessdate < today + 2 days
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)
accessdate is the date provided in |access-date= at time 00:00:00 UTC
today is the current date at time 00:00:00 UTC plus 48 hours
if today is 2015-01-01T00:00:00 then
adding 24 hours gives 2015-01-02T00:00:00 – one second more than today
adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow
This function does not work if it is fed month names for languages other than English. Wikimedia #time: parser
apparently doesn't understand non-English date month names. This function will always return false when the date
contains a non-English month name because good1 is false after the call to lang.formatDate(). To get around that
call this function with YYYY-MM-DD format dates.
]=]
local function is_valid_accessdate (accessdate)
local good1, good2;
local access_ts, tomorrow_ts; -- to hold Unix time stamps representing the dates
good1, access_ts = pcall (lang_obj.formatDate, lang_obj, 'U', accessdate ); -- convert accessdate value to Unix timestamp
good2, tomorrow_ts = pcall (lang_obj.formatDate, lang_obj, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which which tonumber() may not understand
access_ts = tonumber (access_ts) or lang_obj:parseFormattedNumber (access_ts); -- convert to numbers for the comparison;
tomorrow_ts = tonumber (tomorrow_ts) or lang_obj:parseFormattedNumber (tomorrow_ts);
else
return false; -- one or both failed to convert to Unix time stamp
end
if 979516800 <= access_ts and access_ts < tomorrow_ts then -- Wikipedia start date <= accessdate < tomorrow's date
return true;
else
return false; -- accessdate out of range
end
end
--[[--------------------------< G E T _ M O N T H _ N U M B E R >----------------------------------------------
returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct.
If not a valid month, returns 0
]]
local function get_month_number (month)
return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first
cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names
0; -- not a recognized month name
end
--[[--------------------------< G E T _ S E A S O N _ N U M B E R >--------------------------------------------
returns a number according to the sequence of seasons in a year: 21 for Spring, etc. Capitalization and spelling
must be correct. If not a valid season, returns 0.
21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere”
returns 0 when <param> is not |date=
Season numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons. EDTF does support the distinction between north and south
hemisphere seasons but cs1|2 has no way to make that distinction.
These additional divisions not currently supported:
25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere
29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)
]]
local function get_season_number (season, param)
if 'date' ~= param then
return 0; -- season dates only supported by |date=
end
return cfg.date_names['local'].season[season] or -- look for local names first
cfg.date_names['en'].season[season] or -- failing that, look for English names
0; -- not a recognized season name
end
--[[--------------------------< G E T _ Q U A R T E R _ N U M B E R >------------------------------------------
returns a number according to the sequence of quarters in a year: 33 for first quarter, etc. Capitalization and spelling
must be correct. If not a valid quarter, returns 0.
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
returns 0 when <param> is not |date=
Quarter numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons and quarters.
These additional divisions not currently supported:
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)
]]
local function get_quarter_number (quarter, param)
if 'date' ~= param then
return 0; -- quarter dates only supported by |date=
end
quarter = mw.ustring.gsub (quarter, ' +', ' '); -- special case replace multiple space chars with a single space char
return cfg.date_names['local'].quarter[quarter] or -- look for local names first
cfg.date_names['en'].quarter[quarter] or -- failing that, look for English names
0; -- not a recognized quarter name
end
--[[--------------------------< G E T _ P R O P E R _ N A M E _ N U M B E R >----------------------------------
returns a non-zero number if date contains a recognized proper-name. Capitalization and spelling must be correct.
returns 0 when <param> is not |date=
]]
local function get_proper_name_number (name, param)
if 'date' ~= param then
return 0; -- proper-name dates only supported by |date=
end
return cfg.date_names['local'].named[name] or -- look for local names dates first
cfg.date_names['en'].named[name] or -- failing that, look for English names
0; -- not a recognized named date
end
--[[--------------------------< G E T _ E L E M E N T _ N U M B E R <------------------------------------------
returns true if month or season or quarter or proper name is valid (properly spelled, capitalized, abbreviated)
]]
local function get_element_number (element, param)
local num;
local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number}; -- list of functions to execute in order
for _, func in ipairs (funcs) do -- spin through the function list
num = func (element, param); -- call the function and get the returned number
if 0 ~= num then -- non-zero when valid month season quarter
return num; -- return that number
end
end
return nil; -- not valid
end
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
Function gets current year from the server and compares it to year from a citation parameter. Years more than one
year in the future are not acceptable.
Special case for |pmc-embargo-date=: years more than two years in the future are not acceptable
]]
local function is_valid_year (year, param)
if not is_set (year_limit) then
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once
end
year = tonumber (year) or lang_obj:parseFormattedNumber (year); -- convert to number for the comparison
if year and (100 > year) then -- years less than 100 not supported
return false;
end
if 'pmc-embargo-date' == param then -- special case for |pmc-embargo-date=
return year and (year <= tonumber(os.date("%Y"))+2) or false; -- years more than two years in the future are not accepted
end
return year and (year <= year_limit) or false;
end
--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------
Returns true if day is less than or equal to the number of days in month and year is no farther into the future
than next year; else returns false.
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately
1923) dates are assumed to be Gregorian.
]]
local function is_valid_date (year, month, day, param)
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
if not is_valid_year (year, param) then -- no farther into the future than next year except |pmc-embargo-date= no more than two years in the future
return false;
end
month = tonumber (month); -- required for YYYY-MM-DD dates
if (2 == month) then -- if February
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0 == (year%4) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
else -- Gregorian calendar
if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
end
else
month_length = days_in_month[month] or 0; -- invalid month number is nil so default <month_length> to 0
end
if tonumber (day) > month_length then
return false;
end
return true;
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >--------------------------
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August.
This function looks in cfg.date_names{} to see if both month names are listed in the long subtable or both are
listed in the short subtable. When both have the same style (both are listed in the same table), returns true; false else
]]
local function is_valid_month_range_style (month1, month2)
if (cfg.date_names.en.long[month1] and cfg.date_names.en.long[month2]) or -- are both English names listed in the long subtable?
(cfg.date_names.en.short[month1] and cfg.date_names.en.short[month2]) or -- are both English names listed in the short subtable?
(cfg.date_names['local'].long[month1] and cfg.date_names['local'].long[month2]) or -- are both local names listed in the long subtable?
(cfg.date_names['local'].short[month1] and cfg.date_names['local'].short[month2]) then -- are both local names listed in the short subtable?
return true;
end
return false; -- names are mixed
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------
Check a pair of months or seasons to see if both are valid members of a month or season pair.
Month pairs are expected to be left to right, earliest to latest in time.
All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue, hence treat as ok
]]
local function is_valid_month_season_range(range_start, range_end, param)
local range_start_number = get_month_number (range_start);
local range_end_number;
if 0 == range_start_number then -- is this a month range?
range_start_number = get_season_number (range_start, param); -- not a month; is it a season? get start season number
range_end_number = get_season_number (range_end, param); -- get end season number
if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then
return true; -- any season pairing is accepted except when both are the same
end
return false; -- range_start and/or range_end is not a season
end
-- here when range_start is a month
range_end_number = get_month_number (range_end); -- get end month number
if range_start_number < range_end_number and -- range_start is a month; does range_start precede range_end?
is_valid_month_range_style (range_start, range_end) then -- do months have the same style?
return true; -- proper order and same style
end
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month
end
--[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------
This function receives a table of date parts for one or two dates and an empty table reference declared in
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is
determined to be a valid date format. The question of what to do with invalid date formats is not answered here.
The date parts in the input table are converted to an ISO 8601 conforming date string:
single whole dates: yyyy-mm-dd
month and year dates: yyyy-mm
year dates: yyyy
ranges: yyyy-mm-dd/yyyy-mm-dd
yyyy-mm/yyyy-mm
yyyy/yyyy
Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from
Julian to Proleptic Gregorian.
The input table has:
year, year2 – always present; if before 1582, ignore months and days if present
month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas
day, day2 – 0 if not provided, 1-31 for days
the output table receives:
rftdate: an ISO 8601 formatted date
rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates)
rftssn: one of four season keywords: winter, spring, summer, fall (lowercase)
rftquarter: one of four values: 1, 2, 3, 4
]]
local function make_COinS_date (input, COinS_date_t)
local date; -- one date or first date in a range
local date2 = ''; -- end of range date
input.year = tonumber (input.year) or lang_obj:parseFormattedNumber (input.year); -- language-aware tonumber()
input.year2 = tonumber (input.year2) or lang_obj:parseFormattedNumber (input.year2); -- COinS dates are pseudo-ISO 8601 so convert to Arabic numerals
if ((1582 == input.year) and (10 > tonumber(input.month))) or (1582 > input.year) then -- if a Julian calendar date
COinS_date_t.rftdate = tostring (input.year); -- &rft.date gets year only
return; -- done
end
-- here for all forms of Gregorian dates
if 20 < tonumber (input.month) then -- if season, quarter, or proper-name date
date = input.year; -- &rft.date gets year only
if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year
date = string.format ('%.4d/%.4d', input.year, input.year2) -- assemble the date range
end
local season = {[24] = 'winter', [21] = 'spring', [22] = 'summer', [23] = 'fall', [33] = '1', [34] = '2', [35] = '3', [36] = '4', [98] = 'Easter', [99] = 'Christmas'}; -- seasons lowercase, no autumn; proper-names use title case
if 0 == input.month2 then -- single season, quarter, or proper-name date
if 40 < tonumber(input.month) then
COinS_date_t.rftchron = season[input.month]; -- proper-name date; used in journal metadata only
elseif 30 < tonumber(input.month) then
COinS_date_t.rftquarter = season[input.month]; -- quarter date; used in journal metadata only
else
COinS_date_t.rftssn = season[input.month]; -- season date; used in journal metadata only
end
else -- season ranges are lumped into &rft.chron; &rft.ssn and &rft.quarter are left blank
if input.year ~= input.year2 then -- season year – season year range or season year–year
if 0 ~= input.month2 then
COinS_date_t.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2); -- used in journal metadata only
end
else -- season–season year range
COinS_date_t.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range; used in journal metadata only
end
end
COinS_date_t.rftdate = tostring (date);
return; -- done
end
-- here for gregorian calendar dates
if 0 ~= input.day then
date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date
elseif 0 ~= input.month then
date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month
else
date = string.format ('%s', input.year); -- just year
end
if 0 ~= input.year2 then
if 0 ~= input.day2 then
date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date
elseif 0 ~= input.month2 then
date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month
else
date2 = string.format ('/%s', input.year2); -- just year
end
end
COinS_date_t.rftdate = date .. date2; -- date2 has the '/' separator
return;
end
--[[--------------------------< P A T T E R N S _ T >----------------------------------------------------------
this is the list of patterns for date formats that this module recognizes. Approximately the first half of these
patterns represent formats that might be reformatted into another format. Those that might be reformatted have
'indicator' letters that identify the content of the matching capture: 'd' (day), 'm' (month), 'a' (anchor year),
'y' (year); second day, month, year have a '2' suffix.
These patterns are used for both date validation and for reformatting. This table should not be moved to ~/Configuration
because changes to this table require changes to check_date() and to reformatter() and reformat_date()
]]
local patterns_t = {
-- year-initial numerical year-month-day
['ymd'] = {'^([1-9]%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'},
-- month-initial: month day, year
['Mdy'] = {'^(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'a', 'y'},
-- month-initial day range: month day–day, year; days are separated by endash
['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'd2', 'a', 'y'},
-- day-initial: day month year
['dMy'] = {'^([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'a', 'y'},
-- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki
-- ['yMd'] = {'^(([1-9]%d%d%d?)%l?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'},
-- day-range-initial: day–day month year; days are separated by endash
['d-dMy'] = {'^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'd2', 'm', 'a', 'y'},
-- day initial month-day-range: day month - day month year; uses spaced endash
['dM-dMy'] = {'^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'd2', 'm2', 'a', 'y'},
-- month initial month-day-range: month day – month day, year; uses spaced endash
['Md-Mdy'] = {'^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$','m', 'd', 'm2', 'd2', 'a', 'y'},
-- day initial month-day-year-range: day month year - day month year; uses spaced endash
['dMy-dMy'] = {'^([1-9]%d?) +(%D-) +([1-9]%d%d%d?) +[%-–] +([1-9]%d?) +(%D-) +(([1-9]%d%d%d?)%l?)$', 'd', 'm', 'y', 'd2', 'm2', 'a', 'y2'},
-- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
['Mdy-Mdy'] = {'^(%D-) +([1-9]%d?), +([1-9]%d%d%d?) +[%-–] +(%D-) +([1-9]%d?), +(([1-9]%d%d%d?)%l?)$', 'm', 'd', 'y', 'm2', 'd2', 'a', 'y2'},
-- these date formats cannot be converted, per se, but month name can be rendered short or long
-- month/season year - month/season year; separated by spaced endash
['My-My'] = {'^(%D-) +([1-9]%d%d%d?) +[%-–] +(%D-) +(([1-9]%d%d%d?)%l?)$', 'm', 'y', 'm2', 'a', 'y2'},
-- month/season range year; months separated by endash
['M-My'] = {'^(%D-)[%-–](%D-) +(([1-9]%d%d%d?)%l?)$', 'm', 'm2', 'a', 'y'},
-- month/season year or proper-name year; quarter year when First Quarter YYYY etc.
['My'] = {'^([^%d–]-) +(([1-9]%d%d%d?)%l?)$', 'm', 'a', 'y'}, -- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't
-- these date formats cannot be converted
['Sy4-y2'] = {'^(%D-) +(([1-9]%d)%d%d)[%-–]((%d%d)%l?)$'}, -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
['Sy-y'] = {'^(%D-) +([1-9]%d%d%d?)[%-–](([1-9]%d%d%d?)%l?)$'}, -- special case Winter/Summer year-year; year separated with unspaced endash
['y-y'] = {'^([1-9]%d%d%d?)[%-–](([1-9]%d%d%d?)%l?)$'}, -- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
['y4-y2'] = {'^(([1-9]%d)%d%d)[%-–]((%d%d)%l?)$'}, -- year range: YYYY–YY; separated by unspaced endash
['y'] = {'^(([1-9]%d%d%d?)%l?)$'}, -- year; here accept either YYY or YYYY
-- these date formats cannot be converted
['n.d.'] = {'^((n%.d%.)%l?)$'}, -- no date with dots
['nd'] = {'^((nd)%l?)$'}, -- no date
}
--[[--------------------------< I S _ V A L I D _ E M B A R G O _ D A T E >------------------------------------
returns true and date value if that value has proper dmy, mdy, ymd format.
returns false and 9999 (embargoed forever) when date value is not proper format; assumes that when |pmc-embargo-date= is
set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date.
]]
local function is_valid_embargo_date (v)
if v:match (patterns_t['ymd'][1]) or -- ymd
v:match (patterns_t['Mdy'][1]) or -- dmy
v:match (patterns_t['dMy'][1]) then -- mdy
return true, v;
end
return false, '9999'; -- if here not good date so return false and set embargo date to long time in future
end
--[[--------------------------< C H E C K _ D A T E >----------------------------------------------------------
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only
allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day
months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons
must be spelled correctly. Future years beyond next year are not allowed.
If the date fails the format tests, this function returns false and does not return values for anchor_year and
COinS_date. When this happens, the date parameter is (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets
its year from the year parameter if present otherwise CITEREF does not get a date value.
Inputs:
date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date)
Returns:
false if date string is not a real date; else
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is ISO 8601 format date; see make_COInS_date()
]]
local function check_date (date_string, param, COinS_date_t)
local year; -- assume that year2, months, and days are not used;
local year2 = 0; -- second year in a year range
local month = 0;
local month2 = 0; -- second month in a month range
local day = 0;
local day2 = 0; -- second day in a day range
local anchor_year;
-- local coins_date;
if date_string:match (patterns_t['ymd'][1]) then -- year-initial numerical year month day format
year, month, day = date_string:match (patterns_t['ymd'][1]);
if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar
anchor_year = year;
elseif mw.ustring.match(date_string, patterns_t['Mdy'][1]) then -- month-initial: month day, year
month, day, anchor_year, year = mw.ustring.match(date_string, patterns_t['Mdy'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif mw.ustring.match(date_string, patterns_t['Md-dy'][1]) then -- month-initial day range: month day–day, year; days are separated by endash
month, day, day2, anchor_year, year = mw.ustring.match(date_string, patterns_t['Md-dy'][1]);
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dMy'][1]) then -- day-initial: day month year
day, month, anchor_year, year = mw.ustring.match(date_string, patterns_t['dMy'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
--[[ NOT supported at en.wiki
elseif mw.ustring.match(date_string, patterns_t['yMd'][1]) then -- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed
anchor_year, year, month, day = mw.ustring.match(date_string, patterns_t['yMd'][1]);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
-- end NOT supported at en.wiki ]]
elseif mw.ustring.match(date_string, patterns_t['d-dMy'][1]) then -- day-range-initial: day–day month year; days are separated by endash
day, day2, month, anchor_year, year = mw.ustring.match(date_string, patterns_t['d-dMy'][1]);
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2 = month; -- for metadata
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dM-dMy'][1]) then -- day initial month-day-range: day month - day month year; uses spaced endash
day, month, day2, month2, anchor_year, year = mw.ustring.match(date_string, patterns_t['dM-dMy'][1]);
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later;
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['Md-Mdy'][1]) then -- month initial month-day-range: month day – month day, year; uses spaced endash
month, day, month2, day2, anchor_year, year = mw.ustring.match(date_string, patterns_t['Md-Mdy'][1]);
if (not is_valid_month_season_range(month, month2, param)) or not is_valid_year(year) then return false; end
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['dMy-dMy'][1]) then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
day, month, year, day2, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['dMy-dMy'][1]);
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
if 0 == month or 0 == month2 then return false; end -- both must be valid
elseif mw.ustring.match(date_string, patterns_t['Mdy-Mdy'][1]) then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
month, day, year, month2, day2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Mdy-Mdy'][1]);
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number(month2);
if 0 == month or 0 == month2 then return false; end -- both must be valid
elseif mw.ustring.match(date_string, patterns_t['Sy4-y2'][1]) then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
local century;
month, year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Sy4-y2'][1]);
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
year2 = century..year2; -- add the century to year2 for comparisons
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number(month, param);
elseif mw.ustring.match(date_string, patterns_t['Sy-y'][1]) then -- special case Winter/Summer year-year; year separated with unspaced endash
month, year, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['Sy-y'][1]);
month = get_season_number (month, param); -- <month> can only be winter or summer; also for metadata
if (month ~= cfg.date_names['en'].season['Winter']) and (month ~= cfg.date_names['en'].season['Summer']) then
return false; -- not Summer or Winter; abandon
end
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif mw.ustring.match(date_string, patterns_t['My-My'][1]) then -- month/season year - month/season year; separated by spaced endash
month, year, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['My-My'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor_year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style
month = get_month_number(month);
month2 = get_month_number(month2);
elseif 0 ~= get_season_number(month, param) and 0 ~= get_season_number(month2, param) then -- both must be season year, not mixed
month = get_season_number(month, param);
month2 = get_season_number(month2, param);
else
return false;
end
elseif mw.ustring.match(date_string, patterns_t['M-My'][1]) then -- month/season range year; months separated by endash
month, month2, anchor_year, year = mw.ustring.match(date_string, patterns_t['M-My'][1]);
if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
month2 = get_month_number(month2);
if 0 == month or 0 == month2 then return false; end
else
month = get_season_number(month, param);
month2 = get_season_number(month2, param);
end
year2 = year;
elseif mw.ustring.match(date_string, patterns_t['My'][1]) then -- month/season/quarter/proper-name year
month, anchor_year, year = mw.ustring.match(date_string, patterns_t['My'][1]);
if not is_valid_year(year) then return false; end
month = get_element_number(month, param); -- get month season quarter proper-name number or nil
if not month then return false; end -- not valid whatever it is
elseif mw.ustring.match(date_string, patterns_t['y-y'][1]) then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
year, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['y-y'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif mw.ustring.match(date_string, patterns_t['y4-y2'][1]) then -- Year range: YYYY–YY; separated by unspaced endash
local century;
year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns_t['y4-y2'][1]);
anchor_year = year .. '–' .. anchor_year; -- assemble anchor year from both years
if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003
year2 = century .. year2; -- add the century to year2 for comparisons
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if in_array (param, {'date', 'publication-date', 'year'}) then -- here when 'valid' abbreviated year range; if one of these parameters
add_prop_cat ('year-range-abbreviated'); -- add properties cat
end
elseif mw.ustring.match(date_string, patterns_t['y'][1]) then -- year; here accept either YYY or YYYY
anchor_year, year = mw.ustring.match(date_string, patterns_t['y'][1]);
if false == is_valid_year(year) then
return false;
end
else
return false; -- date format not one of the MOS:DATE approved formats
end
if param ~= 'date' then -- CITEREF disambiguation only allowed in |date=; |year= & |publication-date= promote to date
if anchor_year:match ('%l$') then
return false;
end
end
if 'access-date' == param then -- test access-date here because we have numerical date parts
if 0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required
0 == year2 and 0 == month2 and 0 == day2 then -- none of these; access-date must not be a range
if not is_valid_accessdate(year .. '-' .. month .. '-' .. day) then
return false; -- return false when access-date out of bounds
end
else
return false; -- return false when access-date is a range of two dates
end
end
if 'archive-date' == param then -- test archive-date here because we have numerical date parts
if not (0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required
0 == year2 and 0 == month2 and 0 == day2) then -- none of these; archive-date must not be a range
return false; -- return false when archive-date is a range of two dates
end
end
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date)
result = is_valid_date (year, month, day, param); -- <param> for |pmc-embargo-date=
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range)
result = is_valid_date (year, month, day);
result = result and is_valid_date (year, month, day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range)
result = is_valid_date (year, month, day);
result = result and is_valid_date (year, month2, day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range)
result = is_valid_date(year, month, day);
result = result and is_valid_date(year2, month2, day2);
end
if false == result then return false; end
if nil ~= COinS_date_t then -- this table only passed into this function when testing |date= parameter values
make_COinS_date ({year = year, month = month, day = day, year2 = year2, month2 = month2, day2 = day2}, COinS_date_t); -- make an ISO 8601 date string for COinS
end
return true, anchor_year; -- format is good and date string represents a real date
end
--[[--------------------------< D A T E S >--------------------------------------------------------------------
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns
true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in
the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes).
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,
parameters with errors are added to the <error_list> sequence table as the dates are tested.
]]
local function dates(date_parameters_list, COinS_date_t, error_list)
local anchor_year; -- will return as nil if the date being tested is not |date=
local embargo_date; -- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999
local good_date;
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v.val) then -- if the parameter has a value
v.val = mw.ustring.gsub(v.val, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9
if v.val:match("^c%. [1-9]%d%d%d?%l?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
local year = v.val:match("c%. ([1-9]%d%d%d?)%l?"); -- get the year portion so it can be tested
if 'date' == k then
anchor_year = v.val:match ('(c%. [1-9]%d%d%d?%l?)'); -- anchor year only from |date= parameter
good_date = is_valid_year(year);
elseif 'year' == k then
good_date = is_valid_year(year);
else
good_date = false;
end
elseif 'date' == k then -- if the parameter is |date=
if v.val:match (patterns_t['n.d.'][1]) then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match (patterns_t['n.d.'][1]); -- "n.d."; no error when date parameter is set to no date
elseif v.val:match (patterns_t.nd[1]) then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match (patterns_t.nd[1]); -- "nd"; no error when date parameter is set to no date
else
good_date, anchor_year = check_date (v.val, k, COinS_date_t); -- go test the date
end
elseif 'year' == k then -- if the parameter is |year= it should hold only a year value
if v.val:match("^[1-9]%d%d%d?%l?$") then -- if |year = 3 or 4 digits only with or without a CITEREF disambiguator
good_date, anchor_year = true, v.val:match ("((%d+)%l?)");
else
good_date = false;
end
elseif 'pmc-embargo-date' == k then -- if the parameter is |pmc-embargo-date=
good_date = check_date (v.val, k); -- go test the date
if true == good_date then -- if the date is a valid date
good_date, embargo_date = is_valid_embargo_date (v.val); -- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo date; no: returns 9999
end
else -- any other date-holding parameter
good_date = check_date (v.val, k); -- go test the date
end
if false == good_date then -- assemble one error message so we don't add the tracking category multiple times
table.insert (error_list, wrap_style ('parameter', v.name)); -- make parameter name suitable for error message list
end
end
end
return anchor_year, embargo_date; -- and done
end
--[[--------------------------< Y E A R _ C H E C K >----------------------------------------------------------
Temporary function to test |year= for acceptable values:
YYY, YYYY, year-only ranges, their circa forms, with or without CITEREF disambiguators.
When |year= holds some form of date that is not one of these year-only dates, emit a maintenance message.
This function necessary because many non-cs1|2 templates have a |year= parameter so cirrus searches are more-or-
less useless
]]
local function year_check (year)
year = year:gsub ('c%. *', ''); -- remove circa annotation (if present) before testing <year>
for _, index in ipairs ({'y-y', 'y4-y2', 'y'}) do -- spin through these indexes into patterns_t
if mw.ustring.match (year, patterns_t[index][1]) then
return; -- if a match then |year= holds a valid 'year'
end
end
set_message ('maint_year'); -- if here, |year= value is not an accepted value; add a maint cat
end
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------
Compare the value provided in |year= with the year value(s) provided in |date=. This function sets a local numeric value:
0 - year value does not match the year value in date
1 - (default) year value matches the year value in date or one of the year values when date contains two years
2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)
the numeric value in <result> determines the 'output' if any from this function:
0 – adds error message to error_list sequence table
1 – adds maint cat
2 – does nothing
]]
local function year_date_check (year_string, year_origin, date_string, date_origin, error_list)
local year;
local date1;
local date2;
local result = 1; -- result of the test; assume that the test passes
year = year_string:match ('(%d%d%d%d?)');
if date_string:match ('%d%d%d%d%-%d%d%-%d%d') then --special case where both date and year are required YYYY-MM-DD and YYYYx
date1 = date_string:match ('(%d%d%d%d)');
year = year_string:match ('(%d%d%d%d)');
if year ~= date1 then
result = 0; -- years don't match
elseif year_string:match ('%d%d%d%d%a') then
result = 2; -- years match; but because disambiguated, don't add to maint cat
end
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard range formats of date with two three- or four-digit years
date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)");
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif mw.ustring.match(date_string, "%d%d%d%d[%-–]%d%d") then -- YYYY-YY date ranges
local century;
date1, century, date2 = mw.ustring.match(date_string, "((%d%d)%d%d)[%-–]+(%d%d)");
date2 = century..date2; -- convert YY to YYYY
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year
date1 = date_string:match ("(%d%d%d%d?)");
if year ~= date1 then
result = 0;
end
else -- should never get here; this function called only when no other date errors
result = 0; -- no recognizable year in date
end
if 0 == result then -- year / date mismatch
table.insert (error_list, substitute (cfg.messages['mismatch'], {year_origin, date_origin})); -- add error message to error_list sequence table
elseif 1 == result then -- redundant year / date
set_message ('maint_date_year'); -- add a maint cat
end
end
--[[--------------------------< R E F O R M A T T E R >--------------------------------------------------------
reformat 'date' into new format specified by format_param if pattern_idx (the current format of 'date') can be
reformatted. Does the grunt work for reformat_dates().
The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds:
format string used by string.format()
identifier letters ('d', 'm', 'y', 'd2', 'm2', 'y2') that serve as indexes into a table t{} that holds captures
from mw.ustring.match() for the various date parts specified by patterns_t[pattern_idx][1]
Items in patterns_t{} have the general form:
['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, where:
['ymd'] is pattern_idx
patterns_t['ymd'][1] is the match pattern with captures for mw.ustring.match()
patterns_t['ymd'][2] is an indicator letter identifying the content of the first capture
patterns_t['ymd'][3] ... the second capture etc.
when a pattern matches a date, the captures are loaded into table t{} in capture order using the idemtifier
characters as indexes into t{} For the above, a ymd date is in t{} as:
t.y = first capture (year), t.m = second capture (month), t.d = third capture (day)
To reformat, this function is called with the pattern_idx that matches the current format of the date and with
format_param set to the desired format. This function loads table t{} as described and then calls string.format()
with the format string specified by re_format[pattern_idx][format_param][1] using values taken from t{} according
to the capture identifier letters specified by patterns_t[pattern_idx][format_param][n] where n is 2..
]]
local re_formats = {
['ymd'] = { -- date format is ymd; reformat to:
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['Mdy'] = { -- date format is Mdy; reformat to:
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- for long/short reformatting
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['dMy'] = { -- date format is dMy; reformat to:
['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- ['yMd'] = {'%s %s %s', 'y', 'm', 'd'}, -- |df=yMd; not supported at en.wiki
},
['Md-dy'] = { -- date format is Md-dy; reformat to:
['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- for long/short reformatting
['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- |df=dmy -> d-dMy
},
['d-dMy'] = { -- date format is d-d>y; reformat to:
['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'}, -- |df=mdy -> Md-dy
},
['dM-dMy'] = { -- date format is dM-dMy; reformat to:
['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- for long/short reformatting
['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- |df=mdy -> Md-Mdy
},
['Md-Mdy'] = { -- date format is Md-Mdy; reformat to:
['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'}, -- for long/short reformatting
['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'}, -- |df=dmy -> dM-dMy
},
['dMy-dMy'] = { -- date format is dMy-dMy; reformat to:
['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- for long/short reformatting
['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- |df=mdy -> Mdy-Mdy
},
['Mdy-Mdy'] = { -- date format is Mdy-Mdy; reformat to:
['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'}, -- for long/short reformatting
['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'}, -- |df=dmy -> dMy-dMy
},
['My-My'] = { -- these for long/short reformatting
['any'] = {'%s %s – %s %s', 'm', 'y', 'm2', 'y2'}, -- dmy/mdy agnostic
},
['M-My'] = { -- these for long/short reformatting
['any'] = {'%s–%s %s', 'm', 'm2', 'y'}, -- dmy/mdy agnostic
},
['My'] = { -- these for long/short reformatting
['any'] = {'%s %s', 'm', 'y'}, -- dmy/mdy agnostic
},
-- ['yMd'] = { -- not supported at en.wiki
-- ['mdy'] = {'%s %s, %s', 'm', 'd', 'y'}, -- |df=mdy
-- ['dmy'] = {'%s %s %s', 'd', 'm', 'y'}, -- |df=dmy
-- ['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'}, -- |df=ymd
-- },
}
local function reformatter (date, pattern_idx, format_param, mon_len)
if not in_array (pattern_idx, {'ymd', 'Mdy', 'Md-dy', 'dMy', 'yMd', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then
return; -- not in this set of date format patterns_t then not a reformattable date
end
if 'ymd' == format_param and in_array (pattern_idx, {'ymd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) then
return; -- ymd date ranges not supported at en.wiki; no point in reformatting ymd to ymd
end
if in_array (pattern_idx, {'My', 'M-My', 'My-My'}) then -- these are not dmy/mdy so can't be 'reformatted' into either
format_param = 'any'; -- so format-agnostic
end
-- yMd is not supported at en.wiki; when yMd is supported at your wiki, uncomment the next line
-- if 'yMd' == format_param and in_array (pattern_idx, {'yMd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy'}) then -- these formats not convertable; yMd not supported at en.wiki
if 'yMd' == format_param then -- yMd not supported at en.wiki; when yMd is supported at your wiki, remove or comment-out this line
return; -- not a reformattable date
end
local c1, c2, c3, c4, c5, c6, c7; -- these hold the captures specified in patterns_t[pattern_idx][1]
c1, c2, c3, c4, c5, c6, c7 = mw.ustring.match (date, patterns_t[pattern_idx][1]); -- get the captures
local t = { -- table that holds k/v pairs of date parts from the captures and patterns_t[pattern_idx][2..]
[patterns_t[pattern_idx][2]] = c1; -- at minimum there is always one capture with a matching indicator letter
[patterns_t[pattern_idx][3] or 'x'] = c2; -- patterns_t can have a variable number of captures; each capture requires an indicator letter;
[patterns_t[pattern_idx][4] or 'x'] = c3; -- where there is no capture, there is no indicator letter so n in patterns_t[pattern_idx][n] will be nil;
[patterns_t[pattern_idx][5] or 'x'] = c4; -- the 'x' here spoofs an indicator letter to prevent 'table index is nil' error
[patterns_t[pattern_idx][6] or 'x'] = c5;
[patterns_t[pattern_idx][7] or 'x'] = c6;
[patterns_t[pattern_idx][8] or 'x'] = c7;
};
if t.a then -- if this date has an anchor year capture (all convertable date formats except ymd)
if t.y2 then -- for year range date formats
t.y2 = t.a; -- use the anchor year capture when reassembling the date
else -- here for single date formats (except ymd)
t.y = t.a; -- use the anchor year capture when reassembling the date
end
end
if tonumber(t.m) then -- if raw month is a number (converting from ymd)
if 's' == mon_len then -- if we are to use abbreviated month names
t.m = cfg.date_names['inv_local_short'][tonumber(t.m)]; -- convert it to a month name
else
t.m = cfg.date_names['inv_local_long'][tonumber(t.m)]; -- convert it to a month name
end
t.d = t.d:gsub ('0(%d)', '%1'); -- strip leading '0' from day if present
elseif 'ymd' == format_param then -- when converting to ymd
t.y = t.y:gsub ('%a', ''); -- strip CITREF disambiguator if present; anchor year already known so process can proceed; TODO: maint message?
if 1582 > tonumber (t.y) then -- ymd format dates not allowed before 1582
return;
end
t.m = string.format ('%02d', get_month_number (t.m)); -- make sure that month and day are two digits
t.d = string.format ('%02d', t.d);
elseif mon_len then -- if mon_len is set to either 'short' or 'long'
for _, mon in ipairs ({'m', 'm2'}) do -- because there can be two month names, check both
if t[mon] then
t[mon] = get_month_number (t[mon]); -- get the month number for this month (is length agnostic)
if 0 == t[mon] then return; end -- seasons and named dates can't be converted
t[mon] = (('s' == mon_len) and cfg.date_names['inv_local_short'][t[mon]]) or cfg.date_names['inv_local_long'][t[mon]]; -- fetch month name according to length
end
end
end
local new_date = string.format (re_formats[pattern_idx][format_param][1], -- format string
t[re_formats[pattern_idx][format_param][2]], -- named captures from t{}
t[re_formats[pattern_idx][format_param][3]],
t[re_formats[pattern_idx][format_param][4]],
t[re_formats[pattern_idx][format_param][5]],
t[re_formats[pattern_idx][format_param][6]],
t[re_formats[pattern_idx][format_param][7]],
t[re_formats[pattern_idx][format_param][8]]
);
return new_date;
end
--[[-------------------------< R E F O R M A T _ D A T E S >--------------------------------------------------
Reformats existing dates into the format specified by format.
format is one of several manual keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all. The -all version includes
access- and archive-dates; otherwise these dates are not reformatted.
This function allows automatic date formatting. In ~/Configuration, the article source is searched for one of
the {{use xxx dates}} templates. If found, xxx becomes the global date format as xxx-all. If |cs1-dates= in
{{use xxx dates}} has legitimate value then that value determines how cs1|2 dates will be rendered. Legitimate
values for |cs1-dates= are:
l - all dates are rendered with long month names
ls - publication dates use long month names; access-/archive-dates use abbreviated month names
ly - publication dates use long month names; access-/archive-dates rendered in ymd format
s - all dates are rendered with abbreviated (short) month names
sy - publication dates use abbreviated month names; access-/archive-dates rendered in ymd format
y - all dates are rendered in ymd format
the format argument for automatic date formatting will be the format specified by {{use xxx dates}} with the
value supplied by |cs1-dates so one of: xxx-l, xxx-ls, xxx-ly, xxx-s, xxx-sy, xxx-y, or simply xxx (|cs1-dates=
empty, omitted, or invalid) where xxx shall be either of dmy or mdy.
dates are extracted from date_parameters_list, reformatted (if appropriate), and then written back into the
list in the new format. Dates in date_parameters_list are presumed here to be valid (no errors). This function
returns true when a date has been reformatted, false else. Actual reformatting is done by reformatter().
]]
local function reformat_dates (date_parameters_list, format)
local all = false; -- set to false to skip access- and archive-dates
local len_p = 'l'; -- default publication date length shall be long
local len_a = 'l'; -- default access-/archive-date length shall be long
local result = false;
local new_date;
if format:match('%a+%-all') then -- manual df keyword; auto df keyword when length not specified in {{use xxx dates}};
format = format:match('(%a+)%-all'); -- extract the format
all = true; -- all dates are long format dates because this keyword doesn't specify length
elseif format:match('%a+%-[lsy][sy]?') then -- auto df keywords; internal only
all = true; -- auto df applies to all dates; use length specified by capture len_p for all dates
format, len_p, len_a = format:match('(%a+)%-([lsy])([sy]?)'); -- extract the format and length keywords
if 'y' == len_p then -- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted
format = 'ymd'; -- override {{use xxx dates}}
elseif (not is_set(len_a)) or (len_p == len_a) then -- no access-/archive-date length specified or same length as publication dates then
len_a = len_p; -- in case len_a not set
end
end -- else only publication dates and they are long
for param_name, param_val in pairs (date_parameters_list) do -- for each date-holding parameter in the list
if is_set (param_val.val) then -- if the parameter has a value
if not (not all and in_array (param_name, {'access-date', 'archive-date'})) then -- skip access- or archive-date unless format is xxx-all; yeah, ugly; TODO: find a better way
for pattern_idx, pattern in pairs (patterns_t) do
if mw.ustring.match (param_val.val, pattern[1]) then
if all and in_array (param_name, {'access-date', 'archive-date'}) then -- if this date is an access- or archive-date
new_date = reformatter (param_val.val, pattern_idx, (('y' == len_a) and 'ymd') or format, len_a); -- choose ymd or dmy/mdy according to len_a setting
else -- all other dates
new_date = reformatter (param_val.val, pattern_idx, format, len_p);
end
if new_date then -- set when date was reformatted
date_parameters_list[param_name].val = new_date; -- update date in date list
result = true; -- and announce that changes have been made
break;
end
end -- if
end -- for
end -- if
end -- if
end -- for
return result; -- declare boolean result and done
end
--[[--------------------------< D A T E _ H Y P H E N _ T O _ D A S H >----------------------------------------
Loops through the list of date-holding parameters and converts any hyphen to an ndash. Not called if the cs1|2
template has any date errors.
Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false.
]]
local function date_hyphen_to_dash (date_parameters_list)
local result = false;
local n;
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set (param_val.val) and
not mw.ustring.match (param_val.val, patterns_t.ymd[1]) then -- for those that are not ymd dates (ustring because here digits may not be Western)
param_val.val, n = param_val.val:gsub ('%-', '–'); -- replace any hyphen with ndash
if 0 ~= n then
date_parameters_list[param_name].val = param_val.val; -- update the list
result = true;
end
end
end
return result; -- so we know if any hyphens were replaced
end
--[[-------------------------< D A T E _ N A M E _ X L A T E >------------------------------------------------
Attempts to translate English date names to local-language date names using names supplied by MediaWiki's
date parser function. This is simple name-for-name replacement and may not work for all languages.
if xlat_dig is true, this function will also translate Western (English) digits to the local language's digits.
This will also translate ymd dates.
]]
local function date_name_xlate (date_parameters_list, xlt_dig)
local xlate;
local modified = false;
local date;
local sources_t = {
{cfg.date_names.en.long, cfg.date_names.inv_local_long}, -- for translating long English month names to long local month names
{cfg.date_names.en.short, cfg.date_names.inv_local_short}, -- short month names
{cfg.date_names.en.quarter, cfg.date_names.inv_local_quarter}, -- quarter date names
{cfg.date_names.en.season, cfg.date_names.inv_local_season}, -- season date nam
{cfg.date_names.en.named, cfg.date_names.inv_local_named}, -- named dates
}
local function is_xlateable (month) -- local function to get local date name that replaces existing English-language date name
for _, date_names_t in ipairs (sources_t) do -- for each sequence table in date_names_t
if date_names_t[1][month] then -- if date name is English month (long or short), quarter, season or named and
if date_names_t[2][date_names_t[1][month]] then -- if there is a matching local date name
return date_names_t[2][date_names_t[1][month]]; -- return the local date name
end
end
end
end
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(param_val.val) then -- if the parameter has a value
date = param_val.val;
for month in mw.ustring.gmatch (date, '[%a ]+') do -- iterate through all date names in the date (single date or date range)
month = mw.text.trim (month); -- this because quarterly dates contain whitespace
xlate = is_xlateable (month); -- get translate <month>; returns translation or nil
if xlate then
date = mw.ustring.gsub (date, month, xlate); -- replace the English with the translation
date_parameters_list[param_name].val = date; -- save the translated date
modified = true;
end
end
if xlt_dig then -- shall we also translate digits?
date = date:gsub ('%d', cfg.date_names.xlate_digits); -- translate digits from Western to 'local digits'
date_parameters_list[param_name].val = date; -- save the translated date
modified = true;
end
end
end
return modified;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
add_prop_cat = utilities_page_ptr.add_prop_cat ; -- import functions from selected Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
set_message = utilities_page_ptr.set_message;
substitute = utilities_page_ptr.substitute;
wrap_style = utilities_page_ptr.wrap_style;
cfg = cfg_table_ptr; -- import tables from selected Module:Citation/CS1/Configuration
end
--[[--------------------------< A R C H I V E _ D A T E _ C H E C K >------------------------------------------
Compare value in |archive-date= with the timestamp in Wayback machine urls. Emits an error message with suggested
date from the |archive-url= timestamp in an appropriate format when the value in |archive-date= does not match
the timestamp.
this function never called when any date in a cs1|2 template has errors
error message suggests new |archive-date= value in an appropriate format specified by <df>. <df> is either
|df= or cfg.global_df in that order. If <df> is nil, suggested date has format from |archive-date=. There is
a caveat: when |df=dmy or |df=mdy, the reformatter leaves |access-date= and |archive-date= formats as they are.
The error message suggested date is passed to the formatter as YYYY-MM-DD so when |df=dmy or |df=mdy, the format
is not changed.
]]
local function archive_date_check (archive_date, archive_url_timestamp, df)
local archive_date_format = 'dmy-y'; -- holds the date format of date in |archive-date; default to ymd; 'dmy' used here to spoof reformat_dates()
for _, v_t in ipairs ({{'dMy', 'dmy-all'}, {'Mdy', 'mdy-all'}}) do -- is |archive-date= format dmy or mdy?
if archive_date:match (patterns_t[v_t[1]][1]) then -- does the pattern match?
archive_date_format = cfg.keywords_xlate[v_t[2]]; -- get appropriate |df= supported keyword from the i18n translator table
break;
end
end
local dates_t = {};
dates_t['archive-date'] = {val=archive_date, name=''}; -- setup to call reformat_dates(); never called when errors so <name> unset as not needed
reformat_dates (dates_t, 'dmy-y'); -- reformat |archive-date= to ymd; 'dmy' used here to spoof reformat_dates()
local archive_url_date = archive_url_timestamp:gsub ('(%d%d%d%d)(%d%d)(%d%d)%d*', '%1-%2-%3'); -- make ymd format date from timestamp
if dates_t['archive-date'].val == archive_url_date then -- are the two dates the same
return; -- yes, done
else
dates_t['archive-date'] = {val=archive_url_date, name=''}; -- setup to call reformat_dates() with the timestamp date
reformat_dates (dates_t, df or archive_date_format); -- reformat timestamp to format specified by <df> or format used in |archive-date=
archive_url_date = dates_t['archive-date'].val;
set_message ('err_archive_date_url_ts_mismatch', archive_url_date); -- emit an error message
end
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return { -- return exported functions
archive_date_check = archive_date_check,
date_hyphen_to_dash = date_hyphen_to_dash,
date_name_xlate = date_name_xlate,
dates = dates,
is_valid_date = is_valid_date,
reformat_dates = reformat_dates,
set_selected_modules = set_selected_modules,
year_check = year_check,
year_date_check = year_date_check,
}
t2d5ocm3ym8yza0dgkl1tstgc2yr6dq
Module:Citation/CS1/Identifiers
828
929
9011
2026-08-08T13:56:47Z
en>Trappist the monk
0
synch from sandbox;
9011
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local has_accept_as_written, is_set, in_array, set_message, select_one, -- functions in Module:Citation/CS1/Utilities
substitute, make_wikilink;
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< P A G E S C O P E V A R I A B L E S >--------------------------------------
declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here
]]
local auto_link_urls = {}; -- holds identifier URLs for those identifiers that can auto-link |title=
--============================<< H E L P E R F U N C T I O N S >>============================================
--[[--------------------------< W I K I D A T A _ A R T I C L E _ N A M E _ G E T >----------------------------
as an aid to internationalizing identifier-label wikilinks, gets identifier article names from Wikidata.
returns w:<lang code>:<article title> when <q> has an <article title> for <lang code>; nil else. 'w:<lang code>'
ensures that sister project (like wiktionary) will link to the <lang code>.wikipedia article.
for identifiers that do not have <q>, returns nil
for wikis that do not have mw.wikibase installed, returns nil
]]
local function wikidata_article_name_get (q)
if not is_set (q) or (q and not mw.wikibase) then -- when no q number or when a q number but mw.wikibase not installed on this wiki
return nil; -- abandon
end
local wd_article;
local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org
wd_article = mw.wikibase.getSitelink (q, this_wiki_code .. 'wiki'); -- fetch article title from WD; nil when no title available at this wiki
if wd_article then
wd_article = table.concat ({'w:', this_wiki_code, ':', wd_article}); -- interwiki-style link without brackets if taken from WD; leading 'w:' required
end
return wd_article; -- article title from WD; nil else
end
--[[--------------------------< L A B E L _ L I N K _ M A K E >------------------------------------------------
common function to create a link for an identifier label from handler table or from Wikidata
returns the first available of:
1. redirect from local wiki's handler table (if enabled)
2. Wikidata sitelink to the local language wikipedia article (if there is a Wikidata entry for this identifier in the local language)
3. link to wikipedia article specified in the local wiki's handler table
]]
local function label_link_make (handler)
local wd_article;
if not (cfg.use_identifier_redirects and is_set (handler.redirect)) then -- redirect has priority so if enabled and available don't fetch from Wikidata because expensive
wd_article = wikidata_article_name_get (handler.q); -- if Wikidata has an article title for this wiki, get it;
end
return (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link;
end
--[[--------------------------< E X T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki-style external link
]]
local function external_link_id (options)
local url_string = options.id;
local ext_link;
if options.encode == true or options.encode == nil then
url_string = mw.uri.encode (url_string, 'PATH');
end
if options.auto_link and is_set (options.access) then
auto_link_urls[options.auto_link] = table.concat ({options.prefix, url_string, options.suffix});
end
ext_link = mw.ustring.format ('[%s%s%s %s]', options.prefix, url_string, options.suffix or "", mw.text.nowiki (options.id));
if is_set (options.access) then
ext_link = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[options.access].class, cfg.presentation[options.access].title, ext_link}); -- add the free-to-read / paywall lock
end
return table.concat ({
make_wikilink (label_link_make (options), options.label), -- redirect, Wikidata link, or locally specified link (in that order)
options.separator or ' ',
ext_link
});
end
--[[--------------------------< I N T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki-style internal link
TODO: Does not currently need to support options.access, options.encode, auto-linking and COinS (as in external_link_id),
but may be needed in the future for :m:Interwiki_map custom-prefixes like :arxiv:, :bibcode:, :DOI:, :hdl:, :ISSN:,
:JSTOR:, :Openlibrary:, :PMID:, :RFC:.
]]
local function internal_link_id (options)
local id = mw.ustring.gsub (options.id, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9
return table.concat (
{
make_wikilink (label_link_make (options), options.label), -- wiki-link the identifier label
options.separator or ' ', -- add the separator
make_wikilink (
table.concat (
{
options.prefix,
id, -- translated to Western digits
options.suffix or ''
}),
substitute (cfg.presentation['bdi'], {'', mw.text.nowiki (options.id)}) -- bdi tags to prevent Latin script identifiers from being reversed at RTL language wikis
); -- nowiki because MediaWiki still has magic links for ISBN and the like; TODO: is it really required?
});
end
--[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------
Determines if a PMC identifier's online version is embargoed. Compares the date in |pmc-embargo-date= against
today's date. If embargo date is in the future, returns the content of |pmc-embargo-date=; otherwise, returns
an empty string because the embargo has expired or because |pmc-embargo-date= was not set in this cite.
]]
local function is_embargoed (embargo)
if is_set (embargo) then
local lang = mw.getContentLanguage();
local good1, embargo_date, todays_date;
good1, embargo_date = pcall (lang.formatDate, lang, 'U', embargo);
todays_date = lang:formatDate ('U');
if good1 then -- if embargo date is a good date
if tonumber (embargo_date) >= tonumber (todays_date) then -- is embargo date is in the future?
return embargo; -- still embargoed
else
set_message ('maint_pmc_embargo'); -- embargo has expired; add main cat
return ''; -- unset because embargo has expired
end
end
end
return ''; -- |pmc-embargo-date= not set return empty string
end
--[=[-------------------------< I S _ V A L I D _ R X I V _ D A T E >------------------------------------------
for biorxiv, returns true if:
2019-12-11T00:00Z <= biorxiv_date < today + 2 days
for medrxiv, returns true if:
2020-01-01T00:00Z <= medrxiv_date < today + 2 days
The dated form of biorxiv identifier has a start date of 2019-12-11. The Unix timestamp for that date is {{#time:U|2019-12-11}} = 1576022400
The medrxiv identifier has a start date of 2020-01-01. The Unix timestamp for that date is {{#time:U|2020-01-01}} = 1577836800
<rxiv_date> is the date provided in those |biorxiv= parameter values that are dated and in |medrxiv= parameter values at time 00:00:00 UTC
<today> is the current date at time 00:00:00 UTC plus 48 hours
if today's date is 2023-01-01T00:00:00 then
adding 24 hours gives 2023-01-02T00:00:00 – one second more than today
adding 24 hours gives 2023-01-03T00:00:00 – one second more than tomorrow
inputs:
<y>, <m>, <d> – year, month, day parts of the date from the birxiv or medrxiv identifier
<select> 'b' for biorxiv, 'm' for medrxiv; defaults to 'b'
]=]
local function is_valid_rxiv_date (y, m, d, select)
if 0 == tonumber (m) and 12 < tonumber (m) then -- <m> must be a number 1–12
return false;
end
if 0 == tonumber (d) and 31 < tonumber (d) then -- <d> must be a number 1–31; TODO: account for month length and leap yer?
return false;
end
local rxiv_date = table.concat ({y, m, d}, '-'); -- make ymd date string
local good1, good2;
local rxiv_ts, tomorrow_ts; -- to hold Unix timestamps representing the dates
local lang_object = mw.getContentLanguage();
good1, rxiv_ts = pcall (lang_object.formatDate, lang_object, 'U', rxiv_date); -- convert rxiv_date value to Unix timestamp
good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which tonumber() may not understand
rxiv_ts = tonumber (rxiv_ts) or lang_object:parseFormattedNumber (rxiv_ts); -- convert to numbers for the comparison;
tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts);
else
return false; -- one or both failed to convert to Unix timestamp
end
local limit_ts = ((select and ('m' == select)) and 1577836800) or 1576022400; -- choose the appropriate limit timesatmp
return ((limit_ts <= rxiv_ts) and (rxiv_ts < tomorrow_ts)) -- limit_ts <= rxiv_date < tomorrow's date
end
--[[--------------------------< IS _ V A L I D _ I S X N >-----------------------------------------------------
ISBN-10 and ISSN validator code calculates checksum across all ISBN/ISSN digits including the check digit.
ISBN-13 is checked in isbn().
If the number is valid the result will be 0. Before calling this function, ISBN/ISSN must be checked for length
and stripped of dashes, spaces and other non-ISxN characters.
]]
local function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58
len = len + 1; -- adjust to be a loop counter
for i, v in ipairs (isxn_str) do -- loop through all of the bytes and calculate the checksum
if v == string.byte ("X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58)
temp = temp + 10 * (len - i); -- it represents 10 decimal
else
temp = temp + tonumber (string.char (v) )*(len-i);
end
end
return temp % 11 == 0; -- returns true if calculation result is zero
end
--[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >-----------------------------------------------
ISBN-13 and ISMN validator code calculates checksum across all 13 ISBN/ISMN digits including the check digit.
If the number is valid, the result will be 0. Before calling this function, ISBN-13/ISMN must be checked for length
and stripped of dashes, spaces and other non-ISxN-13 characters.
]]
local function is_valid_isxn_13 (isxn_str)
local temp=0;
isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39
for i, v in ipairs (isxn_str) do
temp = temp + (3 - 2*(i % 2)) * tonumber (string.char (v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit
end
return temp % 10 == 0; -- sum modulo 10 is zero when ISBN-13/ISMN is correct
end
--[[--------------------------< N O R M A L I Z E _ L C C N >--------------------------------------------------
LCCN normalization (https://www.loc.gov/marc/lccn-namespace.html#normalization)
1. Remove all blanks.
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.
3. If there is a hyphen in the string:
a. Remove it.
b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):
1. All these characters should be digits, and there should be six or less. (not done in this function)
2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.
Returns a normalized LCCN for lccn() to validate. There is no error checking (step 3.b.1) performed in this function.
]]
local function normalize_lccn (lccn)
lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace
if nil ~= string.find (lccn, '/') then
lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it
end
local prefix
local suffix
prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix
if nil ~= suffix then -- if there was a hyphen
suffix = string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6
lccn = prefix..suffix; -- reassemble the LCCN
end
return lccn;
end
--============================<< I D E N T I F I E R F U N C T I O N S >>====================================
--[[--------------------------< A R X I V >--------------------------------------------------------------------
See: https://arxiv.org/help/arxiv_identifier
format and error check arXiv identifier. There are three valid forms of the identifier:
the first form, valid only between date codes 9107 and 0703, is:
arXiv:<archive>.<class>/<date code><number><version>
where:
<archive> is a string of alpha characters - may be hyphenated; no other punctuation
<class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
first digit of YY for this form can only 9 and 0
<number> is a three-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)
the second form, valid from April 2007 through December 2014 is:
arXiv:<date code>.<number><version>
where:
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
<number> is a four-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces
the third form, valid from January 2015 is:
arXiv:<date code>.<number><version>
where:
<date code> and <version> are as defined for 0704-1412
<number> is a five-digit number
]]
local function arxiv (options)
local id = options.id;
local class = options.Class; -- TODO: lowercase?
local handler = options.handler;
local year, month;
local err_msg = false; -- assume no error message
local text; -- output text
if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9107-0703 format with or without version
year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month
((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok?
err_msg = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 with or without version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years)
((7 == year) and (4 > month)) then -- when year is 07, is month invalid (before April)?
err_msg = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format with or without version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years)
err_msg = true; -- flag for error message
end
else
err_msg = true; -- not a recognized format; flag for error message
end
if err_msg then
options.coins_list_t['ARXIV'] = nil; -- when error, unset so not included in COinS
end
if err_msg then
set_message ('err_bad_arxiv');
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});
if is_set (class) then
if id:match ('^%d+') then
text = table.concat ({text, ' [[https://arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink
else
set_message ('err_class_ignored');
end
else -- class not set
if id:match ('^%d+') and options.CitationClass == 'arxiv' then -- new (post 2007) format; {{cite arxiv}} only
set_message ('maint_missing_class'); -- add maint cat
end
end
return text;
end
--[[--------------------------< B I B C O D E >--------------------------------------------------------------------
Validates (sort of) and formats a bibcode ID.
Format for bibcodes is specified here: https://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes
But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters
and first four digits must be a year. This function makes these tests:
length must be 19 characters
characters in position
1–4 must be digits and must represent a year in the range of 1000 – next year
5 must be a letter
6–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. )
9–18 must be letter, digit, or dot
19 must be a letter or dot
]]
local function bibcode (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local ignore_invalid = options.accept;
local err_type;
local year;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,
access = access});
if 19 ~= id:len() then
err_type = cfg.err_msg_supl.length;
else
year = id:match ("^(%d%d%d%d)[%a][%w&%.][%w&%.][%w&%.][%w.]+[%a%.]$");
if not year then -- if nil then no pattern match
err_type = cfg.err_msg_supl.value; -- so value error
else
local next_year = tonumber (os.date ('%Y')) + 1; -- get the current year as a number and add one for next year
year = tonumber (year); -- convert year portion of bibcode to a number
if (1000 > year) or (year > next_year) then
err_type = cfg.err_msg_supl.year; -- year out of bounds
end
if id:find('&%.') then
err_type = cfg.err_msg_supl.journal; -- journal abbreviation must not have '&.' (if it does it's missing a letter)
end
if id:match ('.........%.tmp%.') then -- temporary bibcodes when positions 10–14 are '.tmp.'
set_message ('maint_bibcode');
end
end
end
if is_set (err_type) and not ignore_invalid then -- if there was an error detected and accept-as-written markup not used
set_message ('err_bad_bibcode', {err_type});
options.coins_list_t['BIBCODE'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< B I O R X I V >-----------------------------------------------------------------
Format bioRxiv ID and do simple error checking. Before 2019-12-11, biorXiv IDs were 10.1101/ followed by exactly
6 digits. After 2019-12-11, biorXiv IDs retained the six-digit identifier but prefixed that with a yyyy.mm.dd.
date and suffixed with an optional version identifier.
From December 2025 biorxiv added a new 'doi' prefix: 10.64898:
10.64898/2025.12.10.693067
The bioRxiv ID is the string of characters:
https://doi.org/10.1101/078733 -> 10.1101/078733
or a date followed by a six-digit number followed by an optional version indicator 'v' and one or more digits:
https://www.biorxiv.org/content/10.1101/2019.12.11.123456v2 -> 10.1101/2019.12.11.123456v2
see https://www.biorxiv.org/about-biorxiv
]]
local function biorxiv (options)
local id = options.id;
local handler = options.handler;
local err_msg = true; -- flag; assume that there will be an error
local patterns = {
'^10%.1101/%d%d%d%d%d%d$', -- simple 6-digit identifier (before 2019-12-11)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (after 2019-12-11)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (after 2019-12-11)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (from December 2025)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (from December 2025)
}
for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match
if id:match (pattern) then
local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier
if m then -- m is nil when id is the six-digit form
if not is_valid_rxiv_date (y, m, d, 'b') then -- validate the encoded date; 'b' for biorxiv limit
break; -- date fail; break out early so we don't unset the error message
end
end
err_msg = nil; -- we found a match so unset the error message
break; -- and done
end
end -- err_cat remains set here when no match
if err_msg then
options.coins_list_t['BIORXIV'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_biorxiv'); -- and set the error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator,
encode = handler.encode, access = handler.access});
end
--[[--------------------------< C I T E S E E R X >------------------------------------------------------------
CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org).
The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure
]]
local function citeseerx (options)
local id = options.id;
local handler = options.handler;
local matched;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,
access = handler.access});
matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$");
if not matched then
set_message ('err_bad_citeseerx' );
options.coins_list_t['CITESEERX'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< D O I >------------------------------------------------------------------------
Formats a DOI and checks for DOI errors.
DOI names contain two parts: prefix and suffix separated by a forward slash.
Prefix: directory indicator '10.' followed by a registrant code
Suffix: character string of any length chosen by the registrant
This function checks a DOI name for: prefix/suffix. If the DOI name contains spaces or endashes, or, if it ends
with a period or a comma, this function will emit a bad_doi error message.
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in DOI names.
https://www.doi.org/doi_handbook/2_Numbering.html -- 2.2 Syntax of a DOI name
https://www.doi.org/doi_handbook/2_Numbering.html#2.2.2 -- 2.2.2 DOI prefix
]]
local function doi (options)
local id = options.id;
local inactive = options.DoiBroken
local access = options.access;
local ignore_invalid = options.accept;
local handler = options.handler;
local err_flag; -- error flag for errors that may not be ignored
local ignorable_err_flag; -- error flag for ((ignorable)) errors
local function is_extended_free (registrant, suffix) -- local function to check those few registrants that are mixed; identifiable by the doi suffix <incipit>
suffix = suffix:lower(); -- ascii [a-z] same as [A-Z] in doi names; see §3.4.4 Case Insensitivity of the Doi Name
if cfg.extended_registrants_t[registrant] then -- if this registrant has known free-to-read extentions
for _, incipit in ipairs (cfg.extended_registrants_t[registrant]) do -- loop through the registrant's incipits
if mw.ustring.find (suffix, '^' .. incipit:lower()) then -- ascii [a-z] same as [A-Z] in doi names
return true; -- if found done
end
end
end
end
local text;
if is_set (inactive) then
local inactive_year = inactive:match("%d%d%d%d"); -- try to get the year portion from the inactive date
local inactive_month, good;
if is_set (inactive_year) then
if 4 < inactive:len() then -- inactive date has more than just a year (could be anything)
local lang_obj = mw.getContentLanguage(); -- get a language object for this wiki
good, inactive_month = pcall (lang_obj.formatDate, lang_obj, 'F', inactive); -- try to get the month name from the inactive date
if not good then
inactive_month = nil; -- something went wrong so make sure this is unset
end
end
end -- otherwise, |doi-broken-date= has something but it isn't a date
if is_set (inactive_year) and is_set (inactive_month) then
set_message ('maint_doi_inactive_dated', {inactive_year, inactive_month, ' '});
elseif is_set (inactive_year) then
set_message ('maint_doi_inactive_dated', {inactive_year, '', ''});
else
set_message ('maint_doi_inactive');
end
inactive = substitute (cfg.messages['inactive'], inactive );
end
local registrant, suffix = mw.ustring.match (id, '^10%.([^/]+)/([^%s–]+)$'); -- registrant and suffix set when DOI has the proper basic form; both nil else
if suffix then
if suffix:match ('[%.,]$') then -- |doi= has basic form but suffix has trailing dot or comma
ignorable_err_flag = true; -- set the flag so that we can emit an error message if not ignored
end
else -- here when |doi= does not have proper basic form
err_flag = true; -- set the non-ignorable error flag
ignore_invalid = false; -- unset because this error may not be ignored
end
local registrant_err_patterns = { -- these patterns are for code ranges that are not supported
'^[^1-3]%d%d%d%d%.%d+$', -- 5 digits with subcode (reject 0xxxx, 40000+); accepts: 10000–39999
'^[^1-8]%d%d%d%d$', -- 5 digits without subcode (reject 0xxxx, 90000+); accepts: 10000–89999
'^[^1-9]%d%d%d%.%d+$', -- 4 digits with subcode (reject 0xxx); accepts: 1000–9999
'^[^1-9]%d%d%d$', -- 4 digits without subcode (reject 0xxx); accepts: 1000–9999
'^%d%d%d%d%d%d+', -- 6 or more digits
'^%d%d?%d?$', -- less than 4 digits without subcode (3 digits with subcode is legitimate)
'^%d%d?%.[%d%.]+', -- 1 or 2 digits with subcode
'^5555$', -- test registrant will never resolve
'[^%d%.]', -- any character that isn't a digit or a dot
}
if not err_flag then -- when DOI has proper form; <err_flag> is true when |doi= is malformed
if not ignore_invalid then -- when we're not ignoring errors
if registrant then -- when DOI has proper form
for i, pattern in ipairs (registrant_err_patterns) do -- spin through error patterns
if registrant:match (pattern) then -- to validate registrant codes
ignorable_err_flag = true; -- when found, mark this DOI as bad
break; -- and done
end
end
end
else -- here when ignoring invalid |doi= values
ignorable_err_flag = false; -- unset so we don't emit an error message for ignorable errors
set_message ('maint_doi_ignore'); -- add maint message when doi is properly formatted
end
end
if err_flag or ignorable_err_flag then
set_message ('err_bad_doi'); -- invalid |doi= value; emit an error message
options.coins_list_t['DOI'] = nil; -- when in error, unset so |doi= value not included in COinS
else -- here when doi has no errors or has been wrapped in accept-as-written markup
suffix = mw.ustring.match (id, '^10%.[^/]+/(.+)'); -- refetch suffix because doi may have been wrapped in accept-as-written markup
if not access and (cfg.known_free_doi_registrants_t[registrant] or is_extended_free (registrant, suffix)) then -- |doi-access=free not set and <registrant> is known to be free
set_message ('maint_doi_unflagged_free'); -- set a maint cat
end
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access,
auto_link = not (err_flag or is_set (inactive) or ignore_invalid) and 'doi' or nil -- do not auto-link when |doi-broken-date= has a value or when there is a DOI error or (to play it safe, after all, auto-linking is not essential) when invalid DOIs are ignored
}) .. (inactive or '');
return text;
end
--[[--------------------------< H D L >------------------------------------------------------------------------
Formats an HDL with minor error checking.
HDL names contain two parts: prefix and suffix separated by a forward slash.
Prefix: character string using any character in the UCS-2 character set except '/'
Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant
This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends
with a period or a comma, this function will emit a bad_hdl error message.
HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and
terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in HDLs.
Query string parameters are named here: https://www.handle.net/proxy_servlet.html. query strings are not displayed
but since '?' is an allowed character in an HDL, '?' followed by one of the query parameters is the only way we
have to detect the query string so that it isn't URL-encoded with the rest of the identifier.
]]
local function hdl (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local query_params_t = { -- list of known query parameters from https://www.handle.net/proxy_servlet.html
'noredirect',
'ignore_aliases',
'auth',
'cert',
'index',
'type',
'urlappend',
'locatt',
'action',
}
local handle, suffix, param = id:match ('(.-)(%?(%a+).+)$'); -- look for query string
local found;
if handle then -- when there are query strings, this is the handle identifier portion
for _, q in ipairs (query_params_t) do -- spin through the list of query parameters
if param:match ('^' .. q) then -- if the query string begins with one of the parameters
found = true; -- announce a find
break; -- and stop looking
end
end
end
if found then
id = handle; -- found so replace id with the handle portion; this will be URL-encoded, suffix will not
else
suffix = ''; -- make sure suffix is empty string for concatenation else
end
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, suffix = suffix, separator = handler.separator, encode = handler.encode, access = access})
if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- HDL must contain a forward slash, must not contain spaces, endashes, and must not end with period or comma
set_message ('err_bad_hdl' );
options.coins_list_t['HDL'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< I S B N >----------------------------------------------------------------------
Determines whether an ISBN string is valid
]]
local function isbn (options_t)
local isbn_str = options_t.id;
local ignore_invalid = options_t.accept;
local handler = options_t.handler;
local year = options_t.Year; -- when set, valid anchor_year; may have a disambiguator which must be removed
local function return_result (check, err_type) -- local function to handle the various returns
local ISBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = isbn_str, separator = handler.separator});
if ignore_invalid then -- if ignoring ISBN errors
set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error
else -- here when not ignoring
if not check then -- and there is an error
options_t.coins_list_t['ISBN'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_isbn', err_type); -- set an error message
return ISBN; -- return id text
end
end
return ISBN; -- return id text
end
if year and not ignore_invalid then --
year = year:match ('%d%d%d%d?'); -- strip disambiguator if present
if year and (1965 > tonumber(year)) then -- <year> will be nil here when |year=n.d. or |year=nd
set_message ('err_invalid_isbn_date'); -- set an error message
return internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = isbn_str, separator = handler.separator});
end
end
if nil ~= isbn_str:match ('[^%s-0-9X]') then
return return_result (false, cfg.err_msg_supl.char); -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
end
local id = isbn_str:gsub ('[%s-]', ''); -- remove hyphens and whitespace
local len = id:len();
if len ~= 10 and len ~= 13 then
return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length
end
if len == 10 then
if id:match ('^%d*X?$') == nil then -- fail if isbn_str has 'X' anywhere but last position
return return_result (false, cfg.err_msg_supl.form);
end
if not is_valid_isxn (id, 10) then -- test isbn-10 for numerical validity
return return_result (false, cfg.err_msg_supl.check); -- fail if isbn-10 is not numerically valid
end
if id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not valid isbn group ids but are used by amazon as numeric identifiers (asin)
return return_result (false, cfg.err_msg_supl.group); -- fail if isbn-10 begins with 630/1
end
return return_result (true, cfg.err_msg_supl.check); -- pass if isbn-10 is numerically valid
else
if id:match ('^%d+$') == nil then
return return_result (false, cfg.err_msg_supl.char); -- fail if ISBN-13 is not all digits
end
if id:match ('^97[89]%d*$') == nil then
return return_result (false, cfg.err_msg_supl.prefix); -- fail when ISBN-13 does not begin with 978 or 979
end
if id:match ('^9790') then
return return_result (false, cfg.err_msg_supl.group); -- group identifier '0' is reserved to ISMN
end
return return_result (is_valid_isxn_13 (id), cfg.err_msg_supl.check);
end
end
--[[--------------------------< A S I N >----------------------------------------------------------------------
Formats a link to Amazon. Do simple error checking: ASIN must be mix of 10 numeric or uppercase alpha
characters. If a mix, first character must be uppercase alpha; if all numeric, ASINs must be 10-digit
ISBN. If 10-digit ISBN, add a maintenance category so a bot or AWB script can replace |asin= with |isbn=.
Error message if not 10 characters, if not ISBN-10, if mixed and first character is a digit.
|asin=630....... and |asin=631....... are (apparently) not a legitimate ISBN though it checksums as one; these
do not cause this function to emit the maint_asin message
This function is positioned here because it calls isbn()
]]
local function asin (options)
local id = options.id;
local domain = options.ASINTLD;
local err_flag = nil; -- must be explicitly initialized
if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then
err_flag = set_message ('err_bad_asin'); -- ASIN is not a mix of 10 uppercase alpha and numeric characters
else
if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X)
if is_valid_isxn (id, 10) then -- see if ASIN value is or validates as ISBN-10
if not id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not a valid isbn prefixes but are used by amazon as a numeric identifier
err_flag = set_message ('err_bad_asin'); -- ASIN has ISBN-10 form but begins with something other than 630/1 so probably an isbn
end
elseif not is_set (err_flag) then
err_flag = set_message ('err_bad_asin'); -- ASIN is not ISBN-10
end
elseif not id:match("^%u[%d%u]+$") then
err_flag = set_message ('err_bad_asin'); -- asin doesn't begin with uppercase alpha
end
end
if (not is_set (domain)) or in_array (domain, {'us'}) then -- default: United States
domain = "com";
elseif in_array (domain, {'jp', 'uk', 'za'}) then -- Japan, United Kingdom, South Africa
domain = "co." .. domain;
elseif in_array (domain, {'z.cn'}) then -- China
domain = "cn";
elseif in_array (domain, {'au', 'be', 'br', 'mx', 'sg', 'tr'}) then -- Australia, Belgium, Brazil, Mexico, Singapore, Turkey
domain = "com." .. domain;
elseif not in_array (domain, {'ae', 'ca', 'cn', 'de', 'eg', 'es', 'fr', 'ie', 'in', 'it', 'nl', 'pl', 'sa', 'se', 'co.jp', 'co.uk', 'com', 'com.au', 'com.br', 'com.mx', 'com.sg', 'com.tr'}) then -- Arabic Emirates, Canada, China, Germany, Egypt, Spain, France, Ireland, Indonesia, Italy, Netherlands, Poland, Saudi Arabia, Sweden (as of 2021-03 Austria (.at), Liechtenstein (.li) and Switzerland (.ch) still redirect to the German site (.de) with special settings, so don't maintain local ASINs for them)
err_flag = set_message ('err_bad_asin_tld'); -- unsupported asin-tld value
end
local handler = options.handler;
if not is_set (err_flag) then
options.coins_list_t['ASIN'] = handler.prefix .. domain .. "/dp/" .. id; -- asin for coins
else
options.coins_list_t['ASIN'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix .. domain .. "/dp/",
id = id, encode = handler.encode, separator = handler.separator})
end
--[[--------------------------< I S M N >----------------------------------------------------------------------
Determines whether an ISMN string is valid. Similar to ISBN-13, ISMN is 13 digits beginning 979-0-... and uses the
same check digit calculations. See https://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf
section 2, pages 9–12.
ismn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx)
or an identifier registered at info-uri.info (info:)
]]
local function ismn (options)
local id = options.id;
local handler = options.handler;
local text;
local valid_ismn;
local id_copy;
id_copy = id; -- save a copy because this testing is destructive
id = id:gsub ('[%s-]', ''); -- remove hyphens and white space
if 13 ~= id:len() or id:match ("^9790%d*$" ) == nil then -- ISMN must be 13 digits and begin with 9790
valid_ismn = false;
else
valid_ismn=is_valid_isxn_13 (id); -- validate ISMN
end
-- text = internal_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- use this (or external version) when there is some place to link to
-- prefix = handler.prefix, id = id_copy, separator = handler.separator, encode = handler.encode})
text = table.concat ( -- because no place to link to yet
{
make_wikilink (label_link_make (handler), handler.label),
handler.separator,
id_copy
});
if false == valid_ismn then
options.coins_list_t['ISMN'] = nil; -- when error, unset so not included in COinS; not really necessary here because ismn not made part of COinS
set_message ('err_bad_ismn'); -- create an error message if the ISMN is invalid
end
return text;
end
--[[--------------------------< I S S N >----------------------------------------------------------------------
Validate and format an ISSN. This code fixes the case where an editor has included an ISSN in the citation but
has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked
like this:
|issn=0819 4327 gives: [https://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link
This code now prevents that by inserting a hyphen at the ISSN midpoint. It also validates the ISSN for length
and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check ISSN error message. The
ISSN is always displayed with a hyphen, even if the ISSN was given as a single group of 8 digits.
]]
local function issn (options)
local id = options.id;
local handler = options.handler;
local ignore_invalid = options.accept;
local issn_copy = id; -- save a copy of unadulterated ISSN; use this version for display if ISSN does not validate
local text;
local valid_issn;
id = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace
if 8 ~= id:len() or nil == id:match ("^%d*X?$" ) then -- validate the ISSN: 8 digits long, containing only 0-9 or X in the last position
valid_issn = false; -- wrong length or improper character
else
valid_issn = is_valid_isxn (id, 8); -- validate ISSN
end
if true == valid_issn then
id = string.sub (id, 1, 4 ) .. "-" .. string.sub (id, 5 ); -- if valid, display correctly formatted version
else
id = issn_copy; -- if not valid, show the invalid ISSN with error message
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})
if ignore_invalid then
set_message ('maint_issn_ignore');
else
if false == valid_issn then
options.coins_list_t['ISSN'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_issn', (options.hkey == 'EISSN') and 'e' or ''); -- create an error message if the ISSN is invalid
end
end
return text;
end
--[[--------------------------< J F M >-----------------------------------------------------------------------
A numerical identifier in the form nn.nnnn.nn
]]
local function jfm (options)
local id = options.id;
local handler = options.handler;
local id_num;
id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier
if is_set (id_num) then
set_message ('maint_jfm_format');
else -- plain number without JFM prefix
id_num = id; -- if here id does not have prefix
end
if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then
id = id_num; -- jfm matches pattern
else
set_message ('err_bad_jfm' ); -- set an error message
options.coins_list_t['JFM'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< J S T O R >--------------------------------------------------------------------
Format a JSTOR with some error checking
]]
local function jstor (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
if id:find ('[Jj][Ss][Tt][Oo][Rr]') or id:find ('^https?://') or id:find ('%s') then
set_message ('err_bad_jstor'); -- set an error message
options.coins_list_t['JSTOR'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
end
--[[--------------------------< L C C N >----------------------------------------------------------------------
Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.
https://oclc-research.github.io/infoURI-Frozen/info-uri.info/info:lccn/reg.html
length = 8 then all digits
length = 9 then lccn[1] is lowercase alpha
length = 10 then lccn[1] and lccn[2] are both lowercase alpha or both digits
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lowercase alpha or both digits
length = 12 then lccn[1] and lccn[2] are both lowercase alpha
]]
local function lccn (options)
local id = options.id; -- local copy of the LCCN
local lccn_id = id;
local handler = options.handler;
local err_flag; -- presume that LCCN is valid
id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes)
local len = id:len(); -- get the length of the LCCN
if 8 == len then
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits)
err_flag = set_message ('err_bad_lccn'); -- set an error message
end
elseif 9 == len then -- LCCN should be adddddddd
if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern?
err_flag = set_message ('err_bad_lccn'); -- set an error message
end
elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ...
if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
end
elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd
if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
elseif 12 == len then -- LCCN should be aadddddddddd
if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
else
err_flag = set_message ('err_bad_lccn'); -- wrong length, set an error message
end
if not is_set (err_flag) and nil ~= lccn_id:find ('%s') then
err_flag = set_message ('err_bad_lccn'); -- lccn contains a space, set an error message
end
if is_set (err_flag) then
options.coins_list_t['LCCN'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = lccn_id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< M E D R X I V >-----------------------------------------------------------------
Format medRxiv ID and do simple error checking. Similar to later bioRxiv IDs, medRxiv IDs are prefixed with a
yyyy.mm.dd. date and suffixed with an optional version identifier. Ealiest date accepted is 2020.01.01
The medRxiv ID is a date followed by an eight-digit number followed by an optional version indicator 'v' and one or more digits:
https://www.medrxiv.org/content/10.1101/2020.11.16.20232009v2 -> 10.1101/2020.11.16.20232009v2
]]
local function medrxiv (options)
local id = options.id;
local handler = options.handler;
local err_msg_flag = true; -- flag; assume that there will be an error
local patterns = {
'^%d%d%d%d%d%d%d%d$', -- simple 8-digit identifier; these should be relatively rare
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%dv%d+$', -- y.m.d. date + 8-digit identifier + version (2020-01-01 and later)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%d$', -- y.m.d. date + 8-digit identifier (2020-01-01 and later)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%dv%d+$', -- y.m.d. date + 8-digit identifier + version (2025-12-01 and later)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%d$', -- y.m.d. date + 8-digit identifier (2025-12-01 and later)
}
for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match
if id:match (pattern) then
local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier
if m then -- m is nil when id is the 8-digit form
if not is_valid_rxiv_date (y, m, d, 'b') then -- validate the encoded date; 'b' for medrxiv limit
break; -- date fail; break out early so we don't unset the error message
end
end
err_msg_flag = nil; -- we found a match so unset the error message
break; -- and done
end
end -- <err_msg_flag> remains set here when no match
if err_msg_flag then
options.coins_list_t['MEDRXIV'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_medrxiv'); -- and set the error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator,
encode = handler.encode, access = handler.access});
end
--[[--------------------------< M R >--------------------------------------------------------------------------
A seven digit number; if not seven digits, zero-fill leading digits to make seven digits.
]]
local function mr (options)
local id = options.id;
local handler = options.handler;
local id_num;
local id_len;
id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix
if is_set (id_num) then
set_message ('maint_mr_format'); -- add maint cat
else -- plain number without mr prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
id_len = id_num and id_num:len() or 0;
if (7 >= id_len) and (0 ~= id_len) then
id = string.rep ('0', 7-id_len) .. id_num; -- zero-fill leading digits
else
set_message ('err_bad_mr'); -- set an error message
options.coins_list_t['MR'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< O C L C >----------------------------------------------------------------------
Validate and format an OCLC ID. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}}
archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html
]]
local function oclc (options)
local id = options.id;
local handler = options.handler;
local number;
if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters)
number = id:match('ocm(%d+)'); -- get the number
elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters)
number = id:match('ocn(%d+)'); -- get the number
elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters)
number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number
elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field
number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number
if 9 < number:len() then
number = nil; -- constrain to 1 to 9 digits; change this when OCLC issues 10-digit numbers
end
elseif id:match('^%d+$') then -- no prefix
number = id; -- get the number
if tonumber (id) > handler.id_limit then
number = nil; -- unset when id value exceeds the limit
end
end
if number then -- proper format
id = number; -- exclude prefix, if any, from external link
else
set_message ('err_bad_oclc') -- add an error message if the id is malformed
options.coins_list_t['OCLC'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< O P E N L I B R A R Y >--------------------------------------------------------
Formats an OpenLibrary link, and checks for associated errors.
]]
local function openlibrary (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local ident, code = id:gsub('^OL', ''):match("^(%d+([AMW]))$"); -- strip optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W';
local err_flag;
local prefix = { -- these are appended to the handler.prefix according to code
['A']='authors/OL',
['M']='books/OL',
['W']='works/OL',
['X']='OL' -- not a code; spoof when 'code' in id is invalid
};
if not ident then
code = 'X'; -- no code or id completely invalid
ident = id; -- copy id to ident so that we display the flawed identifier
err_flag = set_message ('err_bad_ol');
end
if not is_set (err_flag) then
options.coins_list_t['OL'] = handler.prefix .. prefix[code] .. ident; -- experiment for ol coins
else
options.coins_list_t['OL'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix .. prefix[code],
id = ident, separator = handler.separator, encode = handler.encode,
access = access});
end
--[[--------------------------< O S T I >----------------------------------------------------------------------
Format OSTI and do simple error checking. OSTIs are sequential numbers beginning at 1 and counting up. This
code checks the OSTI to see that it contains only digits and is less than test_limit specified in the configuration;
the value in test_limit will need to be updated periodically as more OSTIs are issued.
NB. 1018 is the lowest OSTI number found in the wild (so far) and resolving OK on the OSTI site
]]
local function osti (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
if id:match("[^%d]") then -- if OSTI has anything but digits
set_message ('err_bad_osti'); -- set an error message
options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS
else -- OSTI is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1018 > id_num or handler.id_limit < id_num then -- if OSTI is outside test limit boundaries
set_message ('err_bad_osti'); -- set an error message
options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
end
--[[--------------------------< P M C >------------------------------------------------------------------------
Format a PMC, do simple error checking, and check for embargoed articles.
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not
be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the
PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation
has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed ()
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.
PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.
]]
local function pmc (options)
local id = options.id;
local embargo = options.Embargo; -- TODO: lowercase?
local handler = options.handler;
local err_flag;
local id_num;
local text;
id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with PMC prefix
if is_set (id_num) then
set_message ('maint_pmc_format');
else -- plain number without PMC prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if PMC is outside test limit boundaries
err_flag = set_message ('err_bad_pmc'); -- set an error message
else
id = tostring (id_num); -- make sure id is a string
end
else -- when id format incorrect
err_flag = set_message ('err_bad_pmc'); -- set an error message
end
if is_set (embargo) and is_set (is_embargoed (embargo)) then -- is PMC is still embargoed?
text = table.concat ( -- still embargoed so no external link
{
make_wikilink (label_link_make (handler), handler.label),
handler.separator,
id,
});
else
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- no embargo date or embargo has expired, ok to link to article
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access,
auto_link = not err_flag and 'pmc' or nil -- do not auto-link when PMC has error
});
end
if err_flag then
options.coins_list_t['PMC'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< P M I D >----------------------------------------------------------------------
Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable
test_limit will need to be updated periodically as more PMIDs are issued.
]]
local function pmid (options)
local id = options.id;
local handler = options.handler;
if id:match("[^%d]") then -- if PMID has anything but digits
set_message ('err_bad_pmid'); -- set an error message
options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS
else -- PMID is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if PMID is outside test limit boundaries
set_message ('err_bad_pmid'); -- set an error message
options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< R F C >------------------------------------------------------------------------
Format RFC and do simple error checking. RFCs are sequential numbers beginning at 1 and counting up. This
code checks the RFC to see that it contains only digits and is less than test_limit specified in the configuration;
the value in test_limit will need to be updated periodically as more RFCs are issued.
An index of all RFCs is here: https://tools.ietf.org/rfc/
]]
local function rfc (options)
local id = options.id;
local handler = options.handler;
if id:match("[^%d]") then -- if RFC has anything but digits
set_message ('err_bad_rfc'); -- set an error message
options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS
else -- RFC is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if RFC is outside test limit boundaries
set_message ('err_bad_rfc'); -- set an error message
options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});
end
--[[--------------------------< S 2 C I D >--------------------------------------------------------------------
Format an S2CID, do simple error checking
S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only
digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically
as more S2CIDs are issued.
]]
local function s2cid (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local id_num;
local text;
id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if handler.id_limit < id_num then -- if S2CID is outside test limit boundaries
set_message ('err_bad_s2cid'); -- set an error message
options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS
end
else -- when id format incorrect
set_message ('err_bad_s2cid'); -- set an error message
options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
return text;
end
--[[--------------------------< S B N >------------------------------------------------------------------------
9-digit form of ISBN-10; uses same check-digit validation when SBN is prefixed with an additional '0' to make 10 digits
sbn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx)
or an identifier registered at info-uri.info (info:)
]]
local function sbn (options)
local id = options.id;
local ignore_invalid = options.accept;
local handler = options.handler;
local function return_result (check, err_type) -- local function to handle the various returns
local SBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator});
if not ignore_invalid then -- if not ignoring SBN errors
if not check then
options.coins_list_t['SBN'] = nil; -- when error, unset so not included in COinS; not really necessary here because sbn not made part of COinS
set_message ('err_bad_sbn', {err_type}); -- display an error message
return SBN;
end
else
set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error (ToDo: Possibly switch to separate message for SBNs only)
end
return SBN;
end
if id:match ('[^%s-0-9X]') then
return return_result (false, cfg.err_msg_supl.char); -- fail if SBN contains anything but digits, hyphens, or the uppercase X
end
local ident = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace; they interfere with the rest of the tests
if 9 ~= ident:len() then
return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length
end
if ident:match ('^%d*X?$') == nil then
return return_result (false, cfg.err_msg_supl.form); -- fail if SBN has 'X' anywhere but last position
end
return return_result (is_valid_isxn ('0' .. ident, 10), cfg.err_msg_supl.check);
end
--[[--------------------------< S S R N >----------------------------------------------------------------------
Format an SSRN, do simple error checking
SSRNs are sequential numbers beginning at 100? and counting up. This code checks the SSRN to see that it is
only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need
to be updated periodically as more SSRNs are issued.
]]
local function ssrn (options)
local id = options.id;
local handler = options.handler;
local id_num;
local text;
id_num = id:match ('^%d+$'); -- id must be all digits
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if 100 > id_num or handler.id_limit < id_num then -- if SSRN is outside test limit boundaries
set_message ('err_bad_ssrn'); -- set an error message
options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS
end
else -- when id format incorrect
set_message ('err_bad_ssrn'); -- set an error message
options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = options.access});
return text;
end
--[[--------------------------< U S E N E T _ I D >------------------------------------------------------------
Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in
'<' and/or '>' angle brackets.
]]
local function usenet_id (options)
local id = options.id;
local handler = options.handler;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})
if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$') then -- doesn't have '@' or has one or first or last character is '< or '>'
set_message ('err_bad_usenet_id') -- add an error message if the message id is invalid
options.coins_list_t['USENETID'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< Z B L >-----------------------------------------------------------------------
A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional
format described here: http://emis.mi.sanu.ac.rs/ZMATH/zmath/en/help/search/
temporary format is apparently eight digits. Anything else is an error
]]
local function zbl (options)
local id = options.id;
local handler = options.handler;
if id:match('^%d%d%d%d%d%d%d%d$') then -- is this identifier using temporary format?
set_message ('maint_zbl'); -- yes, add maint cat
elseif not id:match('^%d?%d?%d?%d%.%d%d%d%d%d$') then -- not temporary, is it normal format?
set_message ('err_bad_zbl'); -- no, set an error message
options.coins_list_t['ZBL'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--============================<< I N T E R F A C E F U N C T I O N S >>==========================================
--[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for
any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to
the identifier list. Emits redundant error message if more than one alias exists in args
]]
local function extract_ids (args)
local id_list = {}; -- list of identifiers found in args
for k, v in pairs (cfg.id_handlers) do -- k is uppercase identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
v = select_one (args, v.parameters, 'err_redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present
if is_set (v) then id_list[k] = v; end -- if found in args, add identifier to our list
end
return id_list;
end
--[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >--------------------------------------
Fetches custom id access levels from arguments using configuration settings. Parameters which have a predefined access
level (e.g. arxiv) do not use this function as they are directly rendered as free without using an additional parameter.
returns a table of k/v pairs where k is same as the identifier's key in cfg.id_handlers and v is the assigned (valid) keyword
access-level values must match the case used in cfg.keywords_lists['id-access'] (lowercase unless there is some special reason for something else)
]]
local function extract_id_access_levels (args, id_list)
local id_accesses_list = {};
for k, v in pairs (cfg.id_handlers) do
local access_param = v.custom_access; -- name of identifier's access-level parameter
if is_set (access_param) then
local access_level = args[access_param]; -- get the assigned value if there is one
if is_set (access_level) then
if not in_array (access_level, cfg.keywords_lists['id-access']) then -- exact match required
set_message ('err_invalid_param_val', {access_param, access_level});
access_level = nil; -- invalid so unset
end
if not is_set (id_list[k]) then -- identifier access-level must have a matching identifier
set_message ('err_param_access_requires_param', {k:lower()}); -- parameter name is uppercase in cfg.id_handlers (k); lowercase for error message
end
id_accesses_list[k] = cfg.keywords_xlate[access_level]; -- get translated keyword
end
end
end
return id_accesses_list;
end
--[[--------------------------< B U I L D _ I D _ L I S T >----------------------------------------------------
render the identifiers into a sorted sequence table
<ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value
<options_t> is a table of various k/v option pairs provided in the call to new_build_id_list();
modified by this function and passed to all identifier rendering functions
<access_levels_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value (if valid)
returns a sequence table of sorted (by hkey - 'handler' key) rendered identifier strings
]]
local function build_id_list (ID_list_coins_t, options_t, access_levels_t)
local ID_list_t = {};
local accept;
local func_map = { --function map points to functions associated with hkey identifier
['ARXIV'] = arxiv,
['ASIN'] = asin,
['BIBCODE'] = bibcode,
['BIORXIV'] = biorxiv,
['CITESEERX'] = citeseerx,
['DOI'] = doi,
['EISSN'] = issn,
['HDL'] = hdl,
['ISBN'] = isbn,
['ISMN'] = ismn,
['ISSN'] = issn,
['JFM'] = jfm,
['JSTOR'] = jstor,
['LCCN'] = lccn,
['MEDRXIV'] = medrxiv,
['MR'] = mr,
['OCLC'] = oclc,
['OL'] = openlibrary,
['OSTI'] = osti,
['PMC'] = pmc,
['PMID'] = pmid,
['RFC'] = rfc,
['S2CID'] = s2cid,
['SBN'] = sbn,
['SSRN'] = ssrn,
['USENETID'] = usenet_id,
['ZBL'] = zbl,
}
for hkey, v in pairs (ID_list_coins_t) do
v, accept = has_accept_as_written (v); -- remove accept-as-written markup if present; accept is boolean true when markup removed; false else
-- every function gets the options table with value v and accept boolean
options_t.hkey = hkey; -- ~/Configuration handler key
options_t.id = v; -- add that identifier value to the options table
options_t.accept = accept; -- add the accept boolean flag
options_t.access = access_levels_t[hkey]; -- add the access level for those that have an |<identifier-access= parameter
options_t.handler = cfg.id_handlers[hkey];
options_t.coins_list_t = ID_list_coins_t; -- pointer to ID_list_coins_t; for |asin= and |ol=; also to keep erroneous values out of the citation's metadata
options_t.coins_list_t[hkey] = v; -- id value without accept-as-written markup for metadata
if options_t.handler.access and not in_array (options_t.handler.access, cfg.keywords_lists['id-access']) then
error (cfg.messages['unknown_ID_access'] .. options_t.handler.access); -- here when handler access key set to a value not listed in list of allowed id access keywords
end
if func_map[hkey] then
local id_text = func_map[hkey] (options_t); -- call the function to get identifier text and any error message
table.insert (ID_list_t, {hkey, id_text}); -- add identifier text to the output sequence table
else
error (cfg.messages['unknown_ID_key'] .. hkey); -- here when func_map doesn't have a function for hkey
end
end
local function comp (a, b) -- used by following table.sort()
return a[1]:lower() < b[1]:lower(); -- sort by hkey
end
table.sort (ID_list_t, comp); -- sequence table of tables sort
for k, v in ipairs (ID_list_t) do -- convert sequence table of tables to simple sequence table of strings
ID_list_t[k] = v[2]; -- v[2] is the identifier rendering from the call to the various functions in func_map{}
end
return ID_list_t;
end
--[[--------------------------< O P T I O N S _ C H E C K >----------------------------------------------------
check that certain option parameters have their associated identifier parameters with values
<ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value
<ID_support_t> is a sequence table of tables created in citation0() where each subtable has four elements:
[1] is the support parameter's assigned value; empty string if not set
[2] is a text string same as key in cfg.id_handlers
[3] is cfg.error_conditions key used to create error message
[4] is original ID support parameter name used to create error message
returns nothing; on error emits an appropriate error message
]]
local function options_check (ID_list_coins_t, ID_support_t)
for _, v in ipairs (ID_support_t) do
if is_set (v[1]) and not ID_list_coins_t[v[2]] then -- when support parameter has a value but matching identifier parameter is missing or empty
set_message (v[3], (v[4])); -- emit the appropriate error message
end
end
end
--[[--------------------------< I D E N T I F I E R _ L I S T S _ G E T >--------------------------------------
Creates two identifier lists: a k/v table of identifiers and their values to be used locally and for use in the
COinS metadata, and a sequence table of the rendered identifier strings that will be included in the rendered
citation.
]]
local function identifier_lists_get (args_t, options_t, ID_support_t)
local ID_list_coins_t = extract_ids (args_t); -- get a table of identifiers and their values for use locally and for use in COinS
options_check (ID_list_coins_t, ID_support_t); -- ID support parameters must have matching identifier parameters
local ID_access_levels_t = extract_id_access_levels (args_t, ID_list_coins_t); -- get a table of identifier access levels
local ID_list_t = build_id_list (ID_list_coins_t, options_t, ID_access_levels_t); -- get a sequence table of rendered identifier strings
return ID_list_t, ID_list_coins_t; -- return the tables
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
cfg = cfg_table_ptr;
has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from select Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
set_message = utilities_page_ptr.set_message;
select_one = utilities_page_ptr.select_one;
substitute = utilities_page_ptr.substitute;
make_wikilink = utilities_page_ptr.make_wikilink;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
auto_link_urls = auto_link_urls, -- table of identifier URLs to be used when auto-linking |title=
identifier_lists_get = identifier_lists_get, -- experiment to replace individual calls to build_id_list(), extract_ids, extract_id_access_levels
is_embargoed = is_embargoed;
set_selected_modules = set_selected_modules;
}
5bj1u7sbno5vyrz0hztvhaip3uwhy2w
9012
8260
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/Identifiers]]
8260
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local has_accept_as_written, is_set, in_array, set_message, select_one, -- functions in Module:Citation/CS1/Utilities
substitute, make_wikilink;
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< P A G E S C O P E V A R I A B L E S >--------------------------------------
declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here
]]
local auto_link_urls = {}; -- holds identifier URLs for those identifiers that can auto-link |title=
--============================<< H E L P E R F U N C T I O N S >>============================================
--[[--------------------------< W I K I D A T A _ A R T I C L E _ N A M E _ G E T >----------------------------
as an aid to internationalizing identifier-label wikilinks, gets identifier article names from Wikidata.
returns w:<lang code>:<article title> when <q> has an <article title> for <lang code>; nil else. 'w:<lang code>'
ensures that sister project (like wiktionary) will link to the <lang code>.wikipedia article.
for identifiers that do not have <q>, returns nil
for wikis that do not have mw.wikibase installed, returns nil
]]
local function wikidata_article_name_get (q)
if not is_set (q) or (q and not mw.wikibase) then -- when no q number or when a q number but mw.wikibase not installed on this wiki
return nil; -- abandon
end
local wd_article;
local this_wiki_code = cfg.this_wiki_code; -- Wikipedia subdomain; 'en' for en.wikipedia.org
wd_article = mw.wikibase.getSitelink (q, this_wiki_code .. 'wiki'); -- fetch article title from WD; nil when no title available at this wiki
if wd_article then
wd_article = table.concat ({'w:', this_wiki_code, ':', wd_article}); -- interwiki-style link without brackets if taken from WD; leading 'w:' required
end
return wd_article; -- article title from WD; nil else
end
--[[--------------------------< L A B E L _ L I N K _ M A K E >------------------------------------------------
common function to create a link for an identifier label from handler table or from Wikidata
returns the first available of:
1. redirect from local wiki's handler table (if enabled)
2. Wikidata sitelink to the local language wikipedia article (if there is a Wikidata entry for this identifier in the local language)
3. link to wikipedia article specified in the local wiki's handler table
]]
local function label_link_make (handler)
local wd_article;
if not (cfg.use_identifier_redirects and is_set (handler.redirect)) then -- redirect has priority so if enabled and available don't fetch from Wikidata because expensive
wd_article = wikidata_article_name_get (handler.q); -- if Wikidata has an article title for this wiki, get it;
end
return (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link;
end
--[[--------------------------< E X T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki-style external link
]]
local function external_link_id (options)
local url_string = options.id;
local ext_link;
if options.encode == true or options.encode == nil then
url_string = mw.uri.encode (url_string, 'PATH');
end
if options.auto_link and is_set (options.access) then
auto_link_urls[options.auto_link] = table.concat ({options.prefix, url_string, options.suffix});
end
ext_link = mw.ustring.format ('[%s%s%s %s]', options.prefix, url_string, options.suffix or "", mw.text.nowiki (options.id));
if is_set (options.access) then
ext_link = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[options.access].class, cfg.presentation[options.access].title, ext_link}); -- add the free-to-read / paywall lock
end
return table.concat ({
make_wikilink (label_link_make (options), options.label), -- redirect, Wikidata link, or locally specified link (in that order)
options.separator or ' ',
ext_link
});
end
--[[--------------------------< I N T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki-style internal link
TODO: Does not currently need to support options.access, options.encode, auto-linking and COinS (as in external_link_id),
but may be needed in the future for :m:Interwiki_map custom-prefixes like :arxiv:, :bibcode:, :DOI:, :hdl:, :ISSN:,
:JSTOR:, :Openlibrary:, :PMID:, :RFC:.
]]
local function internal_link_id (options)
local id = mw.ustring.gsub (options.id, '%d', cfg.date_names.local_digits); -- translate 'local' digits to Western 0-9
return table.concat (
{
make_wikilink (label_link_make (options), options.label), -- wiki-link the identifier label
options.separator or ' ', -- add the separator
make_wikilink (
table.concat (
{
options.prefix,
id, -- translated to Western digits
options.suffix or ''
}),
substitute (cfg.presentation['bdi'], {'', mw.text.nowiki (options.id)}) -- bdi tags to prevent Latin script identifiers from being reversed at RTL language wikis
); -- nowiki because MediaWiki still has magic links for ISBN and the like; TODO: is it really required?
});
end
--[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------
Determines if a PMC identifier's online version is embargoed. Compares the date in |pmc-embargo-date= against
today's date. If embargo date is in the future, returns the content of |pmc-embargo-date=; otherwise, returns
an empty string because the embargo has expired or because |pmc-embargo-date= was not set in this cite.
]]
local function is_embargoed (embargo)
if is_set (embargo) then
local lang = mw.getContentLanguage();
local good1, embargo_date, todays_date;
good1, embargo_date = pcall (lang.formatDate, lang, 'U', embargo);
todays_date = lang:formatDate ('U');
if good1 then -- if embargo date is a good date
if tonumber (embargo_date) >= tonumber (todays_date) then -- is embargo date is in the future?
return embargo; -- still embargoed
else
set_message ('maint_pmc_embargo'); -- embargo has expired; add main cat
return ''; -- unset because embargo has expired
end
end
end
return ''; -- |pmc-embargo-date= not set return empty string
end
--[=[-------------------------< I S _ V A L I D _ R X I V _ D A T E >------------------------------------------
for biorxiv, returns true if:
2019-12-11T00:00Z <= biorxiv_date < today + 2 days
for medrxiv, returns true if:
2020-01-01T00:00Z <= medrxiv_date < today + 2 days
The dated form of biorxiv identifier has a start date of 2019-12-11. The Unix timestamp for that date is {{#time:U|2019-12-11}} = 1576022400
The medrxiv identifier has a start date of 2020-01-01. The Unix timestamp for that date is {{#time:U|2020-01-01}} = 1577836800
<rxiv_date> is the date provided in those |biorxiv= parameter values that are dated and in |medrxiv= parameter values at time 00:00:00 UTC
<today> is the current date at time 00:00:00 UTC plus 48 hours
if today's date is 2023-01-01T00:00:00 then
adding 24 hours gives 2023-01-02T00:00:00 – one second more than today
adding 24 hours gives 2023-01-03T00:00:00 – one second more than tomorrow
inputs:
<y>, <m>, <d> – year, month, day parts of the date from the birxiv or medrxiv identifier
<select> 'b' for biorxiv, 'm' for medrxiv; defaults to 'b'
]=]
local function is_valid_rxiv_date (y, m, d, select)
if 0 == tonumber (m) and 12 < tonumber (m) then -- <m> must be a number 1–12
return false;
end
if 0 == tonumber (d) and 31 < tonumber (d) then -- <d> must be a number 1–31; TODO: account for month length and leap yer?
return false;
end
local rxiv_date = table.concat ({y, m, d}, '-'); -- make ymd date string
local good1, good2;
local rxiv_ts, tomorrow_ts; -- to hold Unix timestamps representing the dates
local lang_object = mw.getContentLanguage();
good1, rxiv_ts = pcall (lang_object.formatDate, lang_object, 'U', rxiv_date); -- convert rxiv_date value to Unix timestamp
good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then -- lang.formatDate() returns a timestamp in the local script which tonumber() may not understand
rxiv_ts = tonumber (rxiv_ts) or lang_object:parseFormattedNumber (rxiv_ts); -- convert to numbers for the comparison;
tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts);
else
return false; -- one or both failed to convert to Unix timestamp
end
local limit_ts = ((select and ('m' == select)) and 1577836800) or 1576022400; -- choose the appropriate limit timesatmp
return ((limit_ts <= rxiv_ts) and (rxiv_ts < tomorrow_ts)) -- limit_ts <= rxiv_date < tomorrow's date
end
--[[--------------------------< IS _ V A L I D _ I S X N >-----------------------------------------------------
ISBN-10 and ISSN validator code calculates checksum across all ISBN/ISSN digits including the check digit.
ISBN-13 is checked in isbn().
If the number is valid the result will be 0. Before calling this function, ISBN/ISSN must be checked for length
and stripped of dashes, spaces and other non-ISxN characters.
]]
local function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58
len = len + 1; -- adjust to be a loop counter
for i, v in ipairs (isxn_str) do -- loop through all of the bytes and calculate the checksum
if v == string.byte ("X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58)
temp = temp + 10 * (len - i); -- it represents 10 decimal
else
temp = temp + tonumber (string.char (v) )*(len-i);
end
end
return temp % 11 == 0; -- returns true if calculation result is zero
end
--[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >-----------------------------------------------
ISBN-13 and ISMN validator code calculates checksum across all 13 ISBN/ISMN digits including the check digit.
If the number is valid, the result will be 0. Before calling this function, ISBN-13/ISMN must be checked for length
and stripped of dashes, spaces and other non-ISxN-13 characters.
]]
local function is_valid_isxn_13 (isxn_str)
local temp=0;
isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39
for i, v in ipairs (isxn_str) do
temp = temp + (3 - 2*(i % 2)) * tonumber (string.char (v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit
end
return temp % 10 == 0; -- sum modulo 10 is zero when ISBN-13/ISMN is correct
end
--[[--------------------------< N O R M A L I Z E _ L C C N >--------------------------------------------------
LCCN normalization (https://www.loc.gov/marc/lccn-namespace.html#normalization)
1. Remove all blanks.
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.
3. If there is a hyphen in the string:
a. Remove it.
b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):
1. All these characters should be digits, and there should be six or less. (not done in this function)
2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.
Returns a normalized LCCN for lccn() to validate. There is no error checking (step 3.b.1) performed in this function.
]]
local function normalize_lccn (lccn)
lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace
if nil ~= string.find (lccn, '/') then
lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it
end
local prefix
local suffix
prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix
if nil ~= suffix then -- if there was a hyphen
suffix = string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6
lccn = prefix..suffix; -- reassemble the LCCN
end
return lccn;
end
--============================<< I D E N T I F I E R F U N C T I O N S >>====================================
--[[--------------------------< A R X I V >--------------------------------------------------------------------
See: https://arxiv.org/help/arxiv_identifier
format and error check arXiv identifier. There are three valid forms of the identifier:
the first form, valid only between date codes 9107 and 0703, is:
arXiv:<archive>.<class>/<date code><number><version>
where:
<archive> is a string of alpha characters - may be hyphenated; no other punctuation
<class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
first digit of YY for this form can only 9 and 0
<number> is a three-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)
the second form, valid from April 2007 through December 2014 is:
arXiv:<date code>.<number><version>
where:
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
<number> is a four-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces
the third form, valid from January 2015 is:
arXiv:<date code>.<number><version>
where:
<date code> and <version> are as defined for 0704-1412
<number> is a five-digit number
]]
local function arxiv (options)
local id = options.id;
local class = options.Class; -- TODO: lowercase?
local handler = options.handler;
local year, month;
local err_msg = false; -- assume no error message
local text; -- output text
if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9107-0703 format with or without version
year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month
((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok?
err_msg = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 with or without version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years)
((7 == year) and (4 > month)) then -- when year is 07, is month invalid (before April)?
err_msg = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format with or without version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$");
year = tonumber (year);
month = tonumber (month);
if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years)
err_msg = true; -- flag for error message
end
else
err_msg = true; -- not a recognized format; flag for error message
end
if err_msg then
options.coins_list_t['ARXIV'] = nil; -- when error, unset so not included in COinS
end
if err_msg then
set_message ('err_bad_arxiv');
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});
if is_set (class) then
if id:match ('^%d+') then
text = table.concat ({text, ' [[https://arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink
else
set_message ('err_class_ignored');
end
else -- class not set
if id:match ('^%d+') and options.CitationClass == 'arxiv' then -- new (post 2007) format; {{cite arxiv}} only
set_message ('maint_missing_class'); -- add maint cat
end
end
return text;
end
--[[--------------------------< B I B C O D E >--------------------------------------------------------------------
Validates (sort of) and formats a bibcode ID.
Format for bibcodes is specified here: https://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes
But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters
and first four digits must be a year. This function makes these tests:
length must be 19 characters
characters in position
1–4 must be digits and must represent a year in the range of 1000 – next year
5 must be a letter
6–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. )
9–18 must be letter, digit, or dot
19 must be a letter or dot
]]
local function bibcode (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local ignore_invalid = options.accept;
local err_type;
local year;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,
access = access});
if 19 ~= id:len() then
err_type = cfg.err_msg_supl.length;
else
year = id:match ("^(%d%d%d%d)[%a][%w&%.][%w&%.][%w&%.][%w.]+[%a%.]$");
if not year then -- if nil then no pattern match
err_type = cfg.err_msg_supl.value; -- so value error
else
local next_year = tonumber (os.date ('%Y')) + 1; -- get the current year as a number and add one for next year
year = tonumber (year); -- convert year portion of bibcode to a number
if (1000 > year) or (year > next_year) then
err_type = cfg.err_msg_supl.year; -- year out of bounds
end
if id:find('&%.') then
err_type = cfg.err_msg_supl.journal; -- journal abbreviation must not have '&.' (if it does it's missing a letter)
end
if id:match ('.........%.tmp%.') then -- temporary bibcodes when positions 10–14 are '.tmp.'
set_message ('maint_bibcode');
end
end
end
if is_set (err_type) and not ignore_invalid then -- if there was an error detected and accept-as-written markup not used
set_message ('err_bad_bibcode', {err_type});
options.coins_list_t['BIBCODE'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< B I O R X I V >-----------------------------------------------------------------
Format bioRxiv ID and do simple error checking. Before 2019-12-11, biorXiv IDs were 10.1101/ followed by exactly
6 digits. After 2019-12-11, biorXiv IDs retained the six-digit identifier but prefixed that with a yyyy.mm.dd.
date and suffixed with an optional version identifier.
From December 2025 biorxiv added a new 'doi' prefix: 10.64898:
10.64898/2025.12.10.693067
The bioRxiv ID is the string of characters:
https://doi.org/10.1101/078733 -> 10.1101/078733
or a date followed by a six-digit number followed by an optional version indicator 'v' and one or more digits:
https://www.biorxiv.org/content/10.1101/2019.12.11.123456v2 -> 10.1101/2019.12.11.123456v2
see https://www.biorxiv.org/about-biorxiv
]]
local function biorxiv (options)
local id = options.id;
local handler = options.handler;
local err_msg = true; -- flag; assume that there will be an error
local patterns = {
'^10%.1101/%d%d%d%d%d%d$', -- simple 6-digit identifier (before 2019-12-11)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (after 2019-12-11)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (after 2019-12-11)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%dv%d+$', -- y.m.d. date + 6-digit identifier + version (from December 2025)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d$', -- y.m.d. date + 6-digit identifier (from December 2025)
}
for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match
if id:match (pattern) then
local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier
if m then -- m is nil when id is the six-digit form
if not is_valid_rxiv_date (y, m, d, 'b') then -- validate the encoded date; 'b' for biorxiv limit
break; -- date fail; break out early so we don't unset the error message
end
end
err_msg = nil; -- we found a match so unset the error message
break; -- and done
end
end -- err_cat remains set here when no match
if err_msg then
options.coins_list_t['BIORXIV'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_biorxiv'); -- and set the error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator,
encode = handler.encode, access = handler.access});
end
--[[--------------------------< C I T E S E E R X >------------------------------------------------------------
CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org).
The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure
]]
local function citeseerx (options)
local id = options.id;
local handler = options.handler;
local matched;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,
access = handler.access});
matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$");
if not matched then
set_message ('err_bad_citeseerx' );
options.coins_list_t['CITESEERX'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< D O I >------------------------------------------------------------------------
Formats a DOI and checks for DOI errors.
DOI names contain two parts: prefix and suffix separated by a forward slash.
Prefix: directory indicator '10.' followed by a registrant code
Suffix: character string of any length chosen by the registrant
This function checks a DOI name for: prefix/suffix. If the DOI name contains spaces or endashes, or, if it ends
with a period or a comma, this function will emit a bad_doi error message.
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in DOI names.
https://www.doi.org/doi_handbook/2_Numbering.html -- 2.2 Syntax of a DOI name
https://www.doi.org/doi_handbook/2_Numbering.html#2.2.2 -- 2.2.2 DOI prefix
]]
local function doi (options)
local id = options.id;
local inactive = options.DoiBroken
local access = options.access;
local ignore_invalid = options.accept;
local handler = options.handler;
local err_flag; -- error flag for errors that may not be ignored
local ignorable_err_flag; -- error flag for ((ignorable)) errors
local function is_extended_free (registrant, suffix) -- local function to check those few registrants that are mixed; identifiable by the doi suffix <incipit>
suffix = suffix:lower(); -- ascii [a-z] same as [A-Z] in doi names; see §3.4.4 Case Insensitivity of the Doi Name
if cfg.extended_registrants_t[registrant] then -- if this registrant has known free-to-read extentions
for _, incipit in ipairs (cfg.extended_registrants_t[registrant]) do -- loop through the registrant's incipits
if mw.ustring.find (suffix, '^' .. incipit:lower()) then -- ascii [a-z] same as [A-Z] in doi names
return true; -- if found done
end
end
end
end
local text;
if is_set (inactive) then
local inactive_year = inactive:match("%d%d%d%d"); -- try to get the year portion from the inactive date
local inactive_month, good;
if is_set (inactive_year) then
if 4 < inactive:len() then -- inactive date has more than just a year (could be anything)
local lang_obj = mw.getContentLanguage(); -- get a language object for this wiki
good, inactive_month = pcall (lang_obj.formatDate, lang_obj, 'F', inactive); -- try to get the month name from the inactive date
if not good then
inactive_month = nil; -- something went wrong so make sure this is unset
end
end
end -- otherwise, |doi-broken-date= has something but it isn't a date
if is_set (inactive_year) and is_set (inactive_month) then
set_message ('maint_doi_inactive_dated', {inactive_year, inactive_month, ' '});
elseif is_set (inactive_year) then
set_message ('maint_doi_inactive_dated', {inactive_year, '', ''});
else
set_message ('maint_doi_inactive');
end
inactive = substitute (cfg.messages['inactive'], inactive );
end
local registrant, suffix = mw.ustring.match (id, '^10%.([^/]+)/([^%s–]+)$'); -- registrant and suffix set when DOI has the proper basic form; both nil else
if suffix then
if suffix:match ('[%.,]$') then -- |doi= has basic form but suffix has trailing dot or comma
ignorable_err_flag = true; -- set the flag so that we can emit an error message if not ignored
end
else -- here when |doi= does not have proper basic form
err_flag = true; -- set the non-ignorable error flag
ignore_invalid = false; -- unset because this error may not be ignored
end
local registrant_err_patterns = { -- these patterns are for code ranges that are not supported
'^[^1-3]%d%d%d%d%.%d+$', -- 5 digits with subcode (reject 0xxxx, 40000+); accepts: 10000–39999
'^[^1-8]%d%d%d%d$', -- 5 digits without subcode (reject 0xxxx, 90000+); accepts: 10000–89999
'^[^1-9]%d%d%d%.%d+$', -- 4 digits with subcode (reject 0xxx); accepts: 1000–9999
'^[^1-9]%d%d%d$', -- 4 digits without subcode (reject 0xxx); accepts: 1000–9999
'^%d%d%d%d%d%d+', -- 6 or more digits
'^%d%d?%d?$', -- less than 4 digits without subcode (3 digits with subcode is legitimate)
'^%d%d?%.[%d%.]+', -- 1 or 2 digits with subcode
'^5555$', -- test registrant will never resolve
'[^%d%.]', -- any character that isn't a digit or a dot
}
if not err_flag then -- when DOI has proper form; <err_flag> is true when |doi= is malformed
if not ignore_invalid then -- when we're not ignoring errors
if registrant then -- when DOI has proper form
for i, pattern in ipairs (registrant_err_patterns) do -- spin through error patterns
if registrant:match (pattern) then -- to validate registrant codes
ignorable_err_flag = true; -- when found, mark this DOI as bad
break; -- and done
end
end
end
else -- here when ignoring invalid |doi= values
ignorable_err_flag = false; -- unset so we don't emit an error message for ignorable errors
set_message ('maint_doi_ignore'); -- add maint message when doi is properly formatted
end
end
if err_flag or ignorable_err_flag then
set_message ('err_bad_doi'); -- invalid |doi= value; emit an error message
options.coins_list_t['DOI'] = nil; -- when in error, unset so |doi= value not included in COinS
else -- here when doi has no errors or has been wrapped in accept-as-written markup
suffix = mw.ustring.match (id, '^10%.[^/]+/(.+)'); -- refetch suffix because doi may have been wrapped in accept-as-written markup
if not access and (cfg.known_free_doi_registrants_t[registrant] or is_extended_free (registrant, suffix)) then -- |doi-access=free not set and <registrant> is known to be free
set_message ('maint_doi_unflagged_free'); -- set a maint cat
end
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access,
auto_link = not (err_flag or is_set (inactive) or ignore_invalid) and 'doi' or nil -- do not auto-link when |doi-broken-date= has a value or when there is a DOI error or (to play it safe, after all, auto-linking is not essential) when invalid DOIs are ignored
}) .. (inactive or '');
return text;
end
--[[--------------------------< H D L >------------------------------------------------------------------------
Formats an HDL with minor error checking.
HDL names contain two parts: prefix and suffix separated by a forward slash.
Prefix: character string using any character in the UCS-2 character set except '/'
Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant
This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends
with a period or a comma, this function will emit a bad_hdl error message.
HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and
terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in HDLs.
Query string parameters are named here: https://www.handle.net/proxy_servlet.html. query strings are not displayed
but since '?' is an allowed character in an HDL, '?' followed by one of the query parameters is the only way we
have to detect the query string so that it isn't URL-encoded with the rest of the identifier.
]]
local function hdl (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local query_params_t = { -- list of known query parameters from https://www.handle.net/proxy_servlet.html
'noredirect',
'ignore_aliases',
'auth',
'cert',
'index',
'type',
'urlappend',
'locatt',
'action',
}
local handle, suffix, param = id:match ('(.-)(%?(%a+).+)$'); -- look for query string
local found;
if handle then -- when there are query strings, this is the handle identifier portion
for _, q in ipairs (query_params_t) do -- spin through the list of query parameters
if param:match ('^' .. q) then -- if the query string begins with one of the parameters
found = true; -- announce a find
break; -- and stop looking
end
end
end
if found then
id = handle; -- found so replace id with the handle portion; this will be URL-encoded, suffix will not
else
suffix = ''; -- make sure suffix is empty string for concatenation else
end
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, suffix = suffix, separator = handler.separator, encode = handler.encode, access = access})
if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- HDL must contain a forward slash, must not contain spaces, endashes, and must not end with period or comma
set_message ('err_bad_hdl' );
options.coins_list_t['HDL'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< I S B N >----------------------------------------------------------------------
Determines whether an ISBN string is valid
]]
local function isbn (options_t)
local isbn_str = options_t.id;
local ignore_invalid = options_t.accept;
local handler = options_t.handler;
local year = options_t.Year; -- when set, valid anchor_year; may have a disambiguator which must be removed
local function return_result (check, err_type) -- local function to handle the various returns
local ISBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = isbn_str, separator = handler.separator});
if ignore_invalid then -- if ignoring ISBN errors
set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error
else -- here when not ignoring
if not check then -- and there is an error
options_t.coins_list_t['ISBN'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_isbn', err_type); -- set an error message
return ISBN; -- return id text
end
end
return ISBN; -- return id text
end
if year and not ignore_invalid then --
year = year:match ('%d%d%d%d?'); -- strip disambiguator if present
if year and (1965 > tonumber(year)) then -- <year> will be nil here when |year=n.d. or |year=nd
set_message ('err_invalid_isbn_date'); -- set an error message
return internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = isbn_str, separator = handler.separator});
end
end
if nil ~= isbn_str:match ('[^%s-0-9X]') then
return return_result (false, cfg.err_msg_supl.char); -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
end
local id = isbn_str:gsub ('[%s-]', ''); -- remove hyphens and whitespace
local len = id:len();
if len ~= 10 and len ~= 13 then
return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length
end
if len == 10 then
if id:match ('^%d*X?$') == nil then -- fail if isbn_str has 'X' anywhere but last position
return return_result (false, cfg.err_msg_supl.form);
end
if not is_valid_isxn (id, 10) then -- test isbn-10 for numerical validity
return return_result (false, cfg.err_msg_supl.check); -- fail if isbn-10 is not numerically valid
end
if id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not valid isbn group ids but are used by amazon as numeric identifiers (asin)
return return_result (false, cfg.err_msg_supl.group); -- fail if isbn-10 begins with 630/1
end
return return_result (true, cfg.err_msg_supl.check); -- pass if isbn-10 is numerically valid
else
if id:match ('^%d+$') == nil then
return return_result (false, cfg.err_msg_supl.char); -- fail if ISBN-13 is not all digits
end
if id:match ('^97[89]%d*$') == nil then
return return_result (false, cfg.err_msg_supl.prefix); -- fail when ISBN-13 does not begin with 978 or 979
end
if id:match ('^9790') then
return return_result (false, cfg.err_msg_supl.group); -- group identifier '0' is reserved to ISMN
end
return return_result (is_valid_isxn_13 (id), cfg.err_msg_supl.check);
end
end
--[[--------------------------< A S I N >----------------------------------------------------------------------
Formats a link to Amazon. Do simple error checking: ASIN must be mix of 10 numeric or uppercase alpha
characters. If a mix, first character must be uppercase alpha; if all numeric, ASINs must be 10-digit
ISBN. If 10-digit ISBN, add a maintenance category so a bot or AWB script can replace |asin= with |isbn=.
Error message if not 10 characters, if not ISBN-10, if mixed and first character is a digit.
|asin=630....... and |asin=631....... are (apparently) not a legitimate ISBN though it checksums as one; these
do not cause this function to emit the maint_asin message
This function is positioned here because it calls isbn()
]]
local function asin (options)
local id = options.id;
local domain = options.ASINTLD;
local err_flag = nil; -- must be explicitly initialized
if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then
err_flag = set_message ('err_bad_asin'); -- ASIN is not a mix of 10 uppercase alpha and numeric characters
else
if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X)
if is_valid_isxn (id, 10) then -- see if ASIN value is or validates as ISBN-10
if not id:find ('^63[01]') then -- 630xxxxxxx and 631xxxxxxx are (apparently) not a valid isbn prefixes but are used by amazon as a numeric identifier
err_flag = set_message ('err_bad_asin'); -- ASIN has ISBN-10 form but begins with something other than 630/1 so probably an isbn
end
elseif not is_set (err_flag) then
err_flag = set_message ('err_bad_asin'); -- ASIN is not ISBN-10
end
elseif not id:match("^%u[%d%u]+$") then
err_flag = set_message ('err_bad_asin'); -- asin doesn't begin with uppercase alpha
end
end
if (not is_set (domain)) or in_array (domain, {'us'}) then -- default: United States
domain = "com";
elseif in_array (domain, {'jp', 'uk', 'za'}) then -- Japan, United Kingdom, South Africa
domain = "co." .. domain;
elseif in_array (domain, {'z.cn'}) then -- China
domain = "cn";
elseif in_array (domain, {'au', 'be', 'br', 'mx', 'sg', 'tr'}) then -- Australia, Belgium, Brazil, Mexico, Singapore, Turkey
domain = "com." .. domain;
elseif not in_array (domain, {'ae', 'ca', 'cn', 'de', 'eg', 'es', 'fr', 'ie', 'in', 'it', 'nl', 'pl', 'sa', 'se', 'co.jp', 'co.uk', 'com', 'com.au', 'com.br', 'com.mx', 'com.sg', 'com.tr'}) then -- Arabic Emirates, Canada, China, Germany, Egypt, Spain, France, Ireland, Indonesia, Italy, Netherlands, Poland, Saudi Arabia, Sweden (as of 2021-03 Austria (.at), Liechtenstein (.li) and Switzerland (.ch) still redirect to the German site (.de) with special settings, so don't maintain local ASINs for them)
err_flag = set_message ('err_bad_asin_tld'); -- unsupported asin-tld value
end
local handler = options.handler;
if not is_set (err_flag) then
options.coins_list_t['ASIN'] = handler.prefix .. domain .. "/dp/" .. id; -- asin for coins
else
options.coins_list_t['ASIN'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix .. domain .. "/dp/",
id = id, encode = handler.encode, separator = handler.separator})
end
--[[--------------------------< I S M N >----------------------------------------------------------------------
Determines whether an ISMN string is valid. Similar to ISBN-13, ISMN is 13 digits beginning 979-0-... and uses the
same check digit calculations. See https://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf
section 2, pages 9–12.
ismn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx)
or an identifier registered at info-uri.info (info:)
]]
local function ismn (options)
local id = options.id;
local handler = options.handler;
local text;
local valid_ismn;
local id_copy;
id_copy = id; -- save a copy because this testing is destructive
id = id:gsub ('[%s-]', ''); -- remove hyphens and white space
if 13 ~= id:len() or id:match ("^9790%d*$" ) == nil then -- ISMN must be 13 digits and begin with 9790
valid_ismn = false;
else
valid_ismn=is_valid_isxn_13 (id); -- validate ISMN
end
-- text = internal_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- use this (or external version) when there is some place to link to
-- prefix = handler.prefix, id = id_copy, separator = handler.separator, encode = handler.encode})
text = table.concat ( -- because no place to link to yet
{
make_wikilink (label_link_make (handler), handler.label),
handler.separator,
id_copy
});
if false == valid_ismn then
options.coins_list_t['ISMN'] = nil; -- when error, unset so not included in COinS; not really necessary here because ismn not made part of COinS
set_message ('err_bad_ismn'); -- create an error message if the ISMN is invalid
end
return text;
end
--[[--------------------------< I S S N >----------------------------------------------------------------------
Validate and format an ISSN. This code fixes the case where an editor has included an ISSN in the citation but
has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked
like this:
|issn=0819 4327 gives: [https://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link
This code now prevents that by inserting a hyphen at the ISSN midpoint. It also validates the ISSN for length
and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check ISSN error message. The
ISSN is always displayed with a hyphen, even if the ISSN was given as a single group of 8 digits.
]]
local function issn (options)
local id = options.id;
local handler = options.handler;
local ignore_invalid = options.accept;
local issn_copy = id; -- save a copy of unadulterated ISSN; use this version for display if ISSN does not validate
local text;
local valid_issn;
id = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace
if 8 ~= id:len() or nil == id:match ("^%d*X?$" ) then -- validate the ISSN: 8 digits long, containing only 0-9 or X in the last position
valid_issn = false; -- wrong length or improper character
else
valid_issn = is_valid_isxn (id, 8); -- validate ISSN
end
if true == valid_issn then
id = string.sub (id, 1, 4 ) .. "-" .. string.sub (id, 5 ); -- if valid, display correctly formatted version
else
id = issn_copy; -- if not valid, show the invalid ISSN with error message
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})
if ignore_invalid then
set_message ('maint_issn_ignore');
else
if false == valid_issn then
options.coins_list_t['ISSN'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_issn', (options.hkey == 'EISSN') and 'e' or ''); -- create an error message if the ISSN is invalid
end
end
return text;
end
--[[--------------------------< J F M >-----------------------------------------------------------------------
A numerical identifier in the form nn.nnnn.nn
]]
local function jfm (options)
local id = options.id;
local handler = options.handler;
local id_num;
id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier
if is_set (id_num) then
set_message ('maint_jfm_format');
else -- plain number without JFM prefix
id_num = id; -- if here id does not have prefix
end
if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then
id = id_num; -- jfm matches pattern
else
set_message ('err_bad_jfm' ); -- set an error message
options.coins_list_t['JFM'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< J S T O R >--------------------------------------------------------------------
Format a JSTOR with some error checking
]]
local function jstor (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
if id:find ('[Jj][Ss][Tt][Oo][Rr]') or id:find ('^https?://') or id:find ('%s') then
set_message ('err_bad_jstor'); -- set an error message
options.coins_list_t['JSTOR'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
end
--[[--------------------------< L C C N >----------------------------------------------------------------------
Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.
https://oclc-research.github.io/infoURI-Frozen/info-uri.info/info:lccn/reg.html
length = 8 then all digits
length = 9 then lccn[1] is lowercase alpha
length = 10 then lccn[1] and lccn[2] are both lowercase alpha or both digits
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lowercase alpha or both digits
length = 12 then lccn[1] and lccn[2] are both lowercase alpha
]]
local function lccn (options)
local id = options.id; -- local copy of the LCCN
local lccn_id = id;
local handler = options.handler;
local err_flag; -- presume that LCCN is valid
id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes)
local len = id:len(); -- get the length of the LCCN
if 8 == len then
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits)
err_flag = set_message ('err_bad_lccn'); -- set an error message
end
elseif 9 == len then -- LCCN should be adddddddd
if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern?
err_flag = set_message ('err_bad_lccn'); -- set an error message
end
elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ...
if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
end
elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd
if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
elseif 12 == len then -- LCCN should be aadddddddddd
if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern
err_flag = set_message ('err_bad_lccn'); -- no match, set an error message
end
else
err_flag = set_message ('err_bad_lccn'); -- wrong length, set an error message
end
if not is_set (err_flag) and nil ~= lccn_id:find ('%s') then
err_flag = set_message ('err_bad_lccn'); -- lccn contains a space, set an error message
end
if is_set (err_flag) then
options.coins_list_t['LCCN'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = lccn_id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< M E D R X I V >-----------------------------------------------------------------
Format medRxiv ID and do simple error checking. Similar to later bioRxiv IDs, medRxiv IDs are prefixed with a
yyyy.mm.dd. date and suffixed with an optional version identifier. Ealiest date accepted is 2020.01.01
The medRxiv ID is a date followed by an eight-digit number followed by an optional version indicator 'v' and one or more digits:
https://www.medrxiv.org/content/10.1101/2020.11.16.20232009v2 -> 10.1101/2020.11.16.20232009v2
]]
local function medrxiv (options)
local id = options.id;
local handler = options.handler;
local err_msg_flag = true; -- flag; assume that there will be an error
local patterns = {
'^%d%d%d%d%d%d%d%d$', -- simple 8-digit identifier; these should be relatively rare
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%dv%d+$', -- y.m.d. date + 8-digit identifier + version (2020-01-01 and later)
'^10%.1101/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%d$', -- y.m.d. date + 8-digit identifier (2020-01-01 and later)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%dv%d+$', -- y.m.d. date + 8-digit identifier + version (2025-12-01 and later)
'^10%.64898/(20%d%d)%.(%d%d)%.(%d%d)%.%d%d%d%d%d%d%d%d$', -- y.m.d. date + 8-digit identifier (2025-12-01 and later)
}
for _, pattern in ipairs (patterns) do -- spin through the patterns looking for a match
if id:match (pattern) then
local y, m, d = id:match (pattern); -- found a match, attempt to get year, month and date from the identifier
if m then -- m is nil when id is the 8-digit form
if not is_valid_rxiv_date (y, m, d, 'b') then -- validate the encoded date; 'b' for medrxiv limit
break; -- date fail; break out early so we don't unset the error message
end
end
err_msg_flag = nil; -- we found a match so unset the error message
break; -- and done
end
end -- <err_msg_flag> remains set here when no match
if err_msg_flag then
options.coins_list_t['MEDRXIV'] = nil; -- when error, unset so not included in COinS
set_message ('err_bad_medrxiv'); -- and set the error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator,
encode = handler.encode, access = handler.access});
end
--[[--------------------------< M R >--------------------------------------------------------------------------
A seven digit number; if not seven digits, zero-fill leading digits to make seven digits.
]]
local function mr (options)
local id = options.id;
local handler = options.handler;
local id_num;
local id_len;
id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix
if is_set (id_num) then
set_message ('maint_mr_format'); -- add maint cat
else -- plain number without mr prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
id_len = id_num and id_num:len() or 0;
if (7 >= id_len) and (0 ~= id_len) then
id = string.rep ('0', 7-id_len) .. id_num; -- zero-fill leading digits
else
set_message ('err_bad_mr'); -- set an error message
options.coins_list_t['MR'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< O C L C >----------------------------------------------------------------------
Validate and format an OCLC ID. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}}
archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html
]]
local function oclc (options)
local id = options.id;
local handler = options.handler;
local number;
if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters)
number = id:match('ocm(%d+)'); -- get the number
elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters)
number = id:match('ocn(%d+)'); -- get the number
elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters)
number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number
elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field
number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number
if 9 < number:len() then
number = nil; -- constrain to 1 to 9 digits; change this when OCLC issues 10-digit numbers
end
elseif id:match('^%d+$') then -- no prefix
number = id; -- get the number
if tonumber (id) > handler.id_limit then
number = nil; -- unset when id value exceeds the limit
end
end
if number then -- proper format
id = number; -- exclude prefix, if any, from external link
else
set_message ('err_bad_oclc') -- add an error message if the id is malformed
options.coins_list_t['OCLC'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< O P E N L I B R A R Y >--------------------------------------------------------
Formats an OpenLibrary link, and checks for associated errors.
]]
local function openlibrary (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local ident, code = id:gsub('^OL', ''):match("^(%d+([AMW]))$"); -- strip optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W';
local err_flag;
local prefix = { -- these are appended to the handler.prefix according to code
['A']='authors/OL',
['M']='books/OL',
['W']='works/OL',
['X']='OL' -- not a code; spoof when 'code' in id is invalid
};
if not ident then
code = 'X'; -- no code or id completely invalid
ident = id; -- copy id to ident so that we display the flawed identifier
err_flag = set_message ('err_bad_ol');
end
if not is_set (err_flag) then
options.coins_list_t['OL'] = handler.prefix .. prefix[code] .. ident; -- experiment for ol coins
else
options.coins_list_t['OL'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix .. prefix[code],
id = ident, separator = handler.separator, encode = handler.encode,
access = access});
end
--[[--------------------------< O S T I >----------------------------------------------------------------------
Format OSTI and do simple error checking. OSTIs are sequential numbers beginning at 1 and counting up. This
code checks the OSTI to see that it contains only digits and is less than test_limit specified in the configuration;
the value in test_limit will need to be updated periodically as more OSTIs are issued.
NB. 1018 is the lowest OSTI number found in the wild (so far) and resolving OK on the OSTI site
]]
local function osti (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
if id:match("[^%d]") then -- if OSTI has anything but digits
set_message ('err_bad_osti'); -- set an error message
options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS
else -- OSTI is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1018 > id_num or handler.id_limit < id_num then -- if OSTI is outside test limit boundaries
set_message ('err_bad_osti'); -- set an error message
options.coins_list_t['OSTI'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
end
--[[--------------------------< P M C >------------------------------------------------------------------------
Format a PMC, do simple error checking, and check for embargoed articles.
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not
be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the
PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation
has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed ()
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.
PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.
]]
local function pmc (options)
local id = options.id;
local embargo = options.Embargo; -- TODO: lowercase?
local handler = options.handler;
local err_flag;
local id_num;
local text;
id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with PMC prefix
if is_set (id_num) then
set_message ('maint_pmc_format');
else -- plain number without PMC prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if PMC is outside test limit boundaries
err_flag = set_message ('err_bad_pmc'); -- set an error message
else
id = tostring (id_num); -- make sure id is a string
end
else -- when id format incorrect
err_flag = set_message ('err_bad_pmc'); -- set an error message
end
if is_set (embargo) and is_set (is_embargoed (embargo)) then -- is PMC is still embargoed?
text = table.concat ( -- still embargoed so no external link
{
make_wikilink (label_link_make (handler), handler.label),
handler.separator,
id,
});
else
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect, -- no embargo date or embargo has expired, ok to link to article
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access,
auto_link = not err_flag and 'pmc' or nil -- do not auto-link when PMC has error
});
end
if err_flag then
options.coins_list_t['PMC'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< P M I D >----------------------------------------------------------------------
Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable
test_limit will need to be updated periodically as more PMIDs are issued.
]]
local function pmid (options)
local id = options.id;
local handler = options.handler;
if id:match("[^%d]") then -- if PMID has anything but digits
set_message ('err_bad_pmid'); -- set an error message
options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS
else -- PMID is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if PMID is outside test limit boundaries
set_message ('err_bad_pmid'); -- set an error message
options.coins_list_t['PMID'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--[[--------------------------< R F C >------------------------------------------------------------------------
Format RFC and do simple error checking. RFCs are sequential numbers beginning at 1 and counting up. This
code checks the RFC to see that it contains only digits and is less than test_limit specified in the configuration;
the value in test_limit will need to be updated periodically as more RFCs are issued.
An index of all RFCs is here: https://tools.ietf.org/rfc/
]]
local function rfc (options)
local id = options.id;
local handler = options.handler;
if id:match("[^%d]") then -- if RFC has anything but digits
set_message ('err_bad_rfc'); -- set an error message
options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS
else -- RFC is only digits
local id_num = tonumber (id); -- convert id to a number for range testing
if 1 > id_num or handler.id_limit < id_num then -- if RFC is outside test limit boundaries
set_message ('err_bad_rfc'); -- set an error message
options.coins_list_t['RFC'] = nil; -- when error, unset so not included in COinS
end
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});
end
--[[--------------------------< S 2 C I D >--------------------------------------------------------------------
Format an S2CID, do simple error checking
S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only
digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically
as more S2CIDs are issued.
]]
local function s2cid (options)
local id = options.id;
local access = options.access;
local handler = options.handler;
local id_num;
local text;
id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if handler.id_limit < id_num then -- if S2CID is outside test limit boundaries
set_message ('err_bad_s2cid'); -- set an error message
options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS
end
else -- when id format incorrect
set_message ('err_bad_s2cid'); -- set an error message
options.coins_list_t['S2CID'] = nil; -- when error, unset so not included in COinS
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});
return text;
end
--[[--------------------------< S B N >------------------------------------------------------------------------
9-digit form of ISBN-10; uses same check-digit validation when SBN is prefixed with an additional '0' to make 10 digits
sbn value not made part of COinS metadata because we don't have a url or isn't a COinS-defined identifier (rft.xxx)
or an identifier registered at info-uri.info (info:)
]]
local function sbn (options)
local id = options.id;
local ignore_invalid = options.accept;
local handler = options.handler;
local function return_result (check, err_type) -- local function to handle the various returns
local SBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator});
if not ignore_invalid then -- if not ignoring SBN errors
if not check then
options.coins_list_t['SBN'] = nil; -- when error, unset so not included in COinS; not really necessary here because sbn not made part of COinS
set_message ('err_bad_sbn', {err_type}); -- display an error message
return SBN;
end
else
set_message ('maint_isbn_ignore'); -- add a maint category even when there is no error (ToDo: Possibly switch to separate message for SBNs only)
end
return SBN;
end
if id:match ('[^%s-0-9X]') then
return return_result (false, cfg.err_msg_supl.char); -- fail if SBN contains anything but digits, hyphens, or the uppercase X
end
local ident = id:gsub ('[%s-]', ''); -- remove hyphens and whitespace; they interfere with the rest of the tests
if 9 ~= ident:len() then
return return_result (false, cfg.err_msg_supl.length); -- fail if incorrect length
end
if ident:match ('^%d*X?$') == nil then
return return_result (false, cfg.err_msg_supl.form); -- fail if SBN has 'X' anywhere but last position
end
return return_result (is_valid_isxn ('0' .. ident, 10), cfg.err_msg_supl.check);
end
--[[--------------------------< S S R N >----------------------------------------------------------------------
Format an SSRN, do simple error checking
SSRNs are sequential numbers beginning at 100? and counting up. This code checks the SSRN to see that it is
only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need
to be updated periodically as more SSRNs are issued.
]]
local function ssrn (options)
local id = options.id;
local handler = options.handler;
local id_num;
local text;
id_num = id:match ('^%d+$'); -- id must be all digits
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if 100 > id_num or handler.id_limit < id_num then -- if SSRN is outside test limit boundaries
set_message ('err_bad_ssrn'); -- set an error message
options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS
end
else -- when id format incorrect
set_message ('err_bad_ssrn'); -- set an error message
options.coins_list_t['SSRN'] = nil; -- when error, unset so not included in COinS
end
text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = options.access});
return text;
end
--[[--------------------------< U S E N E T _ I D >------------------------------------------------------------
Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in
'<' and/or '>' angle brackets.
]]
local function usenet_id (options)
local id = options.id;
local handler = options.handler;
local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})
if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$') then -- doesn't have '@' or has one or first or last character is '< or '>'
set_message ('err_bad_usenet_id') -- add an error message if the message id is invalid
options.coins_list_t['USENETID'] = nil; -- when error, unset so not included in COinS
end
return text;
end
--[[--------------------------< Z B L >-----------------------------------------------------------------------
A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional
format described here: http://emis.mi.sanu.ac.rs/ZMATH/zmath/en/help/search/
temporary format is apparently eight digits. Anything else is an error
]]
local function zbl (options)
local id = options.id;
local handler = options.handler;
if id:match('^%d%d%d%d%d%d%d%d$') then -- is this identifier using temporary format?
set_message ('maint_zbl'); -- yes, add maint cat
elseif not id:match('^%d?%d?%d?%d%.%d%d%d%d%d$') then -- not temporary, is it normal format?
set_message ('err_bad_zbl'); -- no, set an error message
options.coins_list_t['ZBL'] = nil; -- when error, unset so not included in COinS
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});
end
--============================<< I N T E R F A C E F U N C T I O N S >>==========================================
--[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for
any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to
the identifier list. Emits redundant error message if more than one alias exists in args
]]
local function extract_ids (args)
local id_list = {}; -- list of identifiers found in args
for k, v in pairs (cfg.id_handlers) do -- k is uppercase identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
v = select_one (args, v.parameters, 'err_redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present
if is_set (v) then id_list[k] = v; end -- if found in args, add identifier to our list
end
return id_list;
end
--[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >--------------------------------------
Fetches custom id access levels from arguments using configuration settings. Parameters which have a predefined access
level (e.g. arxiv) do not use this function as they are directly rendered as free without using an additional parameter.
returns a table of k/v pairs where k is same as the identifier's key in cfg.id_handlers and v is the assigned (valid) keyword
access-level values must match the case used in cfg.keywords_lists['id-access'] (lowercase unless there is some special reason for something else)
]]
local function extract_id_access_levels (args, id_list)
local id_accesses_list = {};
for k, v in pairs (cfg.id_handlers) do
local access_param = v.custom_access; -- name of identifier's access-level parameter
if is_set (access_param) then
local access_level = args[access_param]; -- get the assigned value if there is one
if is_set (access_level) then
if not in_array (access_level, cfg.keywords_lists['id-access']) then -- exact match required
set_message ('err_invalid_param_val', {access_param, access_level});
access_level = nil; -- invalid so unset
end
if not is_set (id_list[k]) then -- identifier access-level must have a matching identifier
set_message ('err_param_access_requires_param', {k:lower()}); -- parameter name is uppercase in cfg.id_handlers (k); lowercase for error message
end
id_accesses_list[k] = cfg.keywords_xlate[access_level]; -- get translated keyword
end
end
end
return id_accesses_list;
end
--[[--------------------------< B U I L D _ I D _ L I S T >----------------------------------------------------
render the identifiers into a sorted sequence table
<ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value
<options_t> is a table of various k/v option pairs provided in the call to new_build_id_list();
modified by this function and passed to all identifier rendering functions
<access_levels_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value (if valid)
returns a sequence table of sorted (by hkey - 'handler' key) rendered identifier strings
]]
local function build_id_list (ID_list_coins_t, options_t, access_levels_t)
local ID_list_t = {};
local accept;
local func_map = { --function map points to functions associated with hkey identifier
['ARXIV'] = arxiv,
['ASIN'] = asin,
['BIBCODE'] = bibcode,
['BIORXIV'] = biorxiv,
['CITESEERX'] = citeseerx,
['DOI'] = doi,
['EISSN'] = issn,
['HDL'] = hdl,
['ISBN'] = isbn,
['ISMN'] = ismn,
['ISSN'] = issn,
['JFM'] = jfm,
['JSTOR'] = jstor,
['LCCN'] = lccn,
['MEDRXIV'] = medrxiv,
['MR'] = mr,
['OCLC'] = oclc,
['OL'] = openlibrary,
['OSTI'] = osti,
['PMC'] = pmc,
['PMID'] = pmid,
['RFC'] = rfc,
['S2CID'] = s2cid,
['SBN'] = sbn,
['SSRN'] = ssrn,
['USENETID'] = usenet_id,
['ZBL'] = zbl,
}
for hkey, v in pairs (ID_list_coins_t) do
v, accept = has_accept_as_written (v); -- remove accept-as-written markup if present; accept is boolean true when markup removed; false else
-- every function gets the options table with value v and accept boolean
options_t.hkey = hkey; -- ~/Configuration handler key
options_t.id = v; -- add that identifier value to the options table
options_t.accept = accept; -- add the accept boolean flag
options_t.access = access_levels_t[hkey]; -- add the access level for those that have an |<identifier-access= parameter
options_t.handler = cfg.id_handlers[hkey];
options_t.coins_list_t = ID_list_coins_t; -- pointer to ID_list_coins_t; for |asin= and |ol=; also to keep erroneous values out of the citation's metadata
options_t.coins_list_t[hkey] = v; -- id value without accept-as-written markup for metadata
if options_t.handler.access and not in_array (options_t.handler.access, cfg.keywords_lists['id-access']) then
error (cfg.messages['unknown_ID_access'] .. options_t.handler.access); -- here when handler access key set to a value not listed in list of allowed id access keywords
end
if func_map[hkey] then
local id_text = func_map[hkey] (options_t); -- call the function to get identifier text and any error message
table.insert (ID_list_t, {hkey, id_text}); -- add identifier text to the output sequence table
else
error (cfg.messages['unknown_ID_key'] .. hkey); -- here when func_map doesn't have a function for hkey
end
end
local function comp (a, b) -- used by following table.sort()
return a[1]:lower() < b[1]:lower(); -- sort by hkey
end
table.sort (ID_list_t, comp); -- sequence table of tables sort
for k, v in ipairs (ID_list_t) do -- convert sequence table of tables to simple sequence table of strings
ID_list_t[k] = v[2]; -- v[2] is the identifier rendering from the call to the various functions in func_map{}
end
return ID_list_t;
end
--[[--------------------------< O P T I O N S _ C H E C K >----------------------------------------------------
check that certain option parameters have their associated identifier parameters with values
<ID_list_coins_t> is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value
<ID_support_t> is a sequence table of tables created in citation0() where each subtable has four elements:
[1] is the support parameter's assigned value; empty string if not set
[2] is a text string same as key in cfg.id_handlers
[3] is cfg.error_conditions key used to create error message
[4] is original ID support parameter name used to create error message
returns nothing; on error emits an appropriate error message
]]
local function options_check (ID_list_coins_t, ID_support_t)
for _, v in ipairs (ID_support_t) do
if is_set (v[1]) and not ID_list_coins_t[v[2]] then -- when support parameter has a value but matching identifier parameter is missing or empty
set_message (v[3], (v[4])); -- emit the appropriate error message
end
end
end
--[[--------------------------< I D E N T I F I E R _ L I S T S _ G E T >--------------------------------------
Creates two identifier lists: a k/v table of identifiers and their values to be used locally and for use in the
COinS metadata, and a sequence table of the rendered identifier strings that will be included in the rendered
citation.
]]
local function identifier_lists_get (args_t, options_t, ID_support_t)
local ID_list_coins_t = extract_ids (args_t); -- get a table of identifiers and their values for use locally and for use in COinS
options_check (ID_list_coins_t, ID_support_t); -- ID support parameters must have matching identifier parameters
local ID_access_levels_t = extract_id_access_levels (args_t, ID_list_coins_t); -- get a table of identifier access levels
local ID_list_t = build_id_list (ID_list_coins_t, options_t, ID_access_levels_t); -- get a sequence table of rendered identifier strings
return ID_list_t, ID_list_coins_t; -- return the tables
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
cfg = cfg_table_ptr;
has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from select Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
set_message = utilities_page_ptr.set_message;
select_one = utilities_page_ptr.select_one;
substitute = utilities_page_ptr.substitute;
make_wikilink = utilities_page_ptr.make_wikilink;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
auto_link_urls = auto_link_urls, -- table of identifier URLs to be used when auto-linking |title=
identifier_lists_get = identifier_lists_get, -- experiment to replace individual calls to build_id_list(), extract_ids, extract_id_access_levels
is_embargoed = is_embargoed;
set_selected_modules = set_selected_modules;
}
5bj1u7sbno5vyrz0hztvhaip3uwhy2w
Module:Citation/CS1/COinS
828
930
9013
2026-08-08T13:56:43Z
en>Trappist the monk
0
synch from sandbox;
9013
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local has_accept_as_written, is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< M A K E _ C O I N S _ T I T L E >----------------------------------------------
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings
of %27%27...
]]
local function make_coins_title (title, script)
title = has_accept_as_written (title);
if is_set (title) then
title = strip_apostrophe_markup (title); -- strip any apostrophe markup
else
title = ''; -- if not set, make sure title is an empty string
end
if is_set (script) then
script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string)
script = strip_apostrophe_markup (script); -- strip any apostrophe markup
else
script = ''; -- if not set, make sure script is an empty string
end
if is_set (title) and is_set (script) then
script = ' ' .. script; -- add a space before we concatenate
end
return title .. script; -- return the concatenation
end
--[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------
Returns a string where all of Lua's magic characters have been escaped. This is important because functions like
string.gsub() treat their pattern and replace strings as patterns, not literal strings.
]]
local function escape_lua_magic_chars (argument)
argument = argument:gsub("%%", "%%%%"); -- replace % with %%
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters
return argument;
end
--[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.
]]
local function get_coins_pages (pages)
local pattern;
if not is_set (pages) then return pages; end -- if no page numbers then we're done
while true do
pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url "
if nil == pattern then break; end -- no more URLs
pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters
pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible
end
pages = pages:gsub("[%[%]]", ""); -- remove the brackets
pages = pages:gsub("–", "-" ); -- replace endashes with hyphens
pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (– etc.) with hyphens; do we need to replace numerical entities like   and the like?
pages = pages:gsub ('%b<>', ''); -- remove html-like tags; spans are added to <Pages> by utilities.hyphen_to_dash() which should not appear in COinS metadata
return pages;
end
--[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------
There are three options for math markup rendering that depend on the editor's math preference settings. These
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are
PNG images
TeX source
MathML with SVG or PNG fallback
All three are heavy with HTML and CSS which doesn't belong in the metadata.
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings
of the last editor to save the page.
This function gets the rendered form of an equation according to the editor's preference before the page is saved. It
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial
value. To replace multipe equations it is necessary to call this function from within a loop.
]=]
local function coins_replace_math_stripmarker (value)
local stripmarker = cfg.stripmarkers['math'];
local rendering = value:match (stripmarker); -- is there a math stripmarker
if not rendering then -- when value doesn't have a math stripmarker, abandon this test
return false, value;
end
rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error)
if rendering:match ('alt="[^"]+"') then -- if PNG math option
rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text
elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$
rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text
elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option
rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text
else
return false, value; -- had math stripmarker but not one of the three defined forms
end
return true, value:gsub (stripmarker, rendering, 1);
end
--[[--------------------------< C O I N S _ C L E A N U P >----------------------------------------------------
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities.
2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content
when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible
characters table?
]]
local function coins_cleanup (value)
local replaced = true; -- default state to get the do loop running
while replaced do -- loop until all math stripmarkers replaced
replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation
end
value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message
value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content
value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">'(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s
value = value:gsub (' ', ' '); -- replace entity with plain space
value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space
if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script
value = value:gsub ('‍', ''); -- remove ‍ entities
value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen
end
value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space
return value;
end
--[[--------------------------< C O I N S >--------------------------------------------------------------------
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.
]]
local function COinS(data, class)
if 'table' ~= type(data) or nil == next(data) then
return '';
end
for k, v in pairs (data) do -- spin through all of the metadata parameter values
if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)
data[k] = coins_cleanup (v);
end
end
local ctx_ver = "Z39.88-2004";
-- treat table strictly as an array with only set values.
local OCinSoutput = setmetatable( {}, {
__newindex = function(self, key, value)
if is_set(value) then
rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( remove_wiki_link( value ) ) } );
end
end
});
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn', 'journal', 'news', 'magazine'}) or
(in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or
('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) then -- set genre according to the type of citation template we are rendering
OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite medrxiv, cite ssrn
elseif 'conference' == class then
OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set)
elseif 'web' == class then
OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set)
else
OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles
end
OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only
OCinSoutput["rft.atitle"] = data.Title; -- 'periodical' article titles
-- these used only for periodicals
OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall
OCinSoutput["rft.quarter"] = data.Quarter; -- single digits 1->first quarter, etc.
OCinSoutput["rft.chron"] = data.Chron; -- free-form date components
OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books
OCinSoutput["rft.issue"] = data.Issue;
OCinSoutput['rft.artnum'] = data.ArticleNumber; -- {{cite journal}} only
OCinSoutput["rft.pages"] = data.Pages; -- also used in book metadata
elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier
if 'report' == class or 'techreport' == class then -- cite report and cite techreport
OCinSoutput["rft.genre"] = "report";
elseif 'conference' == class then -- cite conference when Periodical not set
OCinSoutput["rft.genre"] = "conference";
OCinSoutput["rft.atitle"] = data.Chapter; -- conference paper as chapter in proceedings (book)
elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then
if is_set (data.Chapter) then
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.atitle"] = data.Chapter; -- book chapter, encyclopedia article, interview in a book, or map title
else
if 'map' == class or 'interview' == class then
OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview
else
OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia
end
end
else -- {'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}
OCinSoutput["rft.genre"] = "unknown";
end
OCinSoutput["rft.btitle"] = data.Title; -- book only
OCinSoutput["rft.place"] = data.PublicationPlace; -- book only
OCinSoutput["rft.series"] = data.Series; -- book only
OCinSoutput["rft.pages"] = data.Pages; -- book, journal
OCinSoutput["rft.edition"] = data.Edition; -- book only
OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation
else -- cite thesis
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier
OCinSoutput["rft.title"] = data.Title; -- dissertation (also patent but that is not yet supported)
OCinSoutput["rft.degree"] = data.Degree; -- dissertation only
OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation
end
-- NB. Not currently supported are "info:ofi/fmt:kev:mtx:patent", "info:ofi/fmt:kev:mtx:dc", "info:ofi/fmt:kev:mtx:sch_svc", "info:ofi/fmt:kev:mtx:ctx"
-- and now common parameters (as much as possible)
OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation
for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all?
if k == 'ISBN' then v = v:gsub( "[^-0-9X]", "" ); end
local id = cfg.id_handlers[k].COinS;
if string.sub( id or "", 1, 4 ) == 'info' then -- for ids that are in the info:registry
OCinSoutput["rft_id"] = table.concat{ id, "/", v };
elseif string.sub (id or "", 1, 3 ) == 'rft' then -- for isbn, issn, eissn, etc. that have defined COinS keywords
OCinSoutput[ id ] = v;
elseif 'url' == id then -- for urls that are assembled in ~/Identifiers; |asin= and |ol=
OCinSoutput["rft_id"] = table.concat ({data.ID_list[k], "#id-name=", cfg.id_handlers[k].label});
elseif id then -- when cfg.id_handlers[k].COinS is not nil so urls created here
OCinSoutput["rft_id"] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or '', "#id-name=", cfg.id_handlers[k].label }; -- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers)
end
end
local last, first;
for k, v in ipairs( data.Authors ) do
last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki stripmarkers, non-printing or invisible characters
if k == 1 then -- for the first author name only
if is_set(last) and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name
OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation
OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name
end
else -- for all other authors
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation
end
-- TODO: At present we do not report "et al.". Add anything special if this condition applies?
end
end
OCinSoutput.rft_id = data.URL;
OCinSoutput.rfr_id = table.concat{ "info:sid/", string.match (mw.site.server, "[^/]*$" ), ":", data.RawPage };
-- TODO: Add optional extra info:
-- rfr_dat=#REVISION<version> (referrer private data)
-- ctx_id=<data.RawPage>#<ref> (identifier for the context object)
-- ctx_tim=<ts> (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd)
-- ctx_enc=info:ofi/enc:UTF-8 (character encoding)
OCinSoutput = setmetatable( OCinSoutput, nil );
-- sort with version string always first, and combine.
-- table.sort( OCinSoutput );
table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004"
return table.concat(OCinSoutput, "&");
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
cfg = cfg_table_ptr;
has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from selected Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
remove_wiki_link = utilities_page_ptr.remove_wiki_link;
strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
make_coins_title = make_coins_title,
get_coins_pages = get_coins_pages,
COinS = COinS,
set_selected_modules = set_selected_modules,
}
eu68irewi9gjrldmcpvk6z9cf3rs6jt
9014
8261
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/COinS]]
8261
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local has_accept_as_written, is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< M A K E _ C O I N S _ T I T L E >----------------------------------------------
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings
of %27%27...
]]
local function make_coins_title (title, script)
title = has_accept_as_written (title);
if is_set (title) then
title = strip_apostrophe_markup (title); -- strip any apostrophe markup
else
title = ''; -- if not set, make sure title is an empty string
end
if is_set (script) then
script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string)
script = strip_apostrophe_markup (script); -- strip any apostrophe markup
else
script = ''; -- if not set, make sure script is an empty string
end
if is_set (title) and is_set (script) then
script = ' ' .. script; -- add a space before we concatenate
end
return title .. script; -- return the concatenation
end
--[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------
Returns a string where all of Lua's magic characters have been escaped. This is important because functions like
string.gsub() treat their pattern and replace strings as patterns, not literal strings.
]]
local function escape_lua_magic_chars (argument)
argument = argument:gsub("%%", "%%%%"); -- replace % with %%
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters
return argument;
end
--[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.
]]
local function get_coins_pages (pages)
local pattern;
if not is_set (pages) then return pages; end -- if no page numbers then we're done
while true do
pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url "
if nil == pattern then break; end -- no more URLs
pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters
pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible
end
pages = pages:gsub("[%[%]]", ""); -- remove the brackets
pages = pages:gsub("–", "-" ); -- replace endashes with hyphens
pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (– etc.) with hyphens; do we need to replace numerical entities like   and the like?
pages = pages:gsub ('%b<>', ''); -- remove html-like tags; spans are added to <Pages> by utilities.hyphen_to_dash() which should not appear in COinS metadata
return pages;
end
--[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------
There are three options for math markup rendering that depend on the editor's math preference settings. These
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are
PNG images
TeX source
MathML with SVG or PNG fallback
All three are heavy with HTML and CSS which doesn't belong in the metadata.
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings
of the last editor to save the page.
This function gets the rendered form of an equation according to the editor's preference before the page is saved. It
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial
value. To replace multipe equations it is necessary to call this function from within a loop.
]=]
local function coins_replace_math_stripmarker (value)
local stripmarker = cfg.stripmarkers['math'];
local rendering = value:match (stripmarker); -- is there a math stripmarker
if not rendering then -- when value doesn't have a math stripmarker, abandon this test
return false, value;
end
rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error)
if rendering:match ('alt="[^"]+"') then -- if PNG math option
rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text
elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$
rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text
elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option
rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text
else
return false, value; -- had math stripmarker but not one of the three defined forms
end
return true, value:gsub (stripmarker, rendering, 1);
end
--[[--------------------------< C O I N S _ C L E A N U P >----------------------------------------------------
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities.
2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content
when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible
characters table?
]]
local function coins_cleanup (value)
local replaced = true; -- default state to get the do loop running
while replaced do -- loop until all math stripmarkers replaced
replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation
end
value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message
value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content
value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">'(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s
value = value:gsub (' ', ' '); -- replace entity with plain space
value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space
if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script
value = value:gsub ('‍', ''); -- remove ‍ entities
value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen
end
value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space
return value;
end
--[[--------------------------< C O I N S >--------------------------------------------------------------------
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.
]]
local function COinS(data, class)
if 'table' ~= type(data) or nil == next(data) then
return '';
end
for k, v in pairs (data) do -- spin through all of the metadata parameter values
if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)
data[k] = coins_cleanup (v);
end
end
local ctx_ver = "Z39.88-2004";
-- treat table strictly as an array with only set values.
local OCinSoutput = setmetatable( {}, {
__newindex = function(self, key, value)
if is_set(value) then
rawset( self, #self+1, table.concat{ key, '=', mw.uri.encode( remove_wiki_link( value ) ) } );
end
end
});
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn', 'journal', 'news', 'magazine'}) or
(in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or
('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'medrxiv', 'ssrn'}) then -- set genre according to the type of citation template we are rendering
OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite medrxiv, cite ssrn
elseif 'conference' == class then
OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set)
elseif 'web' == class then
OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set)
else
OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles
end
OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only
OCinSoutput["rft.atitle"] = data.Title; -- 'periodical' article titles
-- these used only for periodicals
OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall
OCinSoutput["rft.quarter"] = data.Quarter; -- single digits 1->first quarter, etc.
OCinSoutput["rft.chron"] = data.Chron; -- free-form date components
OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books
OCinSoutput["rft.issue"] = data.Issue;
OCinSoutput['rft.artnum'] = data.ArticleNumber; -- {{cite journal}} only
OCinSoutput["rft.pages"] = data.Pages; -- also used in book metadata
elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier
if 'report' == class or 'techreport' == class then -- cite report and cite techreport
OCinSoutput["rft.genre"] = "report";
elseif 'conference' == class then -- cite conference when Periodical not set
OCinSoutput["rft.genre"] = "conference";
OCinSoutput["rft.atitle"] = data.Chapter; -- conference paper as chapter in proceedings (book)
elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then
if is_set (data.Chapter) then
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.atitle"] = data.Chapter; -- book chapter, encyclopedia article, interview in a book, or map title
else
if 'map' == class or 'interview' == class then
OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview
else
OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia
end
end
else -- {'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}
OCinSoutput["rft.genre"] = "unknown";
end
OCinSoutput["rft.btitle"] = data.Title; -- book only
OCinSoutput["rft.place"] = data.PublicationPlace; -- book only
OCinSoutput["rft.series"] = data.Series; -- book only
OCinSoutput["rft.pages"] = data.Pages; -- book, journal
OCinSoutput["rft.edition"] = data.Edition; -- book only
OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation
else -- cite thesis
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier
OCinSoutput["rft.title"] = data.Title; -- dissertation (also patent but that is not yet supported)
OCinSoutput["rft.degree"] = data.Degree; -- dissertation only
OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation
end
-- NB. Not currently supported are "info:ofi/fmt:kev:mtx:patent", "info:ofi/fmt:kev:mtx:dc", "info:ofi/fmt:kev:mtx:sch_svc", "info:ofi/fmt:kev:mtx:ctx"
-- and now common parameters (as much as possible)
OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation
for k, v in pairs( data.ID_list ) do -- what to do about these? For now assume that they are common to all?
if k == 'ISBN' then v = v:gsub( "[^-0-9X]", "" ); end
local id = cfg.id_handlers[k].COinS;
if string.sub( id or "", 1, 4 ) == 'info' then -- for ids that are in the info:registry
OCinSoutput["rft_id"] = table.concat{ id, "/", v };
elseif string.sub (id or "", 1, 3 ) == 'rft' then -- for isbn, issn, eissn, etc. that have defined COinS keywords
OCinSoutput[ id ] = v;
elseif 'url' == id then -- for urls that are assembled in ~/Identifiers; |asin= and |ol=
OCinSoutput["rft_id"] = table.concat ({data.ID_list[k], "#id-name=", cfg.id_handlers[k].label});
elseif id then -- when cfg.id_handlers[k].COinS is not nil so urls created here
OCinSoutput["rft_id"] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or '', "#id-name=", cfg.id_handlers[k].label }; -- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers)
end
end
local last, first;
for k, v in ipairs( data.Authors ) do
last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki stripmarkers, non-printing or invisible characters
if k == 1 then -- for the first author name only
if is_set(last) and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name
OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation
OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name
end
else -- for all other authors
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat{ last, ", ", first }; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation
end
-- TODO: At present we do not report "et al.". Add anything special if this condition applies?
end
end
OCinSoutput.rft_id = data.URL;
OCinSoutput.rfr_id = table.concat{ "info:sid/", string.match (mw.site.server, "[^/]*$" ), ":", data.RawPage };
-- TODO: Add optional extra info:
-- rfr_dat=#REVISION<version> (referrer private data)
-- ctx_id=<data.RawPage>#<ref> (identifier for the context object)
-- ctx_tim=<ts> (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd)
-- ctx_enc=info:ofi/enc:UTF-8 (character encoding)
OCinSoutput = setmetatable( OCinSoutput, nil );
-- sort with version string always first, and combine.
-- table.sort( OCinSoutput );
table.insert( OCinSoutput, 1, "ctx_ver=" .. ctx_ver ); -- such as "Z39.88-2004"
return table.concat(OCinSoutput, "&");
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
cfg = cfg_table_ptr;
has_accept_as_written = utilities_page_ptr.has_accept_as_written; -- import functions from selected Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
remove_wiki_link = utilities_page_ptr.remove_wiki_link;
strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
make_coins_title = make_coins_title,
get_coins_pages = get_coins_pages,
COinS = COinS,
set_selected_modules = set_selected_modules,
}
eu68irewi9gjrldmcpvk6z9cf3rs6jt
Module:Citation/CS1/styles.css
828
931
9015
2026-01-17T19:25:08Z
en>Trappist the monk
0
synch from sandbox;
9015
sanitized-css
text/css
/* Protection icon
the following line controls the page-protection icon in the upper right corner
it must remain within this comment
{{sandbox other||{{pp-template}}}}
*/
/* Overrides
Some wikis do not override user agent default styles for HTML <cite> and <q>,
unlike en.wp. On en.wp, keep these the same as [[MediaWiki:Common.css]].
The word-wrap and :target styles were moved here from Common.css.
On en.wp, keep these the same as [[Template:Citation/styles.css]].
*/
cite.citation {
font-style: inherit; /* Remove italics for <cite> */
/* Break long urls, etc., rather than overflowing box */
word-wrap: break-word;
}
.citation q {
quotes: '"' '"' "'" "'"; /* Straight quote marks for <q> */
}
/* Highlight linked elements (such as clicked references) in blue */
.citation:target {
/* ignore the linter - all browsers of interest implement this */
background-color: rgba(0, 127, 255, 0.133);
}
/* ID and URL access
Both core and Common.css have selector .mw-parser-output a[href$=".pdf"].external
for PDF pages. All TemplateStyles pages are hoisted to .mw-parser-output. We need
to have specificity equal to a[href$=".pdf"].external for locks to override PDF icon.
That's essentially 2 classes and 1 element.
the .id-lock-... selectors are for use by non-citation templates like
{{Catalog lookup link}}
bg-size `contain` in Minerva and Timeless is too large, so we set a size for them
and then exclude them later
*/
.id-lock-free.id-lock-free a {
background: url(//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg)
right 0.1em center/9px no-repeat;
}
.id-lock-limited.id-lock-limited a,
.id-lock-registration.id-lock-registration a {
background: url(//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg)
right 0.1em center/9px no-repeat;
}
.id-lock-subscription.id-lock-subscription a {
background: url(//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg)
right 0.1em center/9px no-repeat;
}
/* Wikisource
Wikisource icon when |chapter= or |title= is wikilinked to Wikisource
as in cite wikisource
*/
.cs1-ws-icon a {
background: url(//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg)
right 0.1em center/12px no-repeat;
}
body:not(.skin-timeless):not(.skin-minerva) .id-lock-free a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-limited a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-registration a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-subscription a,
body:not(.skin-timeless):not(.skin-minerva) .cs1-ws-icon a {
background-size: contain;
/* Common.css has a padding set for PDF URLs. bg-contain expands to the
* size of the padding which makes the icons very large. we "reset" the
* padding here. 1em picked out of a hat based on console having a similar
* rule from elsewhere
*/
padding: 0 1em 0 0;
}
/* Errors and maintenance */
.cs1-code {
/* <code>...</code> style override: mediawiki's css definition is specified here:
https://git.wikimedia.org/blob/mediawiki%2Fcore.git/
69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199
*/
color: inherit;
background: inherit;
border: none;
padding: inherit;
}
.cs1-hidden-error {
display: none;
color: var(--color-error, #bf3c2c);
}
.cs1-visible-error {
color: var(--color-error, #bf3c2c);
}
.cs1-maint {
display: none;
color: #085;
margin-left: 0.3em;
}
/* kerning */
.cs1-kern-left {
padding-left: 0.2em;
}
.cs1-kern-right {
padding-right: 0.2em;
}
/* selflinks – avoid bold font style when cs1|2 template links to the current page */
.citation .mw-selflink {
font-weight: inherit;
}
@media screen {
/* Small text size
Set small text size in one place. 0.95 (here) * 0.9 (from references list) is
~0.85, which is the lower bound for size for accessibility. Old styling for this
was just 0.85. We could write the rule so that when this template is inside
references/reflist, only then does it multiply by 0.95; else multiply by 0.85 */
.cs1-format {
font-size: 95%;
}
html.skin-theme-clientpref-night .cs1-maint {
color: #18911f;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cs1-maint {
color: #18911f;
}
}
2wrho6o1q12cvwhaslan5n9g140q3wl
9016
8262
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Citation/CS1/styles.css]]
8262
sanitized-css
text/css
/* Protection icon
the following line controls the page-protection icon in the upper right corner
it must remain within this comment
{{sandbox other||{{pp-template}}}}
*/
/* Overrides
Some wikis do not override user agent default styles for HTML <cite> and <q>,
unlike en.wp. On en.wp, keep these the same as [[MediaWiki:Common.css]].
The word-wrap and :target styles were moved here from Common.css.
On en.wp, keep these the same as [[Template:Citation/styles.css]].
*/
cite.citation {
font-style: inherit; /* Remove italics for <cite> */
/* Break long urls, etc., rather than overflowing box */
word-wrap: break-word;
}
.citation q {
quotes: '"' '"' "'" "'"; /* Straight quote marks for <q> */
}
/* Highlight linked elements (such as clicked references) in blue */
.citation:target {
/* ignore the linter - all browsers of interest implement this */
background-color: rgba(0, 127, 255, 0.133);
}
/* ID and URL access
Both core and Common.css have selector .mw-parser-output a[href$=".pdf"].external
for PDF pages. All TemplateStyles pages are hoisted to .mw-parser-output. We need
to have specificity equal to a[href$=".pdf"].external for locks to override PDF icon.
That's essentially 2 classes and 1 element.
the .id-lock-... selectors are for use by non-citation templates like
{{Catalog lookup link}}
bg-size `contain` in Minerva and Timeless is too large, so we set a size for them
and then exclude them later
*/
.id-lock-free.id-lock-free a {
background: url(//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg)
right 0.1em center/9px no-repeat;
}
.id-lock-limited.id-lock-limited a,
.id-lock-registration.id-lock-registration a {
background: url(//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg)
right 0.1em center/9px no-repeat;
}
.id-lock-subscription.id-lock-subscription a {
background: url(//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg)
right 0.1em center/9px no-repeat;
}
/* Wikisource
Wikisource icon when |chapter= or |title= is wikilinked to Wikisource
as in cite wikisource
*/
.cs1-ws-icon a {
background: url(//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg)
right 0.1em center/12px no-repeat;
}
body:not(.skin-timeless):not(.skin-minerva) .id-lock-free a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-limited a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-registration a,
body:not(.skin-timeless):not(.skin-minerva) .id-lock-subscription a,
body:not(.skin-timeless):not(.skin-minerva) .cs1-ws-icon a {
background-size: contain;
/* Common.css has a padding set for PDF URLs. bg-contain expands to the
* size of the padding which makes the icons very large. we "reset" the
* padding here. 1em picked out of a hat based on console having a similar
* rule from elsewhere
*/
padding: 0 1em 0 0;
}
/* Errors and maintenance */
.cs1-code {
/* <code>...</code> style override: mediawiki's css definition is specified here:
https://git.wikimedia.org/blob/mediawiki%2Fcore.git/
69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199
*/
color: inherit;
background: inherit;
border: none;
padding: inherit;
}
.cs1-hidden-error {
display: none;
color: var(--color-error, #bf3c2c);
}
.cs1-visible-error {
color: var(--color-error, #bf3c2c);
}
.cs1-maint {
display: none;
color: #085;
margin-left: 0.3em;
}
/* kerning */
.cs1-kern-left {
padding-left: 0.2em;
}
.cs1-kern-right {
padding-right: 0.2em;
}
/* selflinks – avoid bold font style when cs1|2 template links to the current page */
.citation .mw-selflink {
font-weight: inherit;
}
@media screen {
/* Small text size
Set small text size in one place. 0.95 (here) * 0.9 (from references list) is
~0.85, which is the lower bound for size for accessibility. Old styling for this
was just 0.85. We could write the rule so that when this template is inside
references/reflist, only then does it multiply by 0.95; else multiply by 0.85 */
.cs1-format {
font-size: 95%;
}
html.skin-theme-clientpref-night .cs1-maint {
color: #18911f;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cs1-maint {
color: #18911f;
}
}
2wrho6o1q12cvwhaslan5n9g140q3wl
Tempilet:Cite news
10
934
9027
2018-03-03T19:19:37Z
en>Jo-Jo Eumerus
0
Per edit request on [[Help talk:Citation Style 1]]
9027
wikitext
text/x-wiki
<includeonly>{{#invoke:citation/CS1|citation
|CitationClass=news
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
pbjnspfej5gxihr9izxrzkow3f1uf3i
9028
8265
2026-08-22T12:06:26Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cite_news]]
8265
wikitext
text/x-wiki
<includeonly>{{#invoke:citation/CS1|citation
|CitationClass=news
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
pbjnspfej5gxihr9izxrzkow3f1uf3i
Tempilet:Collapse top
10
971
9311
2026-04-01T12:40:03Z
GoldRingChip
331
Reverted edits by [[Special:Contribs/GoldRingChip|GoldRingChip]] ([[User talk:GoldRingChip|talk]]) to last version by Explicit
9311
wikitext
text/x-wiki
{{ safesubst:<noinclude/>ifsubst||<templatestyles src="Template:Collapse_top/styles.css"/>}}
<div style="margin-left:{{{indent|0}}}"><!-- NOTE: width renders incorrectly if added to main STYLE section -->
{| role="presentation" <!-- Template:Collapse top --> class="mw-collapsible mw-archivedtalk {{<includeonly>safesubst:</includeonly>#if:{{{expand|{{{collapse|}}}}}}||mw-collapsed}} {{{class|}}}" style="color:inherit; background: {{{bg1|transparent}}}; text-align: left; border: {{{border|1px}}} solid {{{b-color|Silver}}}; margin: 0.2em auto auto; width:{{<includeonly>safesubst:</includeonly>#if:{{{width|}}}|{{{width}}}|100%}}; clear: {{{clear|both}}}; padding: 1px;"
|-
! class="{{main other|cot-header-mainspace|cot-header-other}}" style="{{<includeonly>safesubst:</includeonly>#if:{{{bg|}}}|background:{{{bg}}}|{{ safesubst:<noinclude/>ifsubst|{{main other|background:#F0F2F5|background:#CCFFCC}}|}}}}; font-size:87%; padding:0.2em 0.3em; text-align:{{<includeonly>safesubst:</includeonly>#if:{{{left|}}}|left|{{<includeonly>safesubst:</includeonly>#if:{{{align|}}}|left|center}}}}; {{<includeonly>safesubst:</includeonly>#if:{{{fc|}}}|color: {{{fc}}};|{{<includeonly>safesubst:</includeonly>#if:{{{bg|}}}|color:#202122|{{ safesubst:<noinclude/>ifsubst|color:black;|}}}}}}" | <div style="font-size:115%;{{<includeonly>safesubst:</includeonly>#if:{{{left|}}}||margin:0 4em}}">{{{1|{{{title|{{{reason|{{{header|{{{heading|{{{result|Extended content}}}}}}}}}}}}}}}}}}</div>
{{<includeonly>safesubst:</includeonly>#if:{{{warning|{{{2|}}}}}}
|{{<includeonly>safesubst:</includeonly>!}}-
{{<includeonly>safesubst:</includeonly>!}} style="text-align:center; font-style:italic;" {{<includeonly>safesubst:</includeonly>!}} {{{2|The following is a closed discussion. {{strongbad|Please do not modify it.}} }}} }}
|-
| style="color:inherit; border: solid {{{border2|1px Silver}}}; padding: {{{padding|0.6em}}}; background: {{{bg2|var(--background-color-base, #fff)}}};" {{<includeonly>safesubst:</includeonly>!}}<noinclude>
{{lorem ipsum|3}}
{{Collapse bottom}}
{{Documentation}}
</noinclude>
81u93un6q58tt6om5l86tbem971xsxy
9312
8803
2026-08-23T08:17:16Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Collapse_top]]
8803
wikitext
text/x-wiki
{{ safesubst:<noinclude/>ifsubst||<templatestyles src="Template:Collapse_top/styles.css"/>}}
<div style="margin-left:{{{indent|0}}}"><!-- NOTE: width renders incorrectly if added to main STYLE section -->
{| role="presentation" <!-- Template:Collapse top --> class="mw-collapsible mw-archivedtalk {{<includeonly>safesubst:</includeonly>#if:{{{expand|{{{collapse|}}}}}}||mw-collapsed}} {{{class|}}}" style="color:inherit; background: {{{bg1|transparent}}}; text-align: left; border: {{{border|1px}}} solid {{{b-color|Silver}}}; margin: 0.2em auto auto; width:{{<includeonly>safesubst:</includeonly>#if:{{{width|}}}|{{{width}}}|100%}}; clear: {{{clear|both}}}; padding: 1px;"
|-
! class="{{main other|cot-header-mainspace|cot-header-other}}" style="{{<includeonly>safesubst:</includeonly>#if:{{{bg|}}}|background:{{{bg}}}|{{ safesubst:<noinclude/>ifsubst|{{main other|background:#F0F2F5|background:#CCFFCC}}|}}}}; font-size:87%; padding:0.2em 0.3em; text-align:{{<includeonly>safesubst:</includeonly>#if:{{{left|}}}|left|{{<includeonly>safesubst:</includeonly>#if:{{{align|}}}|left|center}}}}; {{<includeonly>safesubst:</includeonly>#if:{{{fc|}}}|color: {{{fc}}};|{{<includeonly>safesubst:</includeonly>#if:{{{bg|}}}|color:#202122|{{ safesubst:<noinclude/>ifsubst|color:black;|}}}}}}" | <div style="font-size:115%;{{<includeonly>safesubst:</includeonly>#if:{{{left|}}}||margin:0 4em}}">{{{1|{{{title|{{{reason|{{{header|{{{heading|{{{result|Extended content}}}}}}}}}}}}}}}}}}</div>
{{<includeonly>safesubst:</includeonly>#if:{{{warning|{{{2|}}}}}}
|{{<includeonly>safesubst:</includeonly>!}}-
{{<includeonly>safesubst:</includeonly>!}} style="text-align:center; font-style:italic;" {{<includeonly>safesubst:</includeonly>!}} {{{2|The following is a closed discussion. {{strongbad|Please do not modify it.}} }}} }}
|-
| style="color:inherit; border: solid {{{border2|1px Silver}}}; padding: {{{padding|0.6em}}}; background: {{{bg2|var(--background-color-base, #fff)}}};" {{<includeonly>safesubst:</includeonly>!}}<noinclude>
{{lorem ipsum|3}}
{{Collapse bottom}}
{{Documentation}}
</noinclude>
81u93un6q58tt6om5l86tbem971xsxy
Tempilet:Ifsubst
10
972
9301
2022-01-02T08:48:20Z
Dinoguy1000
319
fix "|=foo" bug
9301
wikitext
text/x-wiki
{{ safesubst:<noinclude/>#if:{{{demo|}}}
|{{ safesubst:<noinclude/>#ifeq:{{{demo}}} |no
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}
|{{ safesubst:<noinclude/>#ifeq:{{ safesubst:<noinclude/>NAMESPACE}}|{{NAMESPACE}}
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}}}<noinclude>
{{Documentation}}
</noinclude>
6n9xrkgwrhqddknwc59l4tya8074m0o
9302
8804
2026-08-23T08:17:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Ifsubst]]
8804
wikitext
text/x-wiki
{{ safesubst:<noinclude/>#if:{{{demo|}}}
|{{ safesubst:<noinclude/>#ifeq:{{{demo}}} |no
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}
|{{ safesubst:<noinclude/>#ifeq:{{ safesubst:<noinclude/>NAMESPACE}}|{{NAMESPACE}}
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}}}<noinclude>
{{Documentation}}
</noinclude>
6n9xrkgwrhqddknwc59l4tya8074m0o
Tempilet:Collapse top/styles.css
10
973
9285
8807
2026-08-23T03:48:20Z
RAPTOR7762
18
9285
sanitized-css
text/css
/* {{pp-protected|small=yes}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
9gk0t21wwqb7sd0dzk6yotzvouu6rap
9286
9285
2026-08-23T03:48:31Z
RAPTOR7762
18
Protected "[[Tempilet:Collapse top/styles.css]]" ([Ramu=Allow only autoconfirmed users] (indefinite) [Zeme=Allow only autoconfirmed users] (indefinite))
9285
sanitized-css
text/css
/* {{pp-protected|small=yes}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
9gk0t21wwqb7sd0dzk6yotzvouu6rap
9287
9286
2026-08-23T03:49:21Z
RAPTOR7762
18
9287
sanitized-css
text/css
/* {{pp-protected}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
ti00mbkb7yhf0x05rxjw7053wfjz8ak
9288
9287
2026-08-23T03:49:50Z
RAPTOR7762
18
9288
sanitized-css
text/css
/* {{pp-protected|small=yes}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
9gk0t21wwqb7sd0dzk6yotzvouu6rap
9355
2024-11-09T18:23:41Z
Pppery
320
/* {{pp-template}} */
9355
sanitized-css
text/css
/* {{pp-template}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
3dmy4gvp7pqjgd52ssrwtrpf96lg1jj
9356
9288
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Collapse_top/styles.css]]
9288
sanitized-css
text/css
/* {{pp-protected|small=yes}} */
.cot-header-mainspace {
background:#F0F2F5;
color:inherit;
}
.cot-header-other {
background:#CCFFCC;
color:inherit;
}
@media screen {
html.skin-theme-clientpref-night .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-night .cot-header-other {
background:#003500;
color:inherit;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cot-header-mainspace {
background:#14181F;
color:inherit;
}
html.skin-theme-clientpref-os .cot-header-other {
background:#003500;
color:inherit;
}
}
9gk0t21wwqb7sd0dzk6yotzvouu6rap
Tempilet:Collapse bottom
10
974
9313
2022-08-21T18:03:39Z
MSGJ
321
Undid revision 1105766128 by [[Special:Contributions/MSGJ|MSGJ]] ([[User talk:MSGJ|talk]]) - did not work
9313
wikitext
text/x-wiki
<includeonly>|}</div></includeonly><noinclude>
{{Documentation|Template:Collapse top/doc}}
<!-- PLEASE ADD THIS TEMPLATE'S CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS -->
</noinclude>
brg0xxydzz07jqyt62vdk8nb02zd0ob
9314
8808
2026-08-23T08:17:16Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Collapse_bottom]]
8808
wikitext
text/x-wiki
<includeonly>|}</div></includeonly><noinclude>
{{Documentation|Template:Collapse top/doc}}
<!-- PLEASE ADD THIS TEMPLATE'S CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS -->
</noinclude>
brg0xxydzz07jqyt62vdk8nb02zd0ob
Tempilet:Dead link
10
1036
8997
2025-04-22T06:02:11Z
en>Paine Ellsworth
0
remove spacing template per [[Template talk:Dead link#Space before closing square bracket|talk page discussion]]
8997
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Unsubst||date=__DATE__ |$B=
<!--{{Dead link}} begin-->{{Fix
| special = <sup class="noprint Inline-Template"><span style="white-space: nowrap;">[<i>{{#if: {{{url|}}}|[https://web.archive.org/web/*/{{{url|}}} <span title="{{{title|}}}{{#if:{{{date|}}}| tagged {{{date}}}}}">dead link</span>]|[[Wikipedia:Link rot|<span title="{{{title|}}}{{#if:{{{date|}}}| Dead link tagged {{{date}}}}}">{{#if:{{{fix-attempted|}}}|permanent dead link|dead link}}</span>]]}}</i>]</span></sup>
| date = {{{date|}}}
| cat = {{main other|[[Category:All articles with dead external links]]}}
| cat-date = Category:Articles with dead external links
| cat2 = {{main other|{{#if:{{{fix-attempted|}}}|[[Category:Articles with permanently dead external links]]}}}}
}}<!--{{Dead link}} end-->
}}<noinclude>
{{Documentation}}
<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE; INTERWIKIS GO TO WIKIDATA, THANK YOU! -->
</noinclude>
mfb8yp7hxt0hhn5qczv1e5a1o8lyjeu
8998
8997
2026-08-22T12:06:24Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Dead_link]]
8997
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Unsubst||date=__DATE__ |$B=
<!--{{Dead link}} begin-->{{Fix
| special = <sup class="noprint Inline-Template"><span style="white-space: nowrap;">[<i>{{#if: {{{url|}}}|[https://web.archive.org/web/*/{{{url|}}} <span title="{{{title|}}}{{#if:{{{date|}}}| tagged {{{date}}}}}">dead link</span>]|[[Wikipedia:Link rot|<span title="{{{title|}}}{{#if:{{{date|}}}| Dead link tagged {{{date}}}}}">{{#if:{{{fix-attempted|}}}|permanent dead link|dead link}}</span>]]}}</i>]</span></sup>
| date = {{{date|}}}
| cat = {{main other|[[Category:All articles with dead external links]]}}
| cat-date = Category:Articles with dead external links
| cat2 = {{main other|{{#if:{{{fix-attempted|}}}|[[Category:Articles with permanently dead external links]]}}}}
}}<!--{{Dead link}} end-->
}}<noinclude>
{{Documentation}}
<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE; INTERWIKIS GO TO WIKIDATA, THANK YOU! -->
</noinclude>
mfb8yp7hxt0hhn5qczv1e5a1o8lyjeu
Module:Redirect
828
1037
8999
2021-09-10T07:46:37Z
en>Johnuniq
0
restore p.getTargetFromText which is used by [[Module:RfD]] which is causing "Lua error in Module:RfD at line 87: attempt to call upvalue 'getTargetFromText' (a nil value)"
8999
Scribunto
text/plain
-- This module provides functions for getting the target of a redirect page.
local p = {}
-- Gets a mw.title object, using pcall to avoid generating script errors if we
-- are over the expensive function count limit (among other possible causes).
local function getTitle(...)
local success, titleObj = pcall(mw.title.new, ...)
if success then
return titleObj
else
return nil
end
end
-- Gets the name of a page that a redirect leads to, or nil if it isn't a
-- redirect.
function p.getTargetFromText(text)
local target = string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
)
return target and mw.uri.decode(target, 'PATH')
end
-- Gets the target of a redirect. If the page specified is not a redirect,
-- returns nil.
function p.getTarget(page, fulltext)
-- Get the title object. Both page names and title objects are allowed
-- as input.
local titleObj
if type(page) == 'string' or type(page) == 'number' then
titleObj = getTitle(page)
elseif type(page) == 'table' and type(page.getContent) == 'function' then
titleObj = page
else
error(string.format(
"bad argument #1 to 'getTarget'"
.. " (string, number, or title object expected, got %s)",
type(page)
), 2)
end
if not titleObj then
return nil
end
local targetTitle = titleObj.redirectTarget
if targetTitle then
if fulltext then
return targetTitle.fullText
else
return targetTitle.prefixedText
end
else
return nil
end
end
--[[
-- Given a single page name determines what page it redirects to and returns the
-- target page name, or the passed page name when not a redirect. The passed
-- page name can be given as plain text or as a page link.
--
-- Returns page name as plain text, or when the bracket parameter is given, as a
-- page link. Returns an error message when page does not exist or the redirect
-- target cannot be determined for some reason.
--]]
function p.luaMain(rname, bracket, fulltext)
if type(rname) ~= "string" or not rname:find("%S") then
return nil
end
bracket = bracket and "[[%s]]" or "%s"
rname = rname:match("%[%[(.+)%]%]") or rname
local target = p.getTarget(rname, fulltext)
local ret = target or rname
ret = getTitle(ret)
if ret then
if fulltext then
ret = ret.fullText
else
ret = ret.prefixedText
end
return bracket:format(ret)
else
return nil
end
end
-- Provides access to the luaMain function from wikitext.
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
return p.luaMain(args[1], args.bracket, args.fulltext) or ''
end
-- Returns true if the specified page is a redirect, and false otherwise.
function p.luaIsRedirect(page)
local titleObj = getTitle(page)
if not titleObj then
return false
end
if titleObj.isRedirect then
return true
else
return false
end
end
-- Provides access to the luaIsRedirect function from wikitext, returning 'yes'
-- if the specified page is a redirect, and the blank string otherwise.
function p.isRedirect(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
if p.luaIsRedirect(args[1]) then
return 'yes'
else
return ''
end
end
return p
ixuh7hehfu8mxwx3ai7pksok45inaxs
9000
8999
2026-08-22T12:06:24Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Redirect]]
8999
Scribunto
text/plain
-- This module provides functions for getting the target of a redirect page.
local p = {}
-- Gets a mw.title object, using pcall to avoid generating script errors if we
-- are over the expensive function count limit (among other possible causes).
local function getTitle(...)
local success, titleObj = pcall(mw.title.new, ...)
if success then
return titleObj
else
return nil
end
end
-- Gets the name of a page that a redirect leads to, or nil if it isn't a
-- redirect.
function p.getTargetFromText(text)
local target = string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
)
return target and mw.uri.decode(target, 'PATH')
end
-- Gets the target of a redirect. If the page specified is not a redirect,
-- returns nil.
function p.getTarget(page, fulltext)
-- Get the title object. Both page names and title objects are allowed
-- as input.
local titleObj
if type(page) == 'string' or type(page) == 'number' then
titleObj = getTitle(page)
elseif type(page) == 'table' and type(page.getContent) == 'function' then
titleObj = page
else
error(string.format(
"bad argument #1 to 'getTarget'"
.. " (string, number, or title object expected, got %s)",
type(page)
), 2)
end
if not titleObj then
return nil
end
local targetTitle = titleObj.redirectTarget
if targetTitle then
if fulltext then
return targetTitle.fullText
else
return targetTitle.prefixedText
end
else
return nil
end
end
--[[
-- Given a single page name determines what page it redirects to and returns the
-- target page name, or the passed page name when not a redirect. The passed
-- page name can be given as plain text or as a page link.
--
-- Returns page name as plain text, or when the bracket parameter is given, as a
-- page link. Returns an error message when page does not exist or the redirect
-- target cannot be determined for some reason.
--]]
function p.luaMain(rname, bracket, fulltext)
if type(rname) ~= "string" or not rname:find("%S") then
return nil
end
bracket = bracket and "[[%s]]" or "%s"
rname = rname:match("%[%[(.+)%]%]") or rname
local target = p.getTarget(rname, fulltext)
local ret = target or rname
ret = getTitle(ret)
if ret then
if fulltext then
ret = ret.fullText
else
ret = ret.prefixedText
end
return bracket:format(ret)
else
return nil
end
end
-- Provides access to the luaMain function from wikitext.
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
return p.luaMain(args[1], args.bracket, args.fulltext) or ''
end
-- Returns true if the specified page is a redirect, and false otherwise.
function p.luaIsRedirect(page)
local titleObj = getTitle(page)
if not titleObj then
return false
end
if titleObj.isRedirect then
return true
else
return false
end
end
-- Provides access to the luaIsRedirect function from wikitext, returning 'yes'
-- if the specified page is a redirect, and the blank string otherwise.
function p.isRedirect(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
if p.luaIsRedirect(args[1]) then
return 'yes'
else
return ''
end
end
return p
ixuh7hehfu8mxwx3ai7pksok45inaxs
Tempilet:Fix
10
1038
9019
2025-09-14T16:45:46Z
en>Ahecht
0
Reduce [[WP:PEIS]]
9019
wikitext
text/x-wiki
{{#switch:{{{subst|¬}}}
|¬={{#invoke:Category handler|main
|template=[[Category:Templates needing substitution checking]]
|nocat={{{nocat|<noinclude>true</noinclude>}}}
}}
|SUBST=[[Category:Pages with incorrectly substituted templates]]
}}{{#invoke:Category handler|main
|main={{Fix/category
|cat-date={{{cat-date|}}}
|cat={{{cat|}}}
|cat-date2={{{cat-date2|}}}
|cat2={{{cat2|}}}
|cat-date3={{{cat-date3|}}}
|cat3={{{cat3|}}}
|date={{{date|}}}
}}
|template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:Templates including undated clean-up tags]]}}}}}}
|subpage=no
}}{{#if:{{{text|}}}
|<sup class="noprint Inline-Template {{{class|}}}" style="white-space:nowrap;">[<i>{{#if:{{{pre-text|}}}
|{{{pre-text}}} 
}}[[{{{link|Wikipedia:Cleanup}}}|<span title="{{#invoke:string|replace|source={{delink|1={{{title|{{{link|Wikipedia:Cleanup}}}}}}{{#if:{{{date|}}}| ({{{date}}})}}}}|pattern=" |replace=" |plain=true}}">{{{text|}}}</span>]]{{#if:{{{post-text|}}}
| {{{post-text}}}
}}</i>]</sup>|{{{special|}}}
}}{{#invoke:Check for unknown parameters|check|unknown=[[Category:Pages using Template:Fix with unknown parameters|_VALUE_{{PAGENAME}}]]|preview=Page using [[Template:Fix]] with unknown parameter "_VALUE_"|ignoreblank=y| cat | cat-date | cat-date2 | cat-date3 | cat2 | cat3 | class | date | link | name | nocat | post-text | pre-text | special | subst | text | title }}<noinclude>
{{Documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
jwz6zae1wne77hdp52ah3ko3sqik945
9020
9019
2026-08-22T12:06:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Fix]]
9019
wikitext
text/x-wiki
{{#switch:{{{subst|¬}}}
|¬={{#invoke:Category handler|main
|template=[[Category:Templates needing substitution checking]]
|nocat={{{nocat|<noinclude>true</noinclude>}}}
}}
|SUBST=[[Category:Pages with incorrectly substituted templates]]
}}{{#invoke:Category handler|main
|main={{Fix/category
|cat-date={{{cat-date|}}}
|cat={{{cat|}}}
|cat-date2={{{cat-date2|}}}
|cat2={{{cat2|}}}
|cat-date3={{{cat-date3|}}}
|cat3={{{cat3|}}}
|date={{{date|}}}
}}
|template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:Templates including undated clean-up tags]]}}}}}}
|subpage=no
}}{{#if:{{{text|}}}
|<sup class="noprint Inline-Template {{{class|}}}" style="white-space:nowrap;">[<i>{{#if:{{{pre-text|}}}
|{{{pre-text}}} 
}}[[{{{link|Wikipedia:Cleanup}}}|<span title="{{#invoke:string|replace|source={{delink|1={{{title|{{{link|Wikipedia:Cleanup}}}}}}{{#if:{{{date|}}}| ({{{date}}})}}}}|pattern=" |replace=" |plain=true}}">{{{text|}}}</span>]]{{#if:{{{post-text|}}}
| {{{post-text}}}
}}</i>]</sup>|{{{special|}}}
}}{{#invoke:Check for unknown parameters|check|unknown=[[Category:Pages using Template:Fix with unknown parameters|_VALUE_{{PAGENAME}}]]|preview=Page using [[Template:Fix]] with unknown parameter "_VALUE_"|ignoreblank=y| cat | cat-date | cat-date2 | cat-date3 | cat2 | cat3 | class | date | link | name | nocat | post-text | pre-text | special | subst | text | title }}<noinclude>
{{Documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
jwz6zae1wne77hdp52ah3ko3sqik945
Tempilet:Icon
10
1039
9029
2024-03-09T15:06:32Z
en>Plastikspork
0
Closing TfD as merge
9029
wikitext
text/x-wiki
{{#invoke:Icon|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
m4ab9noabl8v4ki5cx6t5ksjcjh5u8o
9030
9029
2026-08-22T12:06:26Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Icon]]
9029
wikitext
text/x-wiki
{{#invoke:Icon|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
m4ab9noabl8v4ki5cx6t5ksjcjh5u8o
Tempilet:Navbox
10
1040
9031
2021-06-26T18:05:09Z
en>Trialpears
0
Remove TfD notice as it wouldn't involve any changes to this template.
9031
wikitext
text/x-wiki
<includeonly>{{#invoke:Navbox|navbox}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
tqodcaa2vvhehqaod229udlla0wimek
9032
9031
2026-08-22T12:06:26Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Navbox]]
9031
wikitext
text/x-wiki
<includeonly>{{#invoke:Navbox|navbox}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
tqodcaa2vvhehqaod229udlla0wimek
Module:Format link
828
1041
9033
2022-10-04T13:37:11Z
en>Pppery
0
Avoid Lua erroring when we run out of expensive parser function calls
9033
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Format link
--
-- Makes a wikilink from the given link and display values. Links are escaped
-- with colons if necessary, and links to sections are detected and displayed
-- with " § " as a separator rather than the standard MediaWiki "#". Used in
-- the {{format link}} template.
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local mError -- lazily initialise [[Module:Error]]
local yesno -- lazily initialise [[Module:Yesno]]
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
local function maybeItalicize(s, shouldItalicize)
-- Italicize s if s is a string and the shouldItalicize parameter is true.
if s and shouldItalicize then
return '<i>' .. s .. '</i>'
else
return s
end
end
local function parseLink(link)
-- Parse a link and return a table with the link's components.
-- These components are:
-- - link: the link, stripped of any initial colon (always present)
-- - page: the page name (always present)
-- - section: the page name (may be nil)
-- - display: the display text, if manually entered after a pipe (may be nil)
link = removeInitialColon(link)
-- Find whether a faux display value has been added with the {{!}} magic
-- word.
local prePipe, display = link:match('^(.-)|(.*)$')
link = prePipe or link
-- Find the page, if it exists.
-- For links like [[#Bar]], the page will be nil.
local preHash, postHash = link:match('^(.-)#(.*)$')
local page
if not preHash then
-- We have a link like [[Foo]].
page = link
elseif preHash ~= '' then
-- We have a link like [[Foo#Bar]].
page = preHash
end
-- Find the section, if it exists.
local section
if postHash and postHash ~= '' then
section = postHash
end
return {
link = link,
page = page,
section = section,
display = display,
}
end
local function formatDisplay(parsed, options)
-- Formats a display string based on a parsed link table (matching the
-- output of parseLink) and an options table (matching the input options for
-- _formatLink).
local page = maybeItalicize(parsed.page, options.italicizePage)
local section = maybeItalicize(parsed.section, options.italicizeSection)
if (not section) then
return page
elseif (not page) then
return mw.ustring.format('§ %s', section)
else
return mw.ustring.format('%s § %s', page, section)
end
end
local function missingArgError(target)
mError = require('Module:Error')
return mError.error{message =
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])'
}
end
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.formatLink(frame)
-- The formatLink export function, for use in templates.
yesno = require('Module:Yesno')
local args = getArgs(frame)
local link = args[1] or args.link
local target = args[3] or args.target
if not (link or target) then
return missingArgError('Template:Format link')
end
return p._formatLink{
link = link,
display = args[2] or args.display,
target = target,
italicizePage = yesno(args.italicizepage),
italicizeSection = yesno(args.italicizesection),
categorizeMissing = args.categorizemissing
}
end
function p._formatLink(options)
-- The formatLink export function, for use in modules.
checkType('_formatLink', 1, options, 'table')
local function check(key, expectedType) --for brevity
checkTypeForNamedArg(
'_formatLink', key, options[key], expectedType or 'string', true
)
end
check('link')
check('display')
check('target')
check('italicizePage', 'boolean')
check('italicizeSection', 'boolean')
check('categorizeMissing')
-- Normalize link and target and check that at least one is present
if options.link == '' then options.link = nil end
if options.target == '' then options.target = nil end
if not (options.link or options.target) then
return missingArgError('Module:Format link')
end
local parsed = parseLink(options.link)
local display = options.display or parsed.display
local catMissing = options.categorizeMissing
local category = ''
-- Find the display text
if not display then display = formatDisplay(parsed, options) end
-- Handle the target option if present
if options.target then
local parsedTarget = parseLink(options.target)
parsed.link = parsedTarget.link
parsed.page = parsedTarget.page
end
-- Test if page exists if a diagnostic category is specified
if catMissing and (mw.ustring.len(catMissing) > 0) then
local title = nil
if parsed.page then title = mw.title.new(parsed.page) end
if title and (not title.isExternal) then
local success, exists = pcall(function() return title.exists end)
if success and not exists then
category = mw.ustring.format('[[Category:%s]]', catMissing)
end
end
end
-- Format the result as a link
if parsed.link == display then
return mw.ustring.format('[[:%s]]%s', parsed.link, category)
else
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category)
end
end
--------------------------------------------------------------------------------
-- Derived convenience functions
--------------------------------------------------------------------------------
function p.formatPages(options, pages)
-- Formats an array of pages using formatLink and the given options table,
-- and returns it as an array. Nil values are not allowed.
local ret = {}
for i, page in ipairs(pages) do
ret[i] = p._formatLink{
link = page,
categorizeMissing = options.categorizeMissing,
italicizePage = options.italicizePage,
italicizeSection = options.italicizeSection
}
end
return ret
end
return p
252hp8jk2qv051cngf0qjx0ljcf0bof
9034
9033
2026-08-22T12:06:26Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Format_link]]
9033
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Format link
--
-- Makes a wikilink from the given link and display values. Links are escaped
-- with colons if necessary, and links to sections are detected and displayed
-- with " § " as a separator rather than the standard MediaWiki "#". Used in
-- the {{format link}} template.
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local mError -- lazily initialise [[Module:Error]]
local yesno -- lazily initialise [[Module:Yesno]]
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
local function maybeItalicize(s, shouldItalicize)
-- Italicize s if s is a string and the shouldItalicize parameter is true.
if s and shouldItalicize then
return '<i>' .. s .. '</i>'
else
return s
end
end
local function parseLink(link)
-- Parse a link and return a table with the link's components.
-- These components are:
-- - link: the link, stripped of any initial colon (always present)
-- - page: the page name (always present)
-- - section: the page name (may be nil)
-- - display: the display text, if manually entered after a pipe (may be nil)
link = removeInitialColon(link)
-- Find whether a faux display value has been added with the {{!}} magic
-- word.
local prePipe, display = link:match('^(.-)|(.*)$')
link = prePipe or link
-- Find the page, if it exists.
-- For links like [[#Bar]], the page will be nil.
local preHash, postHash = link:match('^(.-)#(.*)$')
local page
if not preHash then
-- We have a link like [[Foo]].
page = link
elseif preHash ~= '' then
-- We have a link like [[Foo#Bar]].
page = preHash
end
-- Find the section, if it exists.
local section
if postHash and postHash ~= '' then
section = postHash
end
return {
link = link,
page = page,
section = section,
display = display,
}
end
local function formatDisplay(parsed, options)
-- Formats a display string based on a parsed link table (matching the
-- output of parseLink) and an options table (matching the input options for
-- _formatLink).
local page = maybeItalicize(parsed.page, options.italicizePage)
local section = maybeItalicize(parsed.section, options.italicizeSection)
if (not section) then
return page
elseif (not page) then
return mw.ustring.format('§ %s', section)
else
return mw.ustring.format('%s § %s', page, section)
end
end
local function missingArgError(target)
mError = require('Module:Error')
return mError.error{message =
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])'
}
end
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.formatLink(frame)
-- The formatLink export function, for use in templates.
yesno = require('Module:Yesno')
local args = getArgs(frame)
local link = args[1] or args.link
local target = args[3] or args.target
if not (link or target) then
return missingArgError('Template:Format link')
end
return p._formatLink{
link = link,
display = args[2] or args.display,
target = target,
italicizePage = yesno(args.italicizepage),
italicizeSection = yesno(args.italicizesection),
categorizeMissing = args.categorizemissing
}
end
function p._formatLink(options)
-- The formatLink export function, for use in modules.
checkType('_formatLink', 1, options, 'table')
local function check(key, expectedType) --for brevity
checkTypeForNamedArg(
'_formatLink', key, options[key], expectedType or 'string', true
)
end
check('link')
check('display')
check('target')
check('italicizePage', 'boolean')
check('italicizeSection', 'boolean')
check('categorizeMissing')
-- Normalize link and target and check that at least one is present
if options.link == '' then options.link = nil end
if options.target == '' then options.target = nil end
if not (options.link or options.target) then
return missingArgError('Module:Format link')
end
local parsed = parseLink(options.link)
local display = options.display or parsed.display
local catMissing = options.categorizeMissing
local category = ''
-- Find the display text
if not display then display = formatDisplay(parsed, options) end
-- Handle the target option if present
if options.target then
local parsedTarget = parseLink(options.target)
parsed.link = parsedTarget.link
parsed.page = parsedTarget.page
end
-- Test if page exists if a diagnostic category is specified
if catMissing and (mw.ustring.len(catMissing) > 0) then
local title = nil
if parsed.page then title = mw.title.new(parsed.page) end
if title and (not title.isExternal) then
local success, exists = pcall(function() return title.exists end)
if success and not exists then
category = mw.ustring.format('[[Category:%s]]', catMissing)
end
end
end
-- Format the result as a link
if parsed.link == display then
return mw.ustring.format('[[:%s]]%s', parsed.link, category)
else
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category)
end
end
--------------------------------------------------------------------------------
-- Derived convenience functions
--------------------------------------------------------------------------------
function p.formatPages(options, pages)
-- Formats an array of pages using formatLink and the given options table,
-- and returns it as an array. Nil values are not allowed.
local ret = {}
for i, page in ipairs(pages) do
ret[i] = p._formatLink{
link = page,
categorizeMissing = options.categorizeMissing,
italicizePage = options.italicizePage,
italicizeSection = options.italicizeSection
}
end
return ret
end
return p
252hp8jk2qv051cngf0qjx0ljcf0bof
Module:Hatnote
828
1042
9035
2025-03-18T15:47:33Z
en>Ahecht
0
Revert
9035
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote --
-- --
-- This module produces hatnote links and links to related articles. It --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules. --
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local formatLink -- lazily initialise [[Module:Format link]] ._formatLink
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
function p.defaultClasses(inline)
-- Provides the default hatnote classes as a space-separated string; useful
-- for hatnote-manipulation modules like [[Module:Hatnote group]].
return
(inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
'navigation-not-searchable'
end
function p.disambiguate(page, disambiguator)
-- Formats a page title with a disambiguation parenthetical,
-- i.e. "Example" → "Example (disambiguation)".
checkType('disambiguate', 1, page, 'string')
checkType('disambiguate', 2, disambiguator, 'string', true)
disambiguator = disambiguator or 'disambiguation'
return mw.ustring.format('%s (%s)', page, disambiguator)
end
function p.findNamespaceId(link, removeColon)
-- Finds the namespace id (namespace number) of a link or a pagename. This
-- function will not work if the link is enclosed in double brackets. Colons
-- are trimmed from the start of the link by default. To skip colon
-- trimming, set the removeColon parameter to false.
checkType('findNamespaceId', 1, link, 'string')
checkType('findNamespaceId', 2, removeColon, 'boolean', true)
if removeColon ~= false then
link = removeInitialColon(link)
end
local namespace = link:match('^(.-):')
if namespace then
local nsTable = mw.site.namespaces[namespace]
if nsTable then
return nsTable.id
end
end
return 0
end
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
-- is added.
checkType('makeWikitextError', 1, msg, 'string')
checkType('makeWikitextError', 2, helpLink, 'string', true)
yesno = require('Module:Yesno')
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
local helpText
if helpLink then
helpText = ' ([[' .. helpLink .. '|help]])'
else
helpText = ''
end
-- Make the category text.
local category
if not title.isTalkPage -- Don't categorise talk pages
and title.namespace ~= 2 -- Don't categorise userspace
and yesno(addTrackingCategory) ~= false -- Allow opting out
then
category = 'Hatnote templates with errors'
category = mw.ustring.format(
'[[%s:%s]]',
mw.site.namespaces[14].name,
category
)
else
category = ''
end
return mw.ustring.format(
'<strong class="error">Error: %s%s.</strong>%s',
msg,
helpText,
category
)
end
local curNs = mw.title.getCurrentTitle().namespace
p.missingTargetCat =
--Default missing target category, exported for use in related modules
((curNs == 0) or (curNs == 14)) and
'Articles with hatnote templates targeting a nonexistent page' or nil
function p.quote(title)
--Wraps titles in quotation marks. If the title starts/ends with a quotation
--mark, kerns that side as with {{-'}}
local quotationMarks = {
["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
}
local quoteLeft, quoteRight = -- Test if start/end are quotation marks
quotationMarks[string.sub(title, 1, 1)],
quotationMarks[string.sub(title, -1, -1)]
if quoteLeft or quoteRight then
title = mw.html.create("span"):wikitext(title)
end
if quoteLeft then title:css("padding-left", "0.15em") end
if quoteRight then title:css("padding-right", "0.15em") end
return '"' .. tostring(title) .. '"'
end
--------------------------------------------------------------------------------
-- Hatnote
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
--------------------------------------------------------------------------------
p[''] = function (frame) return p.hatnote(frame:newChild{ title = "Template:Hatnote" }) end
function p.hatnote(frame)
local args = getArgs(frame)
local s = args[1]
if not s then
return p.makeWikitextError(
'no text specified',
'Template:Hatnote#Errors',
args.category
)
end
return p._hatnote(s, {
extraclasses = args.extraclasses,
selfref = args.selfref
})
end
function p._hatnote(s, options)
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 2, options, 'table', true)
options = options or {}
local inline = options.inline
local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
local extraclasses
if type(options.extraclasses) == 'string' then
extraclasses = options.extraclasses
end
hatnote
:attr('role', 'note')
:addClass(p.defaultClasses(inline))
:addClass(extraclasses)
:addClass(options.selfref and 'selfref' or nil)
:wikitext(s)
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
} .. tostring(hatnote)
end
return p
qps4k9ys6ba1dq9msz6m6lq3kfc4w6t
9036
9035
2026-08-22T12:06:26Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Hatnote]]
9035
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote --
-- --
-- This module produces hatnote links and links to related articles. It --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules. --
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local formatLink -- lazily initialise [[Module:Format link]] ._formatLink
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
function p.defaultClasses(inline)
-- Provides the default hatnote classes as a space-separated string; useful
-- for hatnote-manipulation modules like [[Module:Hatnote group]].
return
(inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
'navigation-not-searchable'
end
function p.disambiguate(page, disambiguator)
-- Formats a page title with a disambiguation parenthetical,
-- i.e. "Example" → "Example (disambiguation)".
checkType('disambiguate', 1, page, 'string')
checkType('disambiguate', 2, disambiguator, 'string', true)
disambiguator = disambiguator or 'disambiguation'
return mw.ustring.format('%s (%s)', page, disambiguator)
end
function p.findNamespaceId(link, removeColon)
-- Finds the namespace id (namespace number) of a link or a pagename. This
-- function will not work if the link is enclosed in double brackets. Colons
-- are trimmed from the start of the link by default. To skip colon
-- trimming, set the removeColon parameter to false.
checkType('findNamespaceId', 1, link, 'string')
checkType('findNamespaceId', 2, removeColon, 'boolean', true)
if removeColon ~= false then
link = removeInitialColon(link)
end
local namespace = link:match('^(.-):')
if namespace then
local nsTable = mw.site.namespaces[namespace]
if nsTable then
return nsTable.id
end
end
return 0
end
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
-- is added.
checkType('makeWikitextError', 1, msg, 'string')
checkType('makeWikitextError', 2, helpLink, 'string', true)
yesno = require('Module:Yesno')
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
local helpText
if helpLink then
helpText = ' ([[' .. helpLink .. '|help]])'
else
helpText = ''
end
-- Make the category text.
local category
if not title.isTalkPage -- Don't categorise talk pages
and title.namespace ~= 2 -- Don't categorise userspace
and yesno(addTrackingCategory) ~= false -- Allow opting out
then
category = 'Hatnote templates with errors'
category = mw.ustring.format(
'[[%s:%s]]',
mw.site.namespaces[14].name,
category
)
else
category = ''
end
return mw.ustring.format(
'<strong class="error">Error: %s%s.</strong>%s',
msg,
helpText,
category
)
end
local curNs = mw.title.getCurrentTitle().namespace
p.missingTargetCat =
--Default missing target category, exported for use in related modules
((curNs == 0) or (curNs == 14)) and
'Articles with hatnote templates targeting a nonexistent page' or nil
function p.quote(title)
--Wraps titles in quotation marks. If the title starts/ends with a quotation
--mark, kerns that side as with {{-'}}
local quotationMarks = {
["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
}
local quoteLeft, quoteRight = -- Test if start/end are quotation marks
quotationMarks[string.sub(title, 1, 1)],
quotationMarks[string.sub(title, -1, -1)]
if quoteLeft or quoteRight then
title = mw.html.create("span"):wikitext(title)
end
if quoteLeft then title:css("padding-left", "0.15em") end
if quoteRight then title:css("padding-right", "0.15em") end
return '"' .. tostring(title) .. '"'
end
--------------------------------------------------------------------------------
-- Hatnote
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
--------------------------------------------------------------------------------
p[''] = function (frame) return p.hatnote(frame:newChild{ title = "Template:Hatnote" }) end
function p.hatnote(frame)
local args = getArgs(frame)
local s = args[1]
if not s then
return p.makeWikitextError(
'no text specified',
'Template:Hatnote#Errors',
args.category
)
end
return p._hatnote(s, {
extraclasses = args.extraclasses,
selfref = args.selfref
})
end
function p._hatnote(s, options)
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 2, options, 'table', true)
options = options or {}
local inline = options.inline
local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
local extraclasses
if type(options.extraclasses) == 'string' then
extraclasses = options.extraclasses
end
hatnote
:attr('role', 'note')
:addClass(p.defaultClasses(inline))
:addClass(extraclasses)
:addClass(options.selfref and 'selfref' or nil)
:wikitext(s)
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
} .. tostring(hatnote)
end
return p
qps4k9ys6ba1dq9msz6m6lq3kfc4w6t
Module:Hatnote/styles.css
828
1043
9037
2026-08-09T16:48:05Z
en>Izno
0
Parsoid is now the one true parser
9037
sanitized-css
text/css
/* {{pp|small=y}} */
.hatnote {
font-style: italic;
}
/* Limit structure CSS to divs because of [[Module:Hatnote inline]] */
div.hatnote {
/* @noflip */
padding-left: 1.6em;
margin-bottom: 0.5em;
}
.hatnote i {
font-style: normal;
}
/* Templatestyles causes an 'empty' span between hatnotes.
* See also [[phab:T200206]] for later */
.hatnote + .mw-empty-elt + .hatnote {
margin-top: -0.5em;
}
@media print {
body.ns-0 .hatnote {
display: none !important;
}
}
kcpl5b33dm6ymty930mbmszl720l5oi
9038
9037
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Hatnote/styles.css]]
9037
sanitized-css
text/css
/* {{pp|small=y}} */
.hatnote {
font-style: italic;
}
/* Limit structure CSS to divs because of [[Module:Hatnote inline]] */
div.hatnote {
/* @noflip */
padding-left: 1.6em;
margin-bottom: 0.5em;
}
.hatnote i {
font-style: normal;
}
/* Templatestyles causes an 'empty' span between hatnotes.
* See also [[phab:T200206]] for later */
.hatnote + .mw-empty-elt + .hatnote {
margin-top: -0.5em;
}
@media print {
body.ns-0 .hatnote {
display: none !important;
}
}
kcpl5b33dm6ymty930mbmszl720l5oi
Module:Hatnote list
828
1044
9039
2023-11-13T21:00:31Z
en>Nihiltres
0
Updated from sandbox: added support for punctuation collapse when text is italicized. The update's content includes changes by users Johnuniq, Dexxor, and Nihiltres.
9039
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote list --
-- --
-- This module produces and formats lists for use in hatnotes. In particular, --
-- it implements the for-see list, i.e. lists of "For X, see Y" statements, --
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced --
-- are andList & orList helpers for formatting lists with those conjunctions. --
--------------------------------------------------------------------------------
local mArguments --initialize lazily
local mFormatLink = require('Module:Format link')
local mHatnote = require('Module:Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
--------------------------------------------------------------------------------
-- List stringification helper functions
--
-- These functions are used for stringifying lists, usually page lists inside
-- the "Y" portion of "For X, see Y" for-see items.
--------------------------------------------------------------------------------
--default options table used across the list stringification functions
local stringifyListDefaultOptions = {
conjunction = "and",
separator = ",",
altSeparator = ";",
space = " ",
formatted = false
}
--Searches display text only
local function searchDisp(haystack, needle)
return string.find(
string.sub(haystack, (string.find(haystack, '|') or 0) + 1), needle
)
end
-- Stringifies a list generically; probably shouldn't be used directly
local function stringifyList(list, options)
-- Type-checks, defaults, and a shortcut
checkType("stringifyList", 1, list, "table")
if #list == 0 then return nil end
checkType("stringifyList", 2, options, "table", true)
options = options or {}
for k, v in pairs(stringifyListDefaultOptions) do
if options[k] == nil then options[k] = v end
end
local s = options.space
-- Format the list if requested
if options.formatted then
list = mFormatLink.formatPages(
{categorizeMissing = mHatnote.missingTargetCat}, list
)
end
-- Set the separator; if any item contains it, use the alternate separator
local separator = options.separator
for k, v in pairs(list) do
if searchDisp(v, separator) then
separator = options.altSeparator
break
end
end
-- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§"
local conjunction = s .. options.conjunction .. s
if #list == 2 and searchDisp(list[1], "§") or #list > 2 then
conjunction = separator .. conjunction
end
-- Return the formatted string
return mw.text.listToText(list, separator .. s, conjunction)
end
--DRY function
function p.conjList (conj, list, fmt)
return stringifyList(list, {conjunction = conj, formatted = fmt})
end
-- Stringifies lists with "and" or "or"
function p.andList (...) return p.conjList("and", ...) end
function p.orList (...) return p.conjList("or", ...) end
--------------------------------------------------------------------------------
-- For see
--
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the
-- {{about}} and {{redirect}} templates and their variants.
--------------------------------------------------------------------------------
--default options table used across the forSee family of functions
local forSeeDefaultOptions = {
andKeyword = 'and',
title = mw.title.getCurrentTitle().text,
otherText = 'other uses',
forSeeForm = 'For %s, see %s.',
}
--Collapses duplicate punctuation at end of string, ignoring italics and links
local function punctuationCollapse (text)
return text:match("[.?!]('?)%1(%]?)%2%.$") and text:sub(1, -2) or text
end
-- Structures arguments into a table for stringification, & options
function p.forSeeArgsToTable (args, from, options)
-- Type-checks and defaults
checkType("forSeeArgsToTable", 1, args, 'table')
checkType("forSeeArgsToTable", 2, from, 'number', true)
from = from or 1
checkType("forSeeArgsToTable", 3, options, 'table', true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- maxArg's gotten manually because getArgs() and table.maxn aren't friends
local maxArg = 0
for k, v in pairs(args) do
if type(k) == 'number' and k > maxArg then maxArg = k end
end
-- Structure the data out from the parameter list:
-- * forTable is the wrapper table, with forRow rows
-- * Rows are tables of a "use" string & a "pages" table of pagename strings
-- * Blanks are left empty for defaulting elsewhere, but can terminate list
local forTable = {}
local i = from
local terminated = false
-- If there is extra text, and no arguments are given, give nil value
-- to not produce default of "For other uses, see foo (disambiguation)"
if options.extratext and i > maxArg then return nil end
-- Loop to generate rows
repeat
-- New empty row
local forRow = {}
-- On blank use, assume list's ended & break at end of this loop
forRow.use = args[i]
if not args[i] then terminated = true end
-- New empty list of pages
forRow.pages = {}
-- Insert first pages item if present
table.insert(forRow.pages, args[i + 1])
-- If the param after next is "and", do inner loop to collect params
-- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3}
while args[i + 2] == options.andKeyword do
if args[i + 3] then
table.insert(forRow.pages, args[i + 3])
end
-- Increment to next "and"
i = i + 2
end
-- Increment to next use
i = i + 2
-- Append the row
table.insert(forTable, forRow)
until terminated or i > maxArg
return forTable
end
-- Stringifies a table as formatted by forSeeArgsToTable
function p.forSeeTableToString (forSeeTable, options)
-- Type-checks and defaults
checkType("forSeeTableToString", 1, forSeeTable, "table", true)
checkType("forSeeTableToString", 2, options, "table", true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Stringify each for-see item into a list
local strList = {}
if forSeeTable then
for k, v in pairs(forSeeTable) do
local useStr = v.use or options.otherText
local pagesStr =
p.andList(v.pages, true) or
mFormatLink._formatLink{
categorizeMissing = mHatnote.missingTargetCat,
link = mHatnote.disambiguate(options.title)
}
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)
forSeeStr = punctuationCollapse(forSeeStr)
table.insert(strList, forSeeStr)
end
end
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'.')) end
-- Return the concatenated list
return table.concat(strList, ' ')
end
-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps
-- but not blank/whitespace values. Ignores named args and args < "from".
function p._forSee (args, from, options)
local forSeeTable = p.forSeeArgsToTable(args, from, options)
return p.forSeeTableToString(forSeeTable, options)
end
-- As _forSee, but uses the frame.
function p.forSee (frame, from, options)
mArguments = require('Module:Arguments')
return p._forSee(mArguments.getArgs(frame), from, options)
end
return p
3c31ivxc2t731ceyfvqcqlnp9acgg3s
9040
9039
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Hatnote_list]]
9039
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote list --
-- --
-- This module produces and formats lists for use in hatnotes. In particular, --
-- it implements the for-see list, i.e. lists of "For X, see Y" statements, --
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced --
-- are andList & orList helpers for formatting lists with those conjunctions. --
--------------------------------------------------------------------------------
local mArguments --initialize lazily
local mFormatLink = require('Module:Format link')
local mHatnote = require('Module:Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
--------------------------------------------------------------------------------
-- List stringification helper functions
--
-- These functions are used for stringifying lists, usually page lists inside
-- the "Y" portion of "For X, see Y" for-see items.
--------------------------------------------------------------------------------
--default options table used across the list stringification functions
local stringifyListDefaultOptions = {
conjunction = "and",
separator = ",",
altSeparator = ";",
space = " ",
formatted = false
}
--Searches display text only
local function searchDisp(haystack, needle)
return string.find(
string.sub(haystack, (string.find(haystack, '|') or 0) + 1), needle
)
end
-- Stringifies a list generically; probably shouldn't be used directly
local function stringifyList(list, options)
-- Type-checks, defaults, and a shortcut
checkType("stringifyList", 1, list, "table")
if #list == 0 then return nil end
checkType("stringifyList", 2, options, "table", true)
options = options or {}
for k, v in pairs(stringifyListDefaultOptions) do
if options[k] == nil then options[k] = v end
end
local s = options.space
-- Format the list if requested
if options.formatted then
list = mFormatLink.formatPages(
{categorizeMissing = mHatnote.missingTargetCat}, list
)
end
-- Set the separator; if any item contains it, use the alternate separator
local separator = options.separator
for k, v in pairs(list) do
if searchDisp(v, separator) then
separator = options.altSeparator
break
end
end
-- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§"
local conjunction = s .. options.conjunction .. s
if #list == 2 and searchDisp(list[1], "§") or #list > 2 then
conjunction = separator .. conjunction
end
-- Return the formatted string
return mw.text.listToText(list, separator .. s, conjunction)
end
--DRY function
function p.conjList (conj, list, fmt)
return stringifyList(list, {conjunction = conj, formatted = fmt})
end
-- Stringifies lists with "and" or "or"
function p.andList (...) return p.conjList("and", ...) end
function p.orList (...) return p.conjList("or", ...) end
--------------------------------------------------------------------------------
-- For see
--
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the
-- {{about}} and {{redirect}} templates and their variants.
--------------------------------------------------------------------------------
--default options table used across the forSee family of functions
local forSeeDefaultOptions = {
andKeyword = 'and',
title = mw.title.getCurrentTitle().text,
otherText = 'other uses',
forSeeForm = 'For %s, see %s.',
}
--Collapses duplicate punctuation at end of string, ignoring italics and links
local function punctuationCollapse (text)
return text:match("[.?!]('?)%1(%]?)%2%.$") and text:sub(1, -2) or text
end
-- Structures arguments into a table for stringification, & options
function p.forSeeArgsToTable (args, from, options)
-- Type-checks and defaults
checkType("forSeeArgsToTable", 1, args, 'table')
checkType("forSeeArgsToTable", 2, from, 'number', true)
from = from or 1
checkType("forSeeArgsToTable", 3, options, 'table', true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- maxArg's gotten manually because getArgs() and table.maxn aren't friends
local maxArg = 0
for k, v in pairs(args) do
if type(k) == 'number' and k > maxArg then maxArg = k end
end
-- Structure the data out from the parameter list:
-- * forTable is the wrapper table, with forRow rows
-- * Rows are tables of a "use" string & a "pages" table of pagename strings
-- * Blanks are left empty for defaulting elsewhere, but can terminate list
local forTable = {}
local i = from
local terminated = false
-- If there is extra text, and no arguments are given, give nil value
-- to not produce default of "For other uses, see foo (disambiguation)"
if options.extratext and i > maxArg then return nil end
-- Loop to generate rows
repeat
-- New empty row
local forRow = {}
-- On blank use, assume list's ended & break at end of this loop
forRow.use = args[i]
if not args[i] then terminated = true end
-- New empty list of pages
forRow.pages = {}
-- Insert first pages item if present
table.insert(forRow.pages, args[i + 1])
-- If the param after next is "and", do inner loop to collect params
-- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3}
while args[i + 2] == options.andKeyword do
if args[i + 3] then
table.insert(forRow.pages, args[i + 3])
end
-- Increment to next "and"
i = i + 2
end
-- Increment to next use
i = i + 2
-- Append the row
table.insert(forTable, forRow)
until terminated or i > maxArg
return forTable
end
-- Stringifies a table as formatted by forSeeArgsToTable
function p.forSeeTableToString (forSeeTable, options)
-- Type-checks and defaults
checkType("forSeeTableToString", 1, forSeeTable, "table", true)
checkType("forSeeTableToString", 2, options, "table", true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Stringify each for-see item into a list
local strList = {}
if forSeeTable then
for k, v in pairs(forSeeTable) do
local useStr = v.use or options.otherText
local pagesStr =
p.andList(v.pages, true) or
mFormatLink._formatLink{
categorizeMissing = mHatnote.missingTargetCat,
link = mHatnote.disambiguate(options.title)
}
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)
forSeeStr = punctuationCollapse(forSeeStr)
table.insert(strList, forSeeStr)
end
end
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'.')) end
-- Return the concatenated list
return table.concat(strList, ' ')
end
-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps
-- but not blank/whitespace values. Ignores named args and args < "from".
function p._forSee (args, from, options)
local forSeeTable = p.forSeeArgsToTable(args, from, options)
return p.forSeeTableToString(forSeeTable, options)
end
-- As _forSee, but uses the frame.
function p.forSee (frame, from, options)
mArguments = require('Module:Arguments')
return p._forSee(mArguments.getArgs(frame), from, options)
end
return p
3c31ivxc2t731ceyfvqcqlnp9acgg3s
Module:Icon
828
1045
9041
2026-01-30T06:27:05Z
en>Hike395
0
rm unneeded caching
9041
Scribunto
text/plain
-- This module implements [[Template:Icon]].
require("strict")
local yesNo = require("Module:Yesno")
local getArgs = require("Module:Arguments").getArgs
local p = {}
-- Determine whether we're being called from a sandbox
local sandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) and '/sandbox' or ''
-- Implements [[Template:Icon]]
-- Returns the icon image corresponding to a string (like 'B')
function p._main(args, data)
local data_module = 'Module:Icon/data'..sandbox
data = data or mw.loadData(data_module)
local code = args.class or args[1]
local iconData
if code then
code = code:match('^%s*(.-)%s*$'):lower() -- trim whitespace and put in lower case
iconData = data[code]
end
if not iconData then
iconData = data._DEFAULT
end
return string.format(
'[[File:%s%s%s|%s|class=noviewer|alt=%s]]',
iconData.image,
iconData.tooltip and '|' .. iconData.tooltip or '',
iconData.link == false and '|link=' or '',
args.size or '16x16px',
iconData.alt or ''
)
end
-- Implements [[Template:Icon link]], a superset of [[Template:Icon]]
-- Returns an icon, plus a suitably formatted wikilink
function p._link(args, data)
args.size = args.size or args.iconsize
local icon = p._main(args, data)
-- If no link given in args[2], default back to [[Template:Icon]]
if not args[2] then
return icon
end
-- Strip wiki markup out of link
local getPlain = require("Module:Text").Text().getPlain
local link = getPlain(args[2])
local display = args[3] or args[2]
-- italicize display string, if requested
if yesNo(args.i) or yesNo(args.italic) or yesNo(args.italics) then
display = '<i>'..display..'</i>'
end
-- if display is link, just use standard wlink
if link == display then
return '<span class="nowrap">'..icon..' </span>[['..link..']]'
end
return '<span class="nowrap">'..icon..' </span>[['..link..'|'..display..']]'
end
function p.main(frame)
local args = getArgs(frame,{parentFirst=true})
return p._main(args)
end
function p.link(frame)
local args = getArgs(frame,{parentFirst=true})
return p._link(args)
end
p[''] = function (frame) return p._main(frame.args) end
return p
7i1qzcjn891dcsvokxm98rcqxwkasz0
9042
9041
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Icon]]
9041
Scribunto
text/plain
-- This module implements [[Template:Icon]].
require("strict")
local yesNo = require("Module:Yesno")
local getArgs = require("Module:Arguments").getArgs
local p = {}
-- Determine whether we're being called from a sandbox
local sandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) and '/sandbox' or ''
-- Implements [[Template:Icon]]
-- Returns the icon image corresponding to a string (like 'B')
function p._main(args, data)
local data_module = 'Module:Icon/data'..sandbox
data = data or mw.loadData(data_module)
local code = args.class or args[1]
local iconData
if code then
code = code:match('^%s*(.-)%s*$'):lower() -- trim whitespace and put in lower case
iconData = data[code]
end
if not iconData then
iconData = data._DEFAULT
end
return string.format(
'[[File:%s%s%s|%s|class=noviewer|alt=%s]]',
iconData.image,
iconData.tooltip and '|' .. iconData.tooltip or '',
iconData.link == false and '|link=' or '',
args.size or '16x16px',
iconData.alt or ''
)
end
-- Implements [[Template:Icon link]], a superset of [[Template:Icon]]
-- Returns an icon, plus a suitably formatted wikilink
function p._link(args, data)
args.size = args.size or args.iconsize
local icon = p._main(args, data)
-- If no link given in args[2], default back to [[Template:Icon]]
if not args[2] then
return icon
end
-- Strip wiki markup out of link
local getPlain = require("Module:Text").Text().getPlain
local link = getPlain(args[2])
local display = args[3] or args[2]
-- italicize display string, if requested
if yesNo(args.i) or yesNo(args.italic) or yesNo(args.italics) then
display = '<i>'..display..'</i>'
end
-- if display is link, just use standard wlink
if link == display then
return '<span class="nowrap">'..icon..' </span>[['..link..']]'
end
return '<span class="nowrap">'..icon..' </span>[['..link..'|'..display..']]'
end
function p.main(frame)
local args = getArgs(frame,{parentFirst=true})
return p._main(args)
end
function p.link(frame)
local args = getArgs(frame,{parentFirst=true})
return p._link(args)
end
p[''] = function (frame) return p._main(frame.args) end
return p
7i1qzcjn891dcsvokxm98rcqxwkasz0
Module:Icon/data
828
1046
9043
2026-07-12T17:40:40Z
en>Reconrabbit
0
Replaced former featured list icon to match former featured article, also reflecting change to [[Module:Article history/config]]
9043
Scribunto
text/plain
-- This module stores icon data for [[Module:Icon]].
--------------------------------------------------------------------------------
-- Icon data
--------------------------------------------------------------------------------
local data = {
fa = {
image = "Featured article star.svg",
tooltip = "Featured article",
link = true,
},
far = {
image = "Cscr-star piece.png",
tooltip = "Featured article review",
link = true,
},
farc = {
image = "Cscr-star piece.png",
tooltip = "Featured article removal candidate",
link = true,
},
ffa = {
aliases = {"dfa"},
image = "Featured article star - cross.svg",
tooltip = "Former featured article",
link = true,
},
fac = {
aliases = {"fan"},
image = "Cscr-candidate.svg",
tooltip = "Featured article candidate",
link = true,
},
ffac = {
aliases = {"nofa"},
image = "Cscr-former.svg",
tooltip = "Former featured article candidate",
link = true,
},
fl = {
image = "Featured article star.svg",
tooltip = "Featured list",
link = true,
},
flrc = {
aliases = {"flr"},
image = "Cscr-star piece.png",
tooltip = "Featured list removal candidate",
link = true,
},
ffl = {
aliases = {"dfl"},
image = "Featured article star - cross.svg",
tooltip = "Former featured list",
link = true,
},
flc = {
aliases = {"fln"},
image = "Cscr-candidate.svg",
tooltip = "Featured list candidate",
link = true,
},
fflc = {
aliases = {"nofl"},
image = "Cscr-former.svg",
tooltip = "Former featured list candidate",
link = true,
},
a = {
image = "Symbol a class.svg",
tooltip = "A-Class article",
link = true,
},
admin = {
aliases = {"mop"},
image = "Wikipedia Administrator.svg",
tooltip = "Administrator",
link = true,
},
dac = {
aliases = {"daa"},
image = "Symbol unsupport A vote.svg",
tooltip = "Demoted A-Class article",
link = true,
},
acc = {
aliases = {"acn", "aac"},
image = "A candidate.svg",
tooltip = "A-Class article candidate",
link = true,
},
noac = {
aliases = {"faac"},
image = "Symbol unsupport A vote.svg",
tooltip = "Failed A-Class article candidate",
link = true,
},
ga = {
image = "Symbol support vote.svg",
tooltip = "Good article",
link = false,
},
gar = {
image = "GA Candidate Neutral vote(ChaosNil).svg",
tooltip = "Good article reassessment",
link = false,
},
dga = {
image = "Symbol unsupport vote.svg",
tooltip = "Delisted good article",
link = false,
},
gan = {
aliases = {"gac"},
image = "GA candidate.svg",
tooltip = "Good article nominee",
link = false,
},
ga2 = {
image = "Symbol neutral vote.svg",
tooltip = "Good article, 2nd opinion",
link = false,
},
gah = {
image = "Symbol wait.svg",
tooltip = "Good article on hold",
link = false,
},
fgan = {
aliases = {"noga", "gaf", "gf"},
image = "Symbol oppose vote.svg",
tooltip = "Former good article nominee",
link = false,
},
fp = {
image = "Cscr-featured.svg",
tooltip = "Featured picture",
link = true,
},
fpc = {
aliases = {"fpn"},
image = "Cscr-candidate.svg",
tooltip = "Featured picture candidate",
link = true,
},
ffp = {
image = "Cscr-former.svg",
tooltip = "Former featured picture",
link = true,
},
vp = {
image = "ENWP VP Logo.svg",
tooltip = "Valued picture",
link = true,
},
vpc = {
image = "Valued pics 1.svg",
tooltip = "Valued picture candidate",
link = true,
},
fs = {
image = "Cscr-featured.svg",
tooltip = "Featured sound",
link = true,
},
ffs = {
image = "Cscr-former.svg",
tooltip = "Former featured sound",
link = true,
},
fsc = {
image = "Cscr-candidate.svg",
tooltip = "Featured sound candidate",
link = true,
},
fpo = {
image = "Linecons big-star.svg",
tooltip = "Before the featured portal process ceased in 2017, this had been designated as a featured portal.",
link = true,
},
fpor = {
image = "Cscr-star piece.png",
tooltip = "Featured portal review",
link = true,
},
ffpo = {
image = "Featured article star - cross.svg",
tooltip = "Former featured portal",
link = true,
},
fpoc = {
image = "Cscr-candidate.svg",
tooltip = "Featured portal candidate",
link = true,
},
ft = {
image = "Cscr-featuredtopic.svg",
tooltip = "Featured topic",
link = true,
},
ftrc = {
image = "Cscr-star piece.png",
tooltip = "Featured topic removal candidate",
link = true,
},
fft = {
aliases = {"dft"},
image = "DFT candidate_cluster.svg",
tooltip = "Former featured topic",
link = true,
},
ftc = {
aliases = {"ftn"},
image = "FT candidate cluster.svg",
tooltip = "Featured topic candidate",
link = false,
},
gt = {
image = "Support cluster.svg",
tooltip = "Good topic",
link = false,
},
gtrc = {
image = "Symbol unsupport vote.svg",
tooltip = "Good topic removal candidate",
link = false,
},
gtc = {
aliases = {"gtn"},
image = "GA candidate cluster.svg",
tooltip = "Good topic candidate",
link = false,
},
bplus = {
aliases = {"b+"},
image = "Symbol bplus class.svg",
tooltip = "Bplus-Class article",
link = true,
},
b = {
image = "Symbol b class.svg",
tooltip = "B-Class article",
link = true,
},
br = {
aliases = {"bcr"},
image = "Bclass-checklist.svg",
tooltip = "B-Class review",
link = true,
},
c = {
image = "Symbol c class.svg",
tooltip = "C-Class article",
link = true,
},
start = {
image = "Symbol start class.svg",
tooltip = "Start-Class article",
link = true,
},
stub = {
image = "Symbol stub class.svg",
tooltip = "Stub-Class article",
link = true,
},
list = {
aliases = {"comparison"},
image = "Symbol list class.svg",
tooltip = "List-Class article",
link = false,
},
no = {
image = "Crystal button cancel.svg",
tooltip = "Unknown-Class article",
link = true,
},
book = {
image = "Symbol book class2.svg",
tooltip = "Wikipedia book",
link = true,
},
category = {
aliases = {"cat", "categ"},
image = "Symbol category class.svg",
tooltip = "Category",
link = false,
},
disambiguation = {
aliases = {"dab", "disamb", "disambig"},
image = "Symbol dab class.svg",
tooltip = "Disambiguation page",
link = true,
},
image = {
aliases = {"file"},
image = "Symbol file class.svg",
tooltip = "File",
link = true,
},
needed = {
image = "Symbol needed class.svg",
tooltip = "Needed article",
link = false,
},
outline = {
image = "Global thinking.svg",
tooltip = "Outline",
link = false,
},
portal = {
image = "Symbol portal class.svg",
tooltip = "Portal",
link = true,
},
project = {
image = "Symbol project class.svg",
tooltip = "Project page",
link = false,
},
redirect = {
aliases = {"red", "redir"},
image = "Symbol redirect vote2.svg",
tooltip = "Redirect",
link = true,
},
template = {
aliases = {"temp", "templ"},
image = "Symbol template class pink.svg",
tooltip = "Template",
link = false,
},
essay = {
image = "Essay.svg",
tooltip = "Essay",
link = false,
},
na = {
image = "Symbol na class.svg",
tooltip = "Non-article page",
link = true,
},
aa = {
image = "Yes check.svg",
tooltip = "Audited article of limited subject matter",
link = false,
},
da = {
image = "Symbol oppose vote.svg",
tooltip = "Demoted article",
link = false,
},
dyk = {
image = "Symbol question.svg",
tooltip = "Did You Know?",
link = false,
},
dyk2 = {
image = "DYK questionmark icon.svg",
tooltip = "Did You Know?",
link = false,
},
pr = {
image = "Nuvola apps kedit.png",
tooltip = "Peer review",
link = true,
},
ppr = {
image = "Nuvola apps kedit.png",
tooltip = "Portal peer review",
link = true,
},
q = {
aliases = {"question"},
image = "Symbol question.svg",
tooltip = "Question",
link = false,
},
cleanup = {
image = "Edit-clear.svg",
tooltip = "Cleanup work",
link = false,
},
qi = {
image = "Quality images logo.svg",
tooltip = "Quality image on Wikimedia Commons",
link = false,
},
vi = {
image = "Valued image seal.svg",
tooltip = "Valued image on Wikimedia Commons",
link = false,
},
tfa = {
image = "Wikipedia-logo.svg",
tooltip = "Today's Featured Article",
link = true,
},
tfl = {
image = "Wikipedia-logo.svg",
tooltip = "Today's Featured List",
link = true,
},
itn = {
image = "Globe current.svg",
tooltip = "In The News",
link = true,
},
otd = {
image = "Nuvola apps date.svg",
tooltip = "On This Day",
link = true,
},
wikiproject = {
image = "People icon.svg",
tooltip = "WikiProject",
link = false,
},
goce = {
image = "Writing Magnifying.PNG",
tooltip = "Guild of Copy Editors",
link = true,
},
wikipedia = {
image = "Wikipedia-logo.svg",
tooltip = "Wikipedia page",
link = true,
},
commons = {
image = "Commons-logo.svg",
tooltip = "Commons page",
link = true,
},
wikiquote = {
image = "Wikiquote-logo.svg",
tooltip = "Wikiquote page",
link = false,
},
wikiversity = {
image = "Wikiversity logo 2017.svg",
tooltip = "Wikiversity page",
link = true,
},
wikibooks = {
image = "Wikibooks-logo.svg",
tooltip = "Wikibooks page",
link = true,
},
wikisource = {
image = "Wikisource-logo.svg",
tooltip = "Wikisource page",
link = true,
},
wiktionary = {
image = "Wiktionary-logo.svg",
tooltip = "Wiktionary page",
link = true,
},
wikinews = {
image = "Wikinews-logo.svg",
tooltip = "Wikinews page",
link = true,
},
wikispecies = {
image = "Wikispecies-logo.svg",
tooltip = "Wikispecies page",
link = true,
},
wikidata = {
image = "Wikidata-logo.svg",
tooltip = "Wikidata page",
link = false,
},
wikivoyage = {
image = "Wikivoyage-logo.svg",
tooltip = "Wikivoyage page",
link = true,
},
mediawiki = {
image = "MediaWiki-2020-icon.svg",
tooltip = "MediaWiki",
link = true,
},
phabricator = {
aliases = {"phab"},
image = "Favicon-Phabricator-WM.svg",
tooltip = "Phabricator",
link = false,
},
wikitech = {
image = "Wikitech-2021-blue-icon.svg",
tooltip = "Wikitech",
link = true,
},
meta = {
image = "Wikimedia Community Logo.svg",
tooltip = "Meta-wiki page",
link = false,
},
four = {
aliases = {"4a"},
image = "Four Award with draft icon.svg",
tooltip = "Four Award",
link = false,
},
million = {
image = "Million award logo.svg",
tooltip = "Million Award",
link = true,
},
module = {
image = "Lua-logo-nolabel.svg",
tooltip = "Module",
link = false,
},
vital = {
image = "Círculos_Concéntricos.svg",
tooltip = "Vital article",
link = false,
},
potd = {
image = "Wikipedia-logo.svg",
tooltip = "Picture of the Day",
link = true,
},
draft = {
image = "Symbol draft class.svg",
tooltip = "Draft-Class article",
link = true,
},
user = {
image = "Symbol user class.svg",
tooltip = "User-Class article",
link = true,
},
info = {
image = "Information icon.svg",
tooltip = "Information",
link = false,
},
discussionnotificaion = {
image = "Echo edit-user-talk icon.svg",
tooltip = "Discussion",
link = true,
},
alert = {
image = "OOjs UI icon alert.svg",
tooltip = "Black alert",
link = true,
},
['alert-imagewarning'] = {
image = "OOjs UI icon alert image warning.svg",
tooltip = "Alert",
link = true,
},
['alert-constructive'] = {
image = "OOjs UI icon alert-constructive.svg",
tooltip = "Green alert",
link = true,
},
['alert-blackred'] = {
image = "OOjs UI icon alert destructive black-darkred.svg",
tooltip = "Black, white, and red alert",
link = true,
},
barnstar2 = {
image = "Original Barnstar Hires.svg",
tooltip = "Original barnstar hires",
link = false,
},
barnstar = {
image = "Original Barnstar.png",
tooltip = "Original barnstar",
link = false,
},
gareview = {
aliases = {"ganrv"},
image = "Good article review icon.svg",
tooltip = "Good article review",
link = false,
},
new = {
aliases = {"stork"},
image = "Symbol Stork.svg",
tooltip = "New",
link = true
},
_DEFAULT = {
image = "Symbol question.svg",
link = false,
}
}
--------------------------------------------------------------------------------
-- End icon data
--------------------------------------------------------------------------------
-- Make aliases work the same as normal keys, and remove the "aliases" subtables.
local ret= {}
for code, iconData in pairs(data) do
iconData.canonicalCode = code
if iconData.aliases then
for _, alias in ipairs(iconData.aliases) do
ret[alias] = iconData
end
iconData.aliases = nil
end
ret[code] = iconData
end
return ret
orhqy6iez91aq2a26989x2hpsd451lm
9044
9043
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Icon/data]]
9043
Scribunto
text/plain
-- This module stores icon data for [[Module:Icon]].
--------------------------------------------------------------------------------
-- Icon data
--------------------------------------------------------------------------------
local data = {
fa = {
image = "Featured article star.svg",
tooltip = "Featured article",
link = true,
},
far = {
image = "Cscr-star piece.png",
tooltip = "Featured article review",
link = true,
},
farc = {
image = "Cscr-star piece.png",
tooltip = "Featured article removal candidate",
link = true,
},
ffa = {
aliases = {"dfa"},
image = "Featured article star - cross.svg",
tooltip = "Former featured article",
link = true,
},
fac = {
aliases = {"fan"},
image = "Cscr-candidate.svg",
tooltip = "Featured article candidate",
link = true,
},
ffac = {
aliases = {"nofa"},
image = "Cscr-former.svg",
tooltip = "Former featured article candidate",
link = true,
},
fl = {
image = "Featured article star.svg",
tooltip = "Featured list",
link = true,
},
flrc = {
aliases = {"flr"},
image = "Cscr-star piece.png",
tooltip = "Featured list removal candidate",
link = true,
},
ffl = {
aliases = {"dfl"},
image = "Featured article star - cross.svg",
tooltip = "Former featured list",
link = true,
},
flc = {
aliases = {"fln"},
image = "Cscr-candidate.svg",
tooltip = "Featured list candidate",
link = true,
},
fflc = {
aliases = {"nofl"},
image = "Cscr-former.svg",
tooltip = "Former featured list candidate",
link = true,
},
a = {
image = "Symbol a class.svg",
tooltip = "A-Class article",
link = true,
},
admin = {
aliases = {"mop"},
image = "Wikipedia Administrator.svg",
tooltip = "Administrator",
link = true,
},
dac = {
aliases = {"daa"},
image = "Symbol unsupport A vote.svg",
tooltip = "Demoted A-Class article",
link = true,
},
acc = {
aliases = {"acn", "aac"},
image = "A candidate.svg",
tooltip = "A-Class article candidate",
link = true,
},
noac = {
aliases = {"faac"},
image = "Symbol unsupport A vote.svg",
tooltip = "Failed A-Class article candidate",
link = true,
},
ga = {
image = "Symbol support vote.svg",
tooltip = "Good article",
link = false,
},
gar = {
image = "GA Candidate Neutral vote(ChaosNil).svg",
tooltip = "Good article reassessment",
link = false,
},
dga = {
image = "Symbol unsupport vote.svg",
tooltip = "Delisted good article",
link = false,
},
gan = {
aliases = {"gac"},
image = "GA candidate.svg",
tooltip = "Good article nominee",
link = false,
},
ga2 = {
image = "Symbol neutral vote.svg",
tooltip = "Good article, 2nd opinion",
link = false,
},
gah = {
image = "Symbol wait.svg",
tooltip = "Good article on hold",
link = false,
},
fgan = {
aliases = {"noga", "gaf", "gf"},
image = "Symbol oppose vote.svg",
tooltip = "Former good article nominee",
link = false,
},
fp = {
image = "Cscr-featured.svg",
tooltip = "Featured picture",
link = true,
},
fpc = {
aliases = {"fpn"},
image = "Cscr-candidate.svg",
tooltip = "Featured picture candidate",
link = true,
},
ffp = {
image = "Cscr-former.svg",
tooltip = "Former featured picture",
link = true,
},
vp = {
image = "ENWP VP Logo.svg",
tooltip = "Valued picture",
link = true,
},
vpc = {
image = "Valued pics 1.svg",
tooltip = "Valued picture candidate",
link = true,
},
fs = {
image = "Cscr-featured.svg",
tooltip = "Featured sound",
link = true,
},
ffs = {
image = "Cscr-former.svg",
tooltip = "Former featured sound",
link = true,
},
fsc = {
image = "Cscr-candidate.svg",
tooltip = "Featured sound candidate",
link = true,
},
fpo = {
image = "Linecons big-star.svg",
tooltip = "Before the featured portal process ceased in 2017, this had been designated as a featured portal.",
link = true,
},
fpor = {
image = "Cscr-star piece.png",
tooltip = "Featured portal review",
link = true,
},
ffpo = {
image = "Featured article star - cross.svg",
tooltip = "Former featured portal",
link = true,
},
fpoc = {
image = "Cscr-candidate.svg",
tooltip = "Featured portal candidate",
link = true,
},
ft = {
image = "Cscr-featuredtopic.svg",
tooltip = "Featured topic",
link = true,
},
ftrc = {
image = "Cscr-star piece.png",
tooltip = "Featured topic removal candidate",
link = true,
},
fft = {
aliases = {"dft"},
image = "DFT candidate_cluster.svg",
tooltip = "Former featured topic",
link = true,
},
ftc = {
aliases = {"ftn"},
image = "FT candidate cluster.svg",
tooltip = "Featured topic candidate",
link = false,
},
gt = {
image = "Support cluster.svg",
tooltip = "Good topic",
link = false,
},
gtrc = {
image = "Symbol unsupport vote.svg",
tooltip = "Good topic removal candidate",
link = false,
},
gtc = {
aliases = {"gtn"},
image = "GA candidate cluster.svg",
tooltip = "Good topic candidate",
link = false,
},
bplus = {
aliases = {"b+"},
image = "Symbol bplus class.svg",
tooltip = "Bplus-Class article",
link = true,
},
b = {
image = "Symbol b class.svg",
tooltip = "B-Class article",
link = true,
},
br = {
aliases = {"bcr"},
image = "Bclass-checklist.svg",
tooltip = "B-Class review",
link = true,
},
c = {
image = "Symbol c class.svg",
tooltip = "C-Class article",
link = true,
},
start = {
image = "Symbol start class.svg",
tooltip = "Start-Class article",
link = true,
},
stub = {
image = "Symbol stub class.svg",
tooltip = "Stub-Class article",
link = true,
},
list = {
aliases = {"comparison"},
image = "Symbol list class.svg",
tooltip = "List-Class article",
link = false,
},
no = {
image = "Crystal button cancel.svg",
tooltip = "Unknown-Class article",
link = true,
},
book = {
image = "Symbol book class2.svg",
tooltip = "Wikipedia book",
link = true,
},
category = {
aliases = {"cat", "categ"},
image = "Symbol category class.svg",
tooltip = "Category",
link = false,
},
disambiguation = {
aliases = {"dab", "disamb", "disambig"},
image = "Symbol dab class.svg",
tooltip = "Disambiguation page",
link = true,
},
image = {
aliases = {"file"},
image = "Symbol file class.svg",
tooltip = "File",
link = true,
},
needed = {
image = "Symbol needed class.svg",
tooltip = "Needed article",
link = false,
},
outline = {
image = "Global thinking.svg",
tooltip = "Outline",
link = false,
},
portal = {
image = "Symbol portal class.svg",
tooltip = "Portal",
link = true,
},
project = {
image = "Symbol project class.svg",
tooltip = "Project page",
link = false,
},
redirect = {
aliases = {"red", "redir"},
image = "Symbol redirect vote2.svg",
tooltip = "Redirect",
link = true,
},
template = {
aliases = {"temp", "templ"},
image = "Symbol template class pink.svg",
tooltip = "Template",
link = false,
},
essay = {
image = "Essay.svg",
tooltip = "Essay",
link = false,
},
na = {
image = "Symbol na class.svg",
tooltip = "Non-article page",
link = true,
},
aa = {
image = "Yes check.svg",
tooltip = "Audited article of limited subject matter",
link = false,
},
da = {
image = "Symbol oppose vote.svg",
tooltip = "Demoted article",
link = false,
},
dyk = {
image = "Symbol question.svg",
tooltip = "Did You Know?",
link = false,
},
dyk2 = {
image = "DYK questionmark icon.svg",
tooltip = "Did You Know?",
link = false,
},
pr = {
image = "Nuvola apps kedit.png",
tooltip = "Peer review",
link = true,
},
ppr = {
image = "Nuvola apps kedit.png",
tooltip = "Portal peer review",
link = true,
},
q = {
aliases = {"question"},
image = "Symbol question.svg",
tooltip = "Question",
link = false,
},
cleanup = {
image = "Edit-clear.svg",
tooltip = "Cleanup work",
link = false,
},
qi = {
image = "Quality images logo.svg",
tooltip = "Quality image on Wikimedia Commons",
link = false,
},
vi = {
image = "Valued image seal.svg",
tooltip = "Valued image on Wikimedia Commons",
link = false,
},
tfa = {
image = "Wikipedia-logo.svg",
tooltip = "Today's Featured Article",
link = true,
},
tfl = {
image = "Wikipedia-logo.svg",
tooltip = "Today's Featured List",
link = true,
},
itn = {
image = "Globe current.svg",
tooltip = "In The News",
link = true,
},
otd = {
image = "Nuvola apps date.svg",
tooltip = "On This Day",
link = true,
},
wikiproject = {
image = "People icon.svg",
tooltip = "WikiProject",
link = false,
},
goce = {
image = "Writing Magnifying.PNG",
tooltip = "Guild of Copy Editors",
link = true,
},
wikipedia = {
image = "Wikipedia-logo.svg",
tooltip = "Wikipedia page",
link = true,
},
commons = {
image = "Commons-logo.svg",
tooltip = "Commons page",
link = true,
},
wikiquote = {
image = "Wikiquote-logo.svg",
tooltip = "Wikiquote page",
link = false,
},
wikiversity = {
image = "Wikiversity logo 2017.svg",
tooltip = "Wikiversity page",
link = true,
},
wikibooks = {
image = "Wikibooks-logo.svg",
tooltip = "Wikibooks page",
link = true,
},
wikisource = {
image = "Wikisource-logo.svg",
tooltip = "Wikisource page",
link = true,
},
wiktionary = {
image = "Wiktionary-logo.svg",
tooltip = "Wiktionary page",
link = true,
},
wikinews = {
image = "Wikinews-logo.svg",
tooltip = "Wikinews page",
link = true,
},
wikispecies = {
image = "Wikispecies-logo.svg",
tooltip = "Wikispecies page",
link = true,
},
wikidata = {
image = "Wikidata-logo.svg",
tooltip = "Wikidata page",
link = false,
},
wikivoyage = {
image = "Wikivoyage-logo.svg",
tooltip = "Wikivoyage page",
link = true,
},
mediawiki = {
image = "MediaWiki-2020-icon.svg",
tooltip = "MediaWiki",
link = true,
},
phabricator = {
aliases = {"phab"},
image = "Favicon-Phabricator-WM.svg",
tooltip = "Phabricator",
link = false,
},
wikitech = {
image = "Wikitech-2021-blue-icon.svg",
tooltip = "Wikitech",
link = true,
},
meta = {
image = "Wikimedia Community Logo.svg",
tooltip = "Meta-wiki page",
link = false,
},
four = {
aliases = {"4a"},
image = "Four Award with draft icon.svg",
tooltip = "Four Award",
link = false,
},
million = {
image = "Million award logo.svg",
tooltip = "Million Award",
link = true,
},
module = {
image = "Lua-logo-nolabel.svg",
tooltip = "Module",
link = false,
},
vital = {
image = "Círculos_Concéntricos.svg",
tooltip = "Vital article",
link = false,
},
potd = {
image = "Wikipedia-logo.svg",
tooltip = "Picture of the Day",
link = true,
},
draft = {
image = "Symbol draft class.svg",
tooltip = "Draft-Class article",
link = true,
},
user = {
image = "Symbol user class.svg",
tooltip = "User-Class article",
link = true,
},
info = {
image = "Information icon.svg",
tooltip = "Information",
link = false,
},
discussionnotificaion = {
image = "Echo edit-user-talk icon.svg",
tooltip = "Discussion",
link = true,
},
alert = {
image = "OOjs UI icon alert.svg",
tooltip = "Black alert",
link = true,
},
['alert-imagewarning'] = {
image = "OOjs UI icon alert image warning.svg",
tooltip = "Alert",
link = true,
},
['alert-constructive'] = {
image = "OOjs UI icon alert-constructive.svg",
tooltip = "Green alert",
link = true,
},
['alert-blackred'] = {
image = "OOjs UI icon alert destructive black-darkred.svg",
tooltip = "Black, white, and red alert",
link = true,
},
barnstar2 = {
image = "Original Barnstar Hires.svg",
tooltip = "Original barnstar hires",
link = false,
},
barnstar = {
image = "Original Barnstar.png",
tooltip = "Original barnstar",
link = false,
},
gareview = {
aliases = {"ganrv"},
image = "Good article review icon.svg",
tooltip = "Good article review",
link = false,
},
new = {
aliases = {"stork"},
image = "Symbol Stork.svg",
tooltip = "New",
link = true
},
_DEFAULT = {
image = "Symbol question.svg",
link = false,
}
}
--------------------------------------------------------------------------------
-- End icon data
--------------------------------------------------------------------------------
-- Make aliases work the same as normal keys, and remove the "aliases" subtables.
local ret= {}
for code, iconData in pairs(data) do
iconData.canonicalCode = code
if iconData.aliases then
for _, alias in ipairs(iconData.aliases) do
ret[alias] = iconData
end
iconData.aliases = nil
end
ret[code] = iconData
end
return ret
orhqy6iez91aq2a26989x2hpsd451lm
Module:Navbox
828
1047
9045
2026-02-24T17:16:57Z
en>Epicgenius
0
Undoing changes for now - this is causing errors, per [[Special:PermanentLink/1340234983#Navbox:American Revolutionary War...]]
9045
Scribunto
text/plain
require('strict')
local p = {}
local cfg = mw.loadData('Module:Navbox/configuration')
local inArray = require("Module:TableTools").inArray
local getArgs -- lazily initialized
local hiding_templatestyles = {}
-- global passthrough variables
local passthrough = {
[cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true,
[cfg.arg.basestyle]=true,
[cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true,
[cfg.arg.bodyclass]=true,
[cfg.arg.groupclass]=true,
[cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true,
[cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true,
[cfg.arg.listclass]=true,
[cfg.arg.name]=true,
[cfg.arg.navbar]=true,
[cfg.arg.state]=true,
[cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true,
argHash=true
}
-- helper functions
local andnum = function(s, n) return string.format(cfg.arg[s .. '_and_num'], n) end
local isblank = function(v) return (v or '') == '' end
local function concatstrings(s)
local r = table.concat(s, '')
if r:match('^%s*$') then return nil end
return r
end
local function concatstyles(s)
local r = ''
for _, v in ipairs(s) do
v = mw.text.trim(v, "%s;")
if not isblank(v) then r = r .. v .. ';' end
end
if isblank(r) then return nil end
return r
end
local function getSubgroup(args, listnum, listText, prefix)
local subArgs = {
[cfg.arg.border] = cfg.keyword.border_subgroup,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
argHash = 0
}
local hasSubArgs = false
local subgroups_and_num = prefix and {prefix} or cfg.arg.subgroups_and_num
for k, v in pairs(args) do
k = tostring(k)
for _, w in ipairs(subgroups_and_num) do
w = string.format(w, listnum) .. "_"
if (#k > #w) and (k:sub(1, #w) == w) then
subArgs[k:sub(#w + 1)] = v
hasSubArgs = true
subArgs.argHash = subArgs.argHash + (v and #v or 0)
end
end
end
return hasSubArgs and p._navbox(subArgs) or listText
end
-- Main functions
function p._navbox(args)
if args.type == cfg.keyword.with_collapsible_groups then
return p._withCollapsibleGroups(args)
elseif args.type == cfg.keyword.with_columns then
return p._withColumns(args)
end
local function striped(wikitext, border)
-- Return wikitext with markers replaced for odd/even striping.
-- Child (subgroup) navboxes are flagged with a category that is removed
-- by parent navboxes. The result is that the category shows all pages
-- where a child navbox is not contained in a parent navbox.
local orphanCat = cfg.category.orphan
if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then
-- No change; striping occurs in outermost navbox.
return wikitext .. orphanCat
end
local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part
if args[cfg.arg.evenodd] then
if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then
first, second = second, first
else
first = args[cfg.arg.evenodd]
second = first
end
end
local changer
if first == second then
changer = first
else
local index = 0
changer = function (code)
if code == '0' then
-- Current occurrence is for a group before a nested table.
-- Set it to first as a valid although pointless class.
-- The next occurrence will be the first row after a title
-- in a subgroup and will also be first.
index = 0
return first
end
index = index + 1
return index % 2 == 1 and first or second
end
end
local regex = orphanCat:gsub('([%[%]])', '%%%1')
return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count
end
local function processItem(item, nowrapitems)
if item:sub(1, 2) == '{|' then
-- Applying nowrap to lines in a table does not make sense.
-- Add newlines to compensate for trim of x in |parm=x in a template.
return '\n' .. item .. '\n'
end
if nowrapitems == cfg.keyword.nowrapitems_yes then
local lines = {}
for line in (item .. '\n'):gmatch('([^\n]*)\n') do
local prefix, content = line:match('^([*:;#]+)%s*(.*)')
if prefix and not content:match(cfg.pattern.nowrap) then
line = string.format(cfg.nowrap_item, prefix, content)
end
table.insert(lines, line)
end
item = table.concat(lines, '\n')
end
if item:match('^[*:;#]') then
return '\n' .. item .. '\n'
end
return item
end
local function has_navbar()
return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off
and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain
and (
args[cfg.arg.name]
or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '')
~= cfg.pattern.navbox
)
end
-- extract text color from css, which is the only permitted inline CSS for the navbar
local function extract_color(css_str)
-- return nil because navbar takes its argument into mw.html which handles
-- nil gracefully, removing the associated style attribute
return mw.ustring.match(';' .. css_str .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil
end
local function renderNavBar(titleCell)
if has_navbar() then
local navbar = require('Module:Navbar')._navbar
titleCell:wikitext(navbar{
[cfg.navbar.name] = args[cfg.arg.name],
[cfg.navbar.mini] = 1,
[cfg.navbar.fontstyle] = extract_color(
(args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '')
)
})
end
end
local function renderTitleRow(tbl)
if not args[cfg.arg.title] then return end
local titleRow = tbl:tag('tr')
local titleCell = titleRow:tag('th'):attr('scope', 'col')
local titleColspan = 2
if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end
if args[cfg.arg.image] then titleColspan = titleColspan + 1 end
titleCell
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.titlestyle])
:addClass(cfg.class.navbox_title)
:attr('colspan', titleColspan)
renderNavBar(titleCell)
titleCell
:tag('div')
-- id for aria-labelledby attribute
:attr('id', mw.uri.anchorEncode(args[cfg.arg.title]) .. args.argHash)
:addClass(args[cfg.arg.titleclass])
:css('font-size', '114%')
:css('margin', '0 4em')
:wikitext(processItem(args[cfg.arg.title]))
end
local function getAboveBelowColspan()
local ret = 2
if args[cfg.arg.imageleft] then ret = ret + 1 end
if args[cfg.arg.image] then ret = ret + 1 end
return ret
end
local function renderAboveRow(tbl)
if not args[cfg.arg.above] then return end
tbl:tag('tr')
:tag('td')
:addClass(cfg.class.navbox_abovebelow)
:addClass(args[cfg.arg.aboveclass])
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.abovestyle])
:attr('colspan', getAboveBelowColspan())
:tag('div')
-- id for aria-labelledby attribute, if no title
:attr('id', (not args[cfg.arg.title]) and
(mw.uri.anchorEncode(args[cfg.arg.above]) .. args.argHash)
or nil)
:wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems]))
end
local function renderBelowRow(tbl)
if not args[cfg.arg.below] then return end
tbl:tag('tr')
:tag('td')
:addClass(cfg.class.navbox_abovebelow)
:addClass(args[cfg.arg.belowclass])
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.belowstyle])
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems]))
end
local function renderListRow(tbl, index, listnum, listnums_size)
local row = tbl:tag('tr')
if index == 1 and args[cfg.arg.imageleft] then
row
:tag('td')
:addClass(cfg.class.noviewer)
:addClass(cfg.class.navbox_image)
:addClass(args[cfg.arg.imageclass])
:css('width', '1px') -- Minimize width
:css('padding', '0 2px 0 0')
:cssText(args[cfg.arg.imageleftstyle])
:attr('rowspan', listnums_size)
:tag('div')
:wikitext(processItem(args[cfg.arg.imageleft]))
end
local group_and_num = andnum('group', listnum)
local groupstyle_and_num = andnum('groupstyle', listnum)
if args[group_and_num] then
local groupCell = row:tag('th')
-- id for aria-labelledby attribute, if lone group with no title or above
if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then
groupCell
:attr('id', mw.uri.anchorEncode(args[cfg.arg.group1]) .. args.argHash)
end
groupCell
:attr('scope', 'row')
:addClass(cfg.class.navbox_group)
:addClass(args[cfg.arg.groupclass])
:cssText(args[cfg.arg.basestyle])
-- If groupwidth not specified, minimize width
:css('width', args[cfg.arg.groupwidth] or '1%')
groupCell
:cssText(args[cfg.arg.groupstyle])
:cssText(args[groupstyle_and_num])
:wikitext(args[group_and_num])
end
local listCell = row:tag('td')
if args[group_and_num] then
listCell
:addClass(cfg.class.navbox_list_with_group)
else
listCell:attr('colspan', 2)
end
if not args[cfg.arg.groupwidth] then
listCell:css('width', '100%')
end
local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing
if index % 2 == 1 then
rowstyle = args[cfg.arg.oddstyle]
else
rowstyle = args[cfg.arg.evenstyle]
end
local list_and_num = andnum('list', listnum)
local listText = inArray(cfg.keyword.subgroups, args[list_and_num])
and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num]
local oddEven = cfg.marker.oddeven
if listText:sub(1, 12) == '</div><table' then
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part
end
local liststyle_and_num = andnum('liststyle', listnum)
local listclass_and_num = andnum('listclass', listnum)
listCell
:css('padding', '0')
:cssText(args[cfg.arg.liststyle])
:cssText(rowstyle)
:cssText(args[liststyle_and_num])
:addClass(cfg.class.navbox_list)
:addClass(cfg.class.navbox_part .. oddEven)
:addClass(args[cfg.arg.listclass])
:addClass(args[listclass_and_num])
:tag('div')
:css('padding',
(index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em'
)
:wikitext(processItem(listText, args[cfg.arg.nowrapitems]))
if index == 1 and args[cfg.arg.image] then
row
:tag('td')
:addClass(cfg.class.noviewer)
:addClass(cfg.class.navbox_image)
:addClass(args[cfg.arg.imageclass])
:css('width', '1px') -- Minimize width
:css('padding', '0 0 0 2px')
:cssText(args[cfg.arg.imagestyle])
:attr('rowspan', listnums_size)
:tag('div')
:wikitext(processItem(args[cfg.arg.image]))
end
end
local function has_list_class(htmlclass)
local patterns = {
'^' .. htmlclass .. '$',
'%s' .. htmlclass .. '$',
'^' .. htmlclass .. '%s',
'%s' .. htmlclass .. '%s'
}
for arg, _ in pairs(args) do
if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then
for _, pattern in ipairs(patterns) do
if mw.ustring.find(args[arg] or '', pattern) then
return true
end
end
end
end
return false
end
-- there are a lot of list classes in the wild, so we add their TemplateStyles
local function add_list_styles()
local frame = mw.getCurrentFrame()
local function add_list_templatestyles(htmlclass, templatestyles)
if has_list_class(htmlclass) then
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
else
return ''
end
end
local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles)
local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles)
-- a second workaround for [[phab:T303378]]
-- when that issue is fixed, we can actually use has_navbar not to emit the
-- tag here if we want
if has_navbar() and hlist_styles == '' then
hlist_styles = frame:extensionTag{
name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
}
end
-- hlist -> plainlist is best-effort to preserve old Common.css ordering.
-- this ordering is not a guarantee because most navboxes will emit only
-- one of these classes [hlist_note]
return hlist_styles .. plainlist_styles
end
local function needsHorizontalLists(border)
if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then
return false
end
return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist)
end
local function hasBackgroundColors()
for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle,
cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do
if tostring(args[key]):find('background', 1, true) then
return true
end
end
return false
end
local function hasBorders()
for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle,
cfg.arg.abovestyle, cfg.arg.belowstyle}) do
if tostring(args[key]):find('border', 1, true) then
return true
end
end
return false
end
local function isIllegible()
local styleratio = require('Module:Color contrast')._styleratio
for key, style in pairs(args) do
if tostring(key):match(cfg.pattern.style) then
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
return true
end
end
end
return false
end
local function getTrackingCategories(border)
local cats = {}
if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end
if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end
if isIllegible() then table.insert(cats, cfg.category.illegible) end
if hasBorders() then table.insert(cats, cfg.category.borders) end
return cats
end
local function renderTrackingCategories(builder, border)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 10 then return end -- not in template space
local subpage = title.subpageText
if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox
or subpage == cfg.keyword.subpage_testcases then return end
for _, cat in ipairs(getTrackingCategories(border)) do
builder:wikitext('[[Category:' .. cat .. ']]')
end
end
local function renderMainTable(border, listnums)
local tbl = mw.html.create('table')
:addClass(cfg.class.nowraplinks)
:addClass(args[cfg.arg.bodyclass])
local state = args[cfg.arg.state]
if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then
if state == cfg.keyword.state_collapsed then
state = cfg.class.collapsed
end
tbl
:addClass(cfg.class.collapsible)
:addClass(state or cfg.class.autocollapse)
end
tbl:css('border-spacing', 0)
if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then
tbl
:addClass(cfg.class.navbox_subgroup)
:cssText(args[cfg.arg.bodystyle])
:cssText(args[cfg.arg.style])
else -- regular navbox - bodystyle and style will be applied to the wrapper table
tbl
:addClass(cfg.class.navbox_inner)
:css('background', 'transparent')
:css('color', 'inherit')
end
tbl:cssText(args[cfg.arg.innerstyle])
renderTitleRow(tbl)
renderAboveRow(tbl)
local listnums_size = #listnums
for i, listnum in ipairs(listnums) do
renderListRow(tbl, i, listnum, listnums_size)
end
renderBelowRow(tbl)
return tbl
end
local function add_navbox_styles(hiding_templatestyles)
local frame = mw.getCurrentFrame()
-- This is a lambda so that it doesn't need the frame as a parameter
local function add_user_styles(templatestyles)
if not isblank(templatestyles) then
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
end
return ''
end
-- get templatestyles. load base from config so that Lua only needs to do
-- the work once of parser tag expansion
local base_templatestyles = cfg.templatestyles
local templatestyles = add_user_styles(args[cfg.arg.templatestyles])
local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles])
-- The 'navbox-styles' div exists to wrap the styles to work around T200206
-- more elegantly. Instead of combinatorial rules, this ends up being linear
-- number of CSS rules.
return mw.html.create('div')
:addClass(cfg.class.navbox_styles)
:wikitext(
add_list_styles() .. -- see [hlist_note] applied to 'before base_templatestyles'
base_templatestyles ..
templatestyles ..
child_templatestyles ..
table.concat(hiding_templatestyles)
)
:done()
end
-- work around [[phab:T303378]]
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
local argHash = 0
for k, arg in pairs(args) do
if type(arg) == 'string' then
for marker in string.gfind(arg, strip_marker_pattern) do
table.insert(hiding_templatestyles, marker)
end
argHash = argHash + #arg
args[k] = string.gsub(arg, strip_marker_pattern, '')
end
end
if not args.argHash then args.argHash = argHash end
local listnums = {}
for k, _ in pairs(args) do
if type(k) == 'string' then
local listnum = k:match(cfg.pattern.listnum)
if listnum and args[andnum('list', tonumber(listnum))] then
table.insert(listnums, tonumber(listnum))
end
end
end
table.sort(listnums)
local border = mw.text.trim(args[cfg.arg.border] or args[1] or '')
if border == cfg.keyword.border_child then
border = cfg.keyword.border_subgroup
end
-- render the main body of the navbox
local tbl = renderMainTable(border, listnums)
local res = mw.html.create()
-- render the appropriate wrapper for the navbox, based on the border param
if border == cfg.keyword.border_none then
res:node(add_navbox_styles(hiding_templatestyles))
local nav = res:tag('div')
:attr('role', 'navigation')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1]
and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label .. args.argHash)
end
elseif border == cfg.keyword.border_subgroup then
-- We assume that this navbox is being rendered in a list cell of a
-- parent navbox, and is therefore inside a div with padding:0em 0.25em.
-- We start with a </div> to avoid the padding being applied, and at the
-- end add a <div> to balance out the parent's </div>
res
:wikitext('</div>')
:node(tbl)
:wikitext('<div>')
else
res:node(add_navbox_styles(hiding_templatestyles))
local nav = res:tag('div')
:attr('role', 'navigation')
:addClass(cfg.class.navbox)
:addClass(args[cfg.arg.navboxclass])
:cssText(args[cfg.arg.bodystyle])
:cssText(args[cfg.arg.style])
:css('padding', '3px')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above]
or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label .. args.argHash)
end
end
if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then
renderTrackingCategories(res, border)
end
return striped(tostring(res), border)
end --p._navbox
function p._withCollapsibleGroups(pargs)
-- table for args passed to navbox
local targs = {}
-- process args
local passthroughLocal = {
[cfg.arg.bodystyle] = true,
[cfg.arg.border] = true,
[cfg.arg.style] = true,
}
for k,v in pairs(pargs) do
if k and type(k) == 'string' then
if passthrough[k] or passthroughLocal[k] then
targs[k] = v
elseif (k:match(cfg.pattern.num)) then
local n = k:match(cfg.pattern.num)
local list_and_num = andnum('list', n)
if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum))
and targs[list_and_num] == nil
and pargs[andnum('group', n)] == nil
and pargs[andnum('sect', n)] == nil
and pargs[andnum('section', n)] == nil) then
targs[list_and_num] = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then
targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num])
end
elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum))
and targs[list_and_num] == nil) then
local titlestyle = concatstyles({
pargs[cfg.arg.groupstyle] or '',
pargs[cfg.arg.secttitlestyle] or '',
pargs[andnum('groupstyle', n)] or '',
pargs[andnum('sectiontitlestyle', n)] or ''
})
local liststyle = concatstyles({
pargs[cfg.arg.liststyle] or '',
pargs[cfg.arg.contentstyle] or '',
pargs[andnum('liststyle', n)] or '',
pargs[andnum('contentstyle', n)] or ''
})
local title = concatstrings({
pargs[andnum('group', n)] or '',
pargs[andnum('sect', n)] or '',
pargs[andnum('section', n)] or ''
})
local list = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if list and inArray(cfg.keyword.subgroups, list) then
list = getSubgroup(pargs, n, list)
end
local abbr_and_num = andnum('abbr', n)
local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected])
and cfg.keyword.state_uncollapsed
or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed)
targs[list_and_num] =p._navbox({
cfg.keyword.border_child,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
[cfg.arg.state] = state,
[cfg.arg.basestyle] = pargs[cfg.arg.basestyle],
[cfg.arg.title] = title,
[cfg.arg.titlestyle] = titlestyle,
[andnum('list', 1)] = list,
[cfg.arg.liststyle] = liststyle,
[cfg.arg.listclass] = pargs[andnum('listclass', n)],
[cfg.arg.image] = pargs[andnum('image', n)],
[cfg.arg.imageleft] = pargs[andnum('imageleft', n)],
[cfg.arg.listpadding] = pargs[cfg.arg.listpadding],
argHash = pargs.argHash
})
end
end
end
end
-- ordering of style and bodystyle
targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''})
targs[cfg.arg.bodystyle] = nil
-- child or subgroup
if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end
return p._navbox(targs)
end --p._withCollapsibleGroups
function p._withColumns(pargs)
-- table for args passed to navbox
local targs = {}
-- tables of column numbers
local colheadernums = {}
local colnums = {}
local colfooternums = {}
-- process args
local passthroughLocal = {
[cfg.arg.evenstyle]=true,
[cfg.arg.groupstyle]=true,
[cfg.arg.liststyle]=true,
[cfg.arg.oddstyle]=true,
[cfg.arg.state]=true,
}
for k,v in pairs(pargs) do
if passthrough[k] or passthroughLocal[k] then
targs[k] = v
elseif type(k) == 'string' then
if k:match(cfg.pattern.listnum) then
local n = k:match(cfg.pattern.listnum)
targs[andnum('liststyle', n + 2)] = pargs[andnum('liststyle', n)]
targs[andnum('group', n + 2)] = pargs[andnum('group', n)]
targs[andnum('groupstyle', n + 2)] = pargs[andnum('groupstyle', n)]
if v and inArray(cfg.keyword.subgroups, v) then
targs[andnum('list', n + 2)] = getSubgroup(pargs, n, v)
else
targs[andnum('list', n + 2)] = v
end
elseif (k:match(cfg.pattern.colheadernum) and v ~= '') then
table.insert(colheadernums, tonumber(k:match(cfg.pattern.colheadernum)))
elseif (k:match(cfg.pattern.colnum) and v ~= '') then
table.insert(colnums, tonumber(k:match(cfg.pattern.colnum)))
elseif (k:match(cfg.pattern.colfooternum) and v ~= '') then
table.insert(colfooternums, tonumber(k:match(cfg.pattern.colfooternum)))
end
end
end
table.sort(colheadernums)
table.sort(colnums)
table.sort(colfooternums)
-- HTML table for list1
local coltable = mw.html.create( 'table' ):addClass('navbox-columns-table')
local row, col
local tablestyle = ( (#colheadernums > 0) or (not isblank(pargs[cfg.arg.fullwidth])) )
and 'width:100%'
or 'width:auto; margin-left:auto; margin-right:auto'
coltable:cssText(concatstyles({
'border-spacing: 0px; text-align:left',
tablestyle,
pargs[cfg.arg.coltablestyle] or ''
}))
--- Header row ---
if (#colheadernums > 0) then
row = coltable:tag('tr')
for k, n in ipairs(colheadernums) do
col = row:tag('th'):addClass('navbox-abovebelow')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'font-weight:bold',
pargs[cfg.arg.colheaderstyle] or '',
pargs[andnum('colheaderstyle', n)] or ''
}))
col:attr('colspan', tonumber(pargs[andnum('colheadercolspan', n)]))
col:wikitext(pargs[andnum('colheader', n)])
end
end
--- Main columns ---
row = coltable:tag('tr'):css('vertical-align', 'top')
for k, n in ipairs(colnums) do
if k == 1 and isblank(pargs[andnum('colheader', 1)])
and isblank(pargs[andnum('colfooter', 1)])
and isblank(pargs[cfg.arg.fullwidth]) then
local nopad = inArray(
{'off', '0', '0em', '0px'},
mw.ustring.gsub(pargs[cfg.arg.padding] or '', '[;%%]', ''))
if not nopad then
row:tag('td'):wikitext(' ')
:css('width', (pargs[cfg.arg.padding] or '5em'))
end
end
col = row:tag('td'):addClass('navbox-list')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'padding:0px',
pargs[cfg.arg.colstyle] or '',
((n%2 == 0) and pargs[cfg.arg.evencolstyle] or pargs[cfg.arg.oddcolstyle]) or '',
pargs[andnum('colstyle', n)] or '',
'width:' .. (pargs[andnum('colwidth', n)] or pargs[cfg.arg.colwidth] or '10em')
}))
local wt = pargs[andnum('col', n)]
if wt and inArray(cfg.keyword.subgroups, wt) then
wt = getSubgroup(pargs, n, wt, cfg.arg.col_and_num)
end
col:tag('div'):newline():wikitext(wt):newline()
end
--- Footer row ---
if (#colfooternums > 0) then
row = coltable:tag('tr')
for k, n in ipairs(colfooternums) do
col = row:tag('td'):addClass('navbox-abovebelow')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'font-weight:bold',
pargs[cfg.arg.colfooterstyle] or '',
pargs[andnum('colfooterstyle', n)] or ''
}))
col:attr('colspan', tonumber(pargs[andnum('colfootercolspan', n)]))
col:wikitext(pargs[andnum('colfooter', n)])
end
end
-- assign table to list1
targs[andnum('list', 1)] = tostring(coltable)
if isblank(pargs[andnum('colheader', 1)])
and isblank(pargs[andnum('col', 1)])
and isblank(pargs[andnum('colfooter', 1)]) then
targs[andnum('list', 1)] = targs[andnum('list', 1)] ..
cfg.category.without_first_col
end
-- Other parameters
targs[cfg.arg.border] = pargs[cfg.arg.border] or pargs[1]
targs[cfg.arg.evenodd] = (not isblank(pargs[cfg.arg.evenodd])) and pargs[cfg.arg.evenodd] or nil
targs[cfg.arg.list1padding] = '0px'
targs[andnum('liststyle', 1)] = 'background:transparent;color:inherit;'
targs[cfg.arg.style] = concatstyles({pargs[cfg.arg.style], pargs[cfg.arg.bodystyle]})
targs[cfg.arg.tracking] = 'no'
return p._navbox(targs)
end --p._withColumns
-- Template entry points
function p.navbox (frame, boxtype)
local function readArgs(args, prefix)
local function readSubgroups(element, i)
if inArray(cfg.keyword.subgroups, args[prefix .. andnum(element, i)]) then
for _, v in ipairs(cfg.arg.subgroups_and_num) do
readArgs(args, prefix .. string.format(v, i) .. "_")
end
readArgs(args, prefix .. andnum('col', i) .. "_")
end
end
-- Read the arguments in the order they'll be output in, to make references
-- number in the right order.
local _
_ = args[prefix .. cfg.arg.title]
_ = args[prefix .. cfg.arg.above]
-- Limit this to 20 as covering 'most' cases (that's a SWAG) and because
-- iterator approach won't work here
local boxtype = args.type or cfg.keyword[boxtype]
if boxtype == cfg.keyword.with_columns then
for i = 1, 20 do
_ = args[prefix .. andnum('colheader', i)]
end
for i = 1, 20 do
readSubgroups('col', i)
end
for i = 1, 20 do
_ = args[prefix .. andnum('colfooter', i)]
end
end
for i = 1, 20 do
_ = args[prefix .. andnum('group', i)]
readSubgroups('list', i)
end
_ = args[prefix .. cfg.arg.below]
end
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}})
readArgs(args, "")
args.argHash = nil -- we shouldn't accept argHash passed from a template
args.type = args.type or cfg.keyword[boxtype]
return p['_navbox'](args)
end
p[cfg.keyword.with_collapsible_groups] = function (frame)
return p.navbox(frame, 'with_collapsible_groups')
end
p[cfg.keyword.with_columns] = function (frame)
return p.navbox(frame, 'with_columns')
end
return p
1s4hl193ornydh8zrrhga8nr1v6arn9
9046
9045
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Navbox]]
9045
Scribunto
text/plain
require('strict')
local p = {}
local cfg = mw.loadData('Module:Navbox/configuration')
local inArray = require("Module:TableTools").inArray
local getArgs -- lazily initialized
local hiding_templatestyles = {}
-- global passthrough variables
local passthrough = {
[cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true,
[cfg.arg.basestyle]=true,
[cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true,
[cfg.arg.bodyclass]=true,
[cfg.arg.groupclass]=true,
[cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true,
[cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true,
[cfg.arg.listclass]=true,
[cfg.arg.name]=true,
[cfg.arg.navbar]=true,
[cfg.arg.state]=true,
[cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true,
argHash=true
}
-- helper functions
local andnum = function(s, n) return string.format(cfg.arg[s .. '_and_num'], n) end
local isblank = function(v) return (v or '') == '' end
local function concatstrings(s)
local r = table.concat(s, '')
if r:match('^%s*$') then return nil end
return r
end
local function concatstyles(s)
local r = ''
for _, v in ipairs(s) do
v = mw.text.trim(v, "%s;")
if not isblank(v) then r = r .. v .. ';' end
end
if isblank(r) then return nil end
return r
end
local function getSubgroup(args, listnum, listText, prefix)
local subArgs = {
[cfg.arg.border] = cfg.keyword.border_subgroup,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
argHash = 0
}
local hasSubArgs = false
local subgroups_and_num = prefix and {prefix} or cfg.arg.subgroups_and_num
for k, v in pairs(args) do
k = tostring(k)
for _, w in ipairs(subgroups_and_num) do
w = string.format(w, listnum) .. "_"
if (#k > #w) and (k:sub(1, #w) == w) then
subArgs[k:sub(#w + 1)] = v
hasSubArgs = true
subArgs.argHash = subArgs.argHash + (v and #v or 0)
end
end
end
return hasSubArgs and p._navbox(subArgs) or listText
end
-- Main functions
function p._navbox(args)
if args.type == cfg.keyword.with_collapsible_groups then
return p._withCollapsibleGroups(args)
elseif args.type == cfg.keyword.with_columns then
return p._withColumns(args)
end
local function striped(wikitext, border)
-- Return wikitext with markers replaced for odd/even striping.
-- Child (subgroup) navboxes are flagged with a category that is removed
-- by parent navboxes. The result is that the category shows all pages
-- where a child navbox is not contained in a parent navbox.
local orphanCat = cfg.category.orphan
if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then
-- No change; striping occurs in outermost navbox.
return wikitext .. orphanCat
end
local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part
if args[cfg.arg.evenodd] then
if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then
first, second = second, first
else
first = args[cfg.arg.evenodd]
second = first
end
end
local changer
if first == second then
changer = first
else
local index = 0
changer = function (code)
if code == '0' then
-- Current occurrence is for a group before a nested table.
-- Set it to first as a valid although pointless class.
-- The next occurrence will be the first row after a title
-- in a subgroup and will also be first.
index = 0
return first
end
index = index + 1
return index % 2 == 1 and first or second
end
end
local regex = orphanCat:gsub('([%[%]])', '%%%1')
return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count
end
local function processItem(item, nowrapitems)
if item:sub(1, 2) == '{|' then
-- Applying nowrap to lines in a table does not make sense.
-- Add newlines to compensate for trim of x in |parm=x in a template.
return '\n' .. item .. '\n'
end
if nowrapitems == cfg.keyword.nowrapitems_yes then
local lines = {}
for line in (item .. '\n'):gmatch('([^\n]*)\n') do
local prefix, content = line:match('^([*:;#]+)%s*(.*)')
if prefix and not content:match(cfg.pattern.nowrap) then
line = string.format(cfg.nowrap_item, prefix, content)
end
table.insert(lines, line)
end
item = table.concat(lines, '\n')
end
if item:match('^[*:;#]') then
return '\n' .. item .. '\n'
end
return item
end
local function has_navbar()
return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off
and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain
and (
args[cfg.arg.name]
or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '')
~= cfg.pattern.navbox
)
end
-- extract text color from css, which is the only permitted inline CSS for the navbar
local function extract_color(css_str)
-- return nil because navbar takes its argument into mw.html which handles
-- nil gracefully, removing the associated style attribute
return mw.ustring.match(';' .. css_str .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil
end
local function renderNavBar(titleCell)
if has_navbar() then
local navbar = require('Module:Navbar')._navbar
titleCell:wikitext(navbar{
[cfg.navbar.name] = args[cfg.arg.name],
[cfg.navbar.mini] = 1,
[cfg.navbar.fontstyle] = extract_color(
(args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '')
)
})
end
end
local function renderTitleRow(tbl)
if not args[cfg.arg.title] then return end
local titleRow = tbl:tag('tr')
local titleCell = titleRow:tag('th'):attr('scope', 'col')
local titleColspan = 2
if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end
if args[cfg.arg.image] then titleColspan = titleColspan + 1 end
titleCell
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.titlestyle])
:addClass(cfg.class.navbox_title)
:attr('colspan', titleColspan)
renderNavBar(titleCell)
titleCell
:tag('div')
-- id for aria-labelledby attribute
:attr('id', mw.uri.anchorEncode(args[cfg.arg.title]) .. args.argHash)
:addClass(args[cfg.arg.titleclass])
:css('font-size', '114%')
:css('margin', '0 4em')
:wikitext(processItem(args[cfg.arg.title]))
end
local function getAboveBelowColspan()
local ret = 2
if args[cfg.arg.imageleft] then ret = ret + 1 end
if args[cfg.arg.image] then ret = ret + 1 end
return ret
end
local function renderAboveRow(tbl)
if not args[cfg.arg.above] then return end
tbl:tag('tr')
:tag('td')
:addClass(cfg.class.navbox_abovebelow)
:addClass(args[cfg.arg.aboveclass])
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.abovestyle])
:attr('colspan', getAboveBelowColspan())
:tag('div')
-- id for aria-labelledby attribute, if no title
:attr('id', (not args[cfg.arg.title]) and
(mw.uri.anchorEncode(args[cfg.arg.above]) .. args.argHash)
or nil)
:wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems]))
end
local function renderBelowRow(tbl)
if not args[cfg.arg.below] then return end
tbl:tag('tr')
:tag('td')
:addClass(cfg.class.navbox_abovebelow)
:addClass(args[cfg.arg.belowclass])
:cssText(args[cfg.arg.basestyle])
:cssText(args[cfg.arg.belowstyle])
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems]))
end
local function renderListRow(tbl, index, listnum, listnums_size)
local row = tbl:tag('tr')
if index == 1 and args[cfg.arg.imageleft] then
row
:tag('td')
:addClass(cfg.class.noviewer)
:addClass(cfg.class.navbox_image)
:addClass(args[cfg.arg.imageclass])
:css('width', '1px') -- Minimize width
:css('padding', '0 2px 0 0')
:cssText(args[cfg.arg.imageleftstyle])
:attr('rowspan', listnums_size)
:tag('div')
:wikitext(processItem(args[cfg.arg.imageleft]))
end
local group_and_num = andnum('group', listnum)
local groupstyle_and_num = andnum('groupstyle', listnum)
if args[group_and_num] then
local groupCell = row:tag('th')
-- id for aria-labelledby attribute, if lone group with no title or above
if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then
groupCell
:attr('id', mw.uri.anchorEncode(args[cfg.arg.group1]) .. args.argHash)
end
groupCell
:attr('scope', 'row')
:addClass(cfg.class.navbox_group)
:addClass(args[cfg.arg.groupclass])
:cssText(args[cfg.arg.basestyle])
-- If groupwidth not specified, minimize width
:css('width', args[cfg.arg.groupwidth] or '1%')
groupCell
:cssText(args[cfg.arg.groupstyle])
:cssText(args[groupstyle_and_num])
:wikitext(args[group_and_num])
end
local listCell = row:tag('td')
if args[group_and_num] then
listCell
:addClass(cfg.class.navbox_list_with_group)
else
listCell:attr('colspan', 2)
end
if not args[cfg.arg.groupwidth] then
listCell:css('width', '100%')
end
local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing
if index % 2 == 1 then
rowstyle = args[cfg.arg.oddstyle]
else
rowstyle = args[cfg.arg.evenstyle]
end
local list_and_num = andnum('list', listnum)
local listText = inArray(cfg.keyword.subgroups, args[list_and_num])
and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num]
local oddEven = cfg.marker.oddeven
if listText:sub(1, 12) == '</div><table' then
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part
end
local liststyle_and_num = andnum('liststyle', listnum)
local listclass_and_num = andnum('listclass', listnum)
listCell
:css('padding', '0')
:cssText(args[cfg.arg.liststyle])
:cssText(rowstyle)
:cssText(args[liststyle_and_num])
:addClass(cfg.class.navbox_list)
:addClass(cfg.class.navbox_part .. oddEven)
:addClass(args[cfg.arg.listclass])
:addClass(args[listclass_and_num])
:tag('div')
:css('padding',
(index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em'
)
:wikitext(processItem(listText, args[cfg.arg.nowrapitems]))
if index == 1 and args[cfg.arg.image] then
row
:tag('td')
:addClass(cfg.class.noviewer)
:addClass(cfg.class.navbox_image)
:addClass(args[cfg.arg.imageclass])
:css('width', '1px') -- Minimize width
:css('padding', '0 0 0 2px')
:cssText(args[cfg.arg.imagestyle])
:attr('rowspan', listnums_size)
:tag('div')
:wikitext(processItem(args[cfg.arg.image]))
end
end
local function has_list_class(htmlclass)
local patterns = {
'^' .. htmlclass .. '$',
'%s' .. htmlclass .. '$',
'^' .. htmlclass .. '%s',
'%s' .. htmlclass .. '%s'
}
for arg, _ in pairs(args) do
if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then
for _, pattern in ipairs(patterns) do
if mw.ustring.find(args[arg] or '', pattern) then
return true
end
end
end
end
return false
end
-- there are a lot of list classes in the wild, so we add their TemplateStyles
local function add_list_styles()
local frame = mw.getCurrentFrame()
local function add_list_templatestyles(htmlclass, templatestyles)
if has_list_class(htmlclass) then
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
else
return ''
end
end
local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles)
local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles)
-- a second workaround for [[phab:T303378]]
-- when that issue is fixed, we can actually use has_navbar not to emit the
-- tag here if we want
if has_navbar() and hlist_styles == '' then
hlist_styles = frame:extensionTag{
name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
}
end
-- hlist -> plainlist is best-effort to preserve old Common.css ordering.
-- this ordering is not a guarantee because most navboxes will emit only
-- one of these classes [hlist_note]
return hlist_styles .. plainlist_styles
end
local function needsHorizontalLists(border)
if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then
return false
end
return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist)
end
local function hasBackgroundColors()
for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle,
cfg.arg.basestyle, cfg.arg.abovestyle, cfg.arg.belowstyle}) do
if tostring(args[key]):find('background', 1, true) then
return true
end
end
return false
end
local function hasBorders()
for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle,
cfg.arg.abovestyle, cfg.arg.belowstyle}) do
if tostring(args[key]):find('border', 1, true) then
return true
end
end
return false
end
local function isIllegible()
local styleratio = require('Module:Color contrast')._styleratio
for key, style in pairs(args) do
if tostring(key):match(cfg.pattern.style) then
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
return true
end
end
end
return false
end
local function getTrackingCategories(border)
local cats = {}
if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end
if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end
if isIllegible() then table.insert(cats, cfg.category.illegible) end
if hasBorders() then table.insert(cats, cfg.category.borders) end
return cats
end
local function renderTrackingCategories(builder, border)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 10 then return end -- not in template space
local subpage = title.subpageText
if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox
or subpage == cfg.keyword.subpage_testcases then return end
for _, cat in ipairs(getTrackingCategories(border)) do
builder:wikitext('[[Category:' .. cat .. ']]')
end
end
local function renderMainTable(border, listnums)
local tbl = mw.html.create('table')
:addClass(cfg.class.nowraplinks)
:addClass(args[cfg.arg.bodyclass])
local state = args[cfg.arg.state]
if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then
if state == cfg.keyword.state_collapsed then
state = cfg.class.collapsed
end
tbl
:addClass(cfg.class.collapsible)
:addClass(state or cfg.class.autocollapse)
end
tbl:css('border-spacing', 0)
if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then
tbl
:addClass(cfg.class.navbox_subgroup)
:cssText(args[cfg.arg.bodystyle])
:cssText(args[cfg.arg.style])
else -- regular navbox - bodystyle and style will be applied to the wrapper table
tbl
:addClass(cfg.class.navbox_inner)
:css('background', 'transparent')
:css('color', 'inherit')
end
tbl:cssText(args[cfg.arg.innerstyle])
renderTitleRow(tbl)
renderAboveRow(tbl)
local listnums_size = #listnums
for i, listnum in ipairs(listnums) do
renderListRow(tbl, i, listnum, listnums_size)
end
renderBelowRow(tbl)
return tbl
end
local function add_navbox_styles(hiding_templatestyles)
local frame = mw.getCurrentFrame()
-- This is a lambda so that it doesn't need the frame as a parameter
local function add_user_styles(templatestyles)
if not isblank(templatestyles) then
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
end
return ''
end
-- get templatestyles. load base from config so that Lua only needs to do
-- the work once of parser tag expansion
local base_templatestyles = cfg.templatestyles
local templatestyles = add_user_styles(args[cfg.arg.templatestyles])
local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles])
-- The 'navbox-styles' div exists to wrap the styles to work around T200206
-- more elegantly. Instead of combinatorial rules, this ends up being linear
-- number of CSS rules.
return mw.html.create('div')
:addClass(cfg.class.navbox_styles)
:wikitext(
add_list_styles() .. -- see [hlist_note] applied to 'before base_templatestyles'
base_templatestyles ..
templatestyles ..
child_templatestyles ..
table.concat(hiding_templatestyles)
)
:done()
end
-- work around [[phab:T303378]]
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
local argHash = 0
for k, arg in pairs(args) do
if type(arg) == 'string' then
for marker in string.gfind(arg, strip_marker_pattern) do
table.insert(hiding_templatestyles, marker)
end
argHash = argHash + #arg
args[k] = string.gsub(arg, strip_marker_pattern, '')
end
end
if not args.argHash then args.argHash = argHash end
local listnums = {}
for k, _ in pairs(args) do
if type(k) == 'string' then
local listnum = k:match(cfg.pattern.listnum)
if listnum and args[andnum('list', tonumber(listnum))] then
table.insert(listnums, tonumber(listnum))
end
end
end
table.sort(listnums)
local border = mw.text.trim(args[cfg.arg.border] or args[1] or '')
if border == cfg.keyword.border_child then
border = cfg.keyword.border_subgroup
end
-- render the main body of the navbox
local tbl = renderMainTable(border, listnums)
local res = mw.html.create()
-- render the appropriate wrapper for the navbox, based on the border param
if border == cfg.keyword.border_none then
res:node(add_navbox_styles(hiding_templatestyles))
local nav = res:tag('div')
:attr('role', 'navigation')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1]
and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label .. args.argHash)
end
elseif border == cfg.keyword.border_subgroup then
-- We assume that this navbox is being rendered in a list cell of a
-- parent navbox, and is therefore inside a div with padding:0em 0.25em.
-- We start with a </div> to avoid the padding being applied, and at the
-- end add a <div> to balance out the parent's </div>
res
:wikitext('</div>')
:node(tbl)
:wikitext('<div>')
else
res:node(add_navbox_styles(hiding_templatestyles))
local nav = res:tag('div')
:attr('role', 'navigation')
:addClass(cfg.class.navbox)
:addClass(args[cfg.arg.navboxclass])
:cssText(args[cfg.arg.bodystyle])
:cssText(args[cfg.arg.style])
:css('padding', '3px')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above]
or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label .. args.argHash)
end
end
if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then
renderTrackingCategories(res, border)
end
return striped(tostring(res), border)
end --p._navbox
function p._withCollapsibleGroups(pargs)
-- table for args passed to navbox
local targs = {}
-- process args
local passthroughLocal = {
[cfg.arg.bodystyle] = true,
[cfg.arg.border] = true,
[cfg.arg.style] = true,
}
for k,v in pairs(pargs) do
if k and type(k) == 'string' then
if passthrough[k] or passthroughLocal[k] then
targs[k] = v
elseif (k:match(cfg.pattern.num)) then
local n = k:match(cfg.pattern.num)
local list_and_num = andnum('list', n)
if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum))
and targs[list_and_num] == nil
and pargs[andnum('group', n)] == nil
and pargs[andnum('sect', n)] == nil
and pargs[andnum('section', n)] == nil) then
targs[list_and_num] = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then
targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num])
end
elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum))
and targs[list_and_num] == nil) then
local titlestyle = concatstyles({
pargs[cfg.arg.groupstyle] or '',
pargs[cfg.arg.secttitlestyle] or '',
pargs[andnum('groupstyle', n)] or '',
pargs[andnum('sectiontitlestyle', n)] or ''
})
local liststyle = concatstyles({
pargs[cfg.arg.liststyle] or '',
pargs[cfg.arg.contentstyle] or '',
pargs[andnum('liststyle', n)] or '',
pargs[andnum('contentstyle', n)] or ''
})
local title = concatstrings({
pargs[andnum('group', n)] or '',
pargs[andnum('sect', n)] or '',
pargs[andnum('section', n)] or ''
})
local list = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if list and inArray(cfg.keyword.subgroups, list) then
list = getSubgroup(pargs, n, list)
end
local abbr_and_num = andnum('abbr', n)
local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected])
and cfg.keyword.state_uncollapsed
or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed)
targs[list_and_num] =p._navbox({
cfg.keyword.border_child,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
[cfg.arg.state] = state,
[cfg.arg.basestyle] = pargs[cfg.arg.basestyle],
[cfg.arg.title] = title,
[cfg.arg.titlestyle] = titlestyle,
[andnum('list', 1)] = list,
[cfg.arg.liststyle] = liststyle,
[cfg.arg.listclass] = pargs[andnum('listclass', n)],
[cfg.arg.image] = pargs[andnum('image', n)],
[cfg.arg.imageleft] = pargs[andnum('imageleft', n)],
[cfg.arg.listpadding] = pargs[cfg.arg.listpadding],
argHash = pargs.argHash
})
end
end
end
end
-- ordering of style and bodystyle
targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''})
targs[cfg.arg.bodystyle] = nil
-- child or subgroup
if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end
return p._navbox(targs)
end --p._withCollapsibleGroups
function p._withColumns(pargs)
-- table for args passed to navbox
local targs = {}
-- tables of column numbers
local colheadernums = {}
local colnums = {}
local colfooternums = {}
-- process args
local passthroughLocal = {
[cfg.arg.evenstyle]=true,
[cfg.arg.groupstyle]=true,
[cfg.arg.liststyle]=true,
[cfg.arg.oddstyle]=true,
[cfg.arg.state]=true,
}
for k,v in pairs(pargs) do
if passthrough[k] or passthroughLocal[k] then
targs[k] = v
elseif type(k) == 'string' then
if k:match(cfg.pattern.listnum) then
local n = k:match(cfg.pattern.listnum)
targs[andnum('liststyle', n + 2)] = pargs[andnum('liststyle', n)]
targs[andnum('group', n + 2)] = pargs[andnum('group', n)]
targs[andnum('groupstyle', n + 2)] = pargs[andnum('groupstyle', n)]
if v and inArray(cfg.keyword.subgroups, v) then
targs[andnum('list', n + 2)] = getSubgroup(pargs, n, v)
else
targs[andnum('list', n + 2)] = v
end
elseif (k:match(cfg.pattern.colheadernum) and v ~= '') then
table.insert(colheadernums, tonumber(k:match(cfg.pattern.colheadernum)))
elseif (k:match(cfg.pattern.colnum) and v ~= '') then
table.insert(colnums, tonumber(k:match(cfg.pattern.colnum)))
elseif (k:match(cfg.pattern.colfooternum) and v ~= '') then
table.insert(colfooternums, tonumber(k:match(cfg.pattern.colfooternum)))
end
end
end
table.sort(colheadernums)
table.sort(colnums)
table.sort(colfooternums)
-- HTML table for list1
local coltable = mw.html.create( 'table' ):addClass('navbox-columns-table')
local row, col
local tablestyle = ( (#colheadernums > 0) or (not isblank(pargs[cfg.arg.fullwidth])) )
and 'width:100%'
or 'width:auto; margin-left:auto; margin-right:auto'
coltable:cssText(concatstyles({
'border-spacing: 0px; text-align:left',
tablestyle,
pargs[cfg.arg.coltablestyle] or ''
}))
--- Header row ---
if (#colheadernums > 0) then
row = coltable:tag('tr')
for k, n in ipairs(colheadernums) do
col = row:tag('th'):addClass('navbox-abovebelow')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'font-weight:bold',
pargs[cfg.arg.colheaderstyle] or '',
pargs[andnum('colheaderstyle', n)] or ''
}))
col:attr('colspan', tonumber(pargs[andnum('colheadercolspan', n)]))
col:wikitext(pargs[andnum('colheader', n)])
end
end
--- Main columns ---
row = coltable:tag('tr'):css('vertical-align', 'top')
for k, n in ipairs(colnums) do
if k == 1 and isblank(pargs[andnum('colheader', 1)])
and isblank(pargs[andnum('colfooter', 1)])
and isblank(pargs[cfg.arg.fullwidth]) then
local nopad = inArray(
{'off', '0', '0em', '0px'},
mw.ustring.gsub(pargs[cfg.arg.padding] or '', '[;%%]', ''))
if not nopad then
row:tag('td'):wikitext(' ')
:css('width', (pargs[cfg.arg.padding] or '5em'))
end
end
col = row:tag('td'):addClass('navbox-list')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'padding:0px',
pargs[cfg.arg.colstyle] or '',
((n%2 == 0) and pargs[cfg.arg.evencolstyle] or pargs[cfg.arg.oddcolstyle]) or '',
pargs[andnum('colstyle', n)] or '',
'width:' .. (pargs[andnum('colwidth', n)] or pargs[cfg.arg.colwidth] or '10em')
}))
local wt = pargs[andnum('col', n)]
if wt and inArray(cfg.keyword.subgroups, wt) then
wt = getSubgroup(pargs, n, wt, cfg.arg.col_and_num)
end
col:tag('div'):newline():wikitext(wt):newline()
end
--- Footer row ---
if (#colfooternums > 0) then
row = coltable:tag('tr')
for k, n in ipairs(colfooternums) do
col = row:tag('td'):addClass('navbox-abovebelow')
col:cssText(concatstyles({
(k > 1) and 'border-left:2px solid #fdfdfd' or '',
'font-weight:bold',
pargs[cfg.arg.colfooterstyle] or '',
pargs[andnum('colfooterstyle', n)] or ''
}))
col:attr('colspan', tonumber(pargs[andnum('colfootercolspan', n)]))
col:wikitext(pargs[andnum('colfooter', n)])
end
end
-- assign table to list1
targs[andnum('list', 1)] = tostring(coltable)
if isblank(pargs[andnum('colheader', 1)])
and isblank(pargs[andnum('col', 1)])
and isblank(pargs[andnum('colfooter', 1)]) then
targs[andnum('list', 1)] = targs[andnum('list', 1)] ..
cfg.category.without_first_col
end
-- Other parameters
targs[cfg.arg.border] = pargs[cfg.arg.border] or pargs[1]
targs[cfg.arg.evenodd] = (not isblank(pargs[cfg.arg.evenodd])) and pargs[cfg.arg.evenodd] or nil
targs[cfg.arg.list1padding] = '0px'
targs[andnum('liststyle', 1)] = 'background:transparent;color:inherit;'
targs[cfg.arg.style] = concatstyles({pargs[cfg.arg.style], pargs[cfg.arg.bodystyle]})
targs[cfg.arg.tracking] = 'no'
return p._navbox(targs)
end --p._withColumns
-- Template entry points
function p.navbox (frame, boxtype)
local function readArgs(args, prefix)
local function readSubgroups(element, i)
if inArray(cfg.keyword.subgroups, args[prefix .. andnum(element, i)]) then
for _, v in ipairs(cfg.arg.subgroups_and_num) do
readArgs(args, prefix .. string.format(v, i) .. "_")
end
readArgs(args, prefix .. andnum('col', i) .. "_")
end
end
-- Read the arguments in the order they'll be output in, to make references
-- number in the right order.
local _
_ = args[prefix .. cfg.arg.title]
_ = args[prefix .. cfg.arg.above]
-- Limit this to 20 as covering 'most' cases (that's a SWAG) and because
-- iterator approach won't work here
local boxtype = args.type or cfg.keyword[boxtype]
if boxtype == cfg.keyword.with_columns then
for i = 1, 20 do
_ = args[prefix .. andnum('colheader', i)]
end
for i = 1, 20 do
readSubgroups('col', i)
end
for i = 1, 20 do
_ = args[prefix .. andnum('colfooter', i)]
end
end
for i = 1, 20 do
_ = args[prefix .. andnum('group', i)]
readSubgroups('list', i)
end
_ = args[prefix .. cfg.arg.below]
end
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}})
readArgs(args, "")
args.argHash = nil -- we shouldn't accept argHash passed from a template
args.type = args.type or cfg.keyword[boxtype]
return p['_navbox'](args)
end
p[cfg.keyword.with_collapsible_groups] = function (frame)
return p.navbox(frame, 'with_collapsible_groups')
end
p[cfg.keyword.with_columns] = function (frame)
return p.navbox(frame, 'with_columns')
end
return p
1s4hl193ornydh8zrrhga8nr1v6arn9
Module:Navbox/configuration
828
1048
9047
2026-02-23T23:40:03Z
en>Ahecht
0
do this the right way
9047
Scribunto
text/plain
return {
aria_label = 'Navbox',
nowrap_item = '%s<span class="nowrap">%s</span>',
templatestyles = mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' }
},
hlist_templatestyles = 'Hlist/styles.css',
plainlist_templatestyles = 'Plainlist/styles.css',
-- do not localize marker table
marker = {
oddeven = '\127_ODDEVEN_\127',
restart = '\127_ODDEVEN0_\127',
regex = '\127_ODDEVEN(%d?)_\127'
},
category = {
orphan = '[[Category:Navbox orphans]]',
horizontal_lists = 'Navigational boxes without horizontal lists',
background_colors = 'Navboxes using background colours',
illegible = 'Potentially illegible navboxes',
borders = 'Navboxes using borders',
without_first_col = '[[Category:Pages using navbox columns without the first column]]'
},
keyword = {
border_subgroup = 'subgroup',
border_child = 'child',
border_none = 'none',
evenodd_swap = 'swap',
navbar_off = 'off',
navbar_plain = 'plain',
nocat_false = 'false',
nowrapitems_yes = 'yes',
orphan_yes = 'yes',
state_collapsed = 'collapsed',
state_off = 'off',
state_plain = 'plain',
state_uncollapsed = 'uncollapsed',
subgroups = {'subgroup', 'child', ''},
subpage_doc = 'doc',
subpage_sandbox = 'sandbox',
subpage_testcases = 'testcases',
tracking_no = 'no',
with_collapsible_groups = 'with collapsible groups',
with_collapsible_groups_short = 'collapsible',
with_columns = 'with columns',
with_columns_short = 'columns',
},
class = {
autocollapse = 'autocollapse',
collapsible = 'mw-collapsible',
collapsed = 'mw-collapsed',
-- Warning
navbox = 'navbox', -- WMF currently hides 'navbox' from mobile,
-- so you probably shouldn't change the navbox class.
navbox_abovebelow = 'navbox-abovebelow',
navbox_group = 'navbox-group',
navbox_image = 'navbox-image',
navbox_inner = 'navbox-inner',
navbox_list = 'navbox-list',
navbox_list_with_group = 'navbox-list-with-group',
navbox_part = 'navbox-', -- do not l10n
navbox_styles = 'navbox-styles',
navbox_subgroup = 'navbox-subgroup',
navbox_title = 'navbox-title', -- l10n only if you change pattern.navbox_title below
navbox_odd_part = 'odd', -- do not l10n
navbox_even_part = 'even', -- do not l10n
nomobile = 'nomobile',
nowraplinks = 'nowraplinks',
noviewer = 'noviewer', -- used to remove images from MediaViewer
notheme = 'notheme'
},
pattern = {
class = 'class',
colnum = '^col(%d+)$',
colheadernum = '^col(%d+)header$',
colfooternum = '^col(%d+)footer$',
contentnum = '^content(%d+)$',
groupnum = '^group(%d+)$',
hlist = 'hlist',
listnum = '^list(%d+)$',
navbox = 'Template:Navbox',
navbox_title = '<th[^>]*"navbox%-title"',
nowrap = '^<span class="nowrap">',
num = '^%a+(%d+)$',
plainlist = 'plainlist',
sandbox = '/sandbox$',
sectionnum = '^section(%d+)$',
sectnum = '^sect(%d+)$',
style = 'style$',
with_collapsible_groups = 'Template:Navbox with collapsible groups',
with_columns = 'Template:Navbox with columns',
},
arg = {
abbr_and_num = 'abbr%d',
above = 'above',
aboveclass = 'aboveclass',
abovestyle = 'abovestyle',
basestyle = 'basestyle',
below = 'below',
belowclass = 'belowclass',
belowstyle = 'belowstyle',
bodyclass = 'bodyclass',
bodystyle = 'bodystyle',
border = 'border',
content_and_num = 'content%d',
contentstyle = 'contentstyle',
contentstyle_and_num = 'content%dstyle',
colheaderstyle = 'colheaderstyle',
colheader_and_num = 'col%dheader',
colheaderstyle_and_num = 'col%dheaderstyle',
colheadercolspan_and_num = 'col%dheadercolspan',
colstyle = 'colstyle',
col_and_num = 'col%d',
colstyle_and_num = 'col%dstyle',
colwidth = 'colwidth',
colwidth_and_num = 'col%dwidth',
colfooterstyle = 'colfooterstyle',
colfooter_and_num = 'col%dfooter',
colfooterstyle_and_num = 'col%dfooterstyle',
colfootercolspan_and_num = 'col%dfootercolspan',
coltablestyle = 'coltablestyle',
evencolstyle = 'evencolstyle',
evenodd = 'evenodd',
evenstyle = 'evenstyle',
fullwidth = 'fullwidth',
group1 = 'group1',
group2 = 'group2',
group_and_num = 'group%d',
groupclass = 'groupclass',
groupstyle = 'groupstyle',
groupstyle_and_num = 'group%dstyle',
groupwidth = 'groupwidth',
image = 'image',
image_and_num = 'image%d',
imageclass = 'imageclass',
imageleft = 'imageleft',
imageleft_and_num = 'imageleft%d',
imageleftstyle = 'imageleftstyle',
imagestyle = 'imagestyle',
innerstyle = 'innerstyle',
list1padding = 'list1padding',
list_and_num = 'list%d',
listclass = 'listclass',
listclass_and_num = 'list%dclass',
listpadding = 'listpadding',
liststyle = 'liststyle',
liststyle_and_num = 'list%dstyle',
name = 'name',
navbar = 'navbar',
navboxclass = 'navboxclass',
nocat = 'nocat',
nowrapitems = 'nowrapitems',
oddcolstyle = 'oddcolstyle',
oddstyle = 'oddstyle',
orphan = 'orphan',
padding = 'padding',
sect_and_num = 'sect%d',
section_and_num = 'section%d',
sectiontitlestyle_and_num = 'section%dtitlestyle',
secttitlestyle = 'secttitlestyle',
selected = 'selected',
state = 'state',
state_and_num = 'state%d',
style = 'style',
subgroups_and_num = {'subgroup%d', 'child%d', '%d'},
templatestyles = 'templatestyles',
child_templatestyles = 'child templatestyles',
title = 'title',
titleclass = 'titleclass',
titlestyle = 'titlestyle',
tracking = 'tracking',
},
-- names of navbar arguments
navbar = {
name = 1,
fontstyle = 'fontstyle',
mini = 'mini'
}
}
hfe9tuviwm23frg4eyuetl5fcr6lsto
9048
9047
2026-08-22T12:06:27Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Navbox/configuration]]
9047
Scribunto
text/plain
return {
aria_label = 'Navbox',
nowrap_item = '%s<span class="nowrap">%s</span>',
templatestyles = mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' }
},
hlist_templatestyles = 'Hlist/styles.css',
plainlist_templatestyles = 'Plainlist/styles.css',
-- do not localize marker table
marker = {
oddeven = '\127_ODDEVEN_\127',
restart = '\127_ODDEVEN0_\127',
regex = '\127_ODDEVEN(%d?)_\127'
},
category = {
orphan = '[[Category:Navbox orphans]]',
horizontal_lists = 'Navigational boxes without horizontal lists',
background_colors = 'Navboxes using background colours',
illegible = 'Potentially illegible navboxes',
borders = 'Navboxes using borders',
without_first_col = '[[Category:Pages using navbox columns without the first column]]'
},
keyword = {
border_subgroup = 'subgroup',
border_child = 'child',
border_none = 'none',
evenodd_swap = 'swap',
navbar_off = 'off',
navbar_plain = 'plain',
nocat_false = 'false',
nowrapitems_yes = 'yes',
orphan_yes = 'yes',
state_collapsed = 'collapsed',
state_off = 'off',
state_plain = 'plain',
state_uncollapsed = 'uncollapsed',
subgroups = {'subgroup', 'child', ''},
subpage_doc = 'doc',
subpage_sandbox = 'sandbox',
subpage_testcases = 'testcases',
tracking_no = 'no',
with_collapsible_groups = 'with collapsible groups',
with_collapsible_groups_short = 'collapsible',
with_columns = 'with columns',
with_columns_short = 'columns',
},
class = {
autocollapse = 'autocollapse',
collapsible = 'mw-collapsible',
collapsed = 'mw-collapsed',
-- Warning
navbox = 'navbox', -- WMF currently hides 'navbox' from mobile,
-- so you probably shouldn't change the navbox class.
navbox_abovebelow = 'navbox-abovebelow',
navbox_group = 'navbox-group',
navbox_image = 'navbox-image',
navbox_inner = 'navbox-inner',
navbox_list = 'navbox-list',
navbox_list_with_group = 'navbox-list-with-group',
navbox_part = 'navbox-', -- do not l10n
navbox_styles = 'navbox-styles',
navbox_subgroup = 'navbox-subgroup',
navbox_title = 'navbox-title', -- l10n only if you change pattern.navbox_title below
navbox_odd_part = 'odd', -- do not l10n
navbox_even_part = 'even', -- do not l10n
nomobile = 'nomobile',
nowraplinks = 'nowraplinks',
noviewer = 'noviewer', -- used to remove images from MediaViewer
notheme = 'notheme'
},
pattern = {
class = 'class',
colnum = '^col(%d+)$',
colheadernum = '^col(%d+)header$',
colfooternum = '^col(%d+)footer$',
contentnum = '^content(%d+)$',
groupnum = '^group(%d+)$',
hlist = 'hlist',
listnum = '^list(%d+)$',
navbox = 'Template:Navbox',
navbox_title = '<th[^>]*"navbox%-title"',
nowrap = '^<span class="nowrap">',
num = '^%a+(%d+)$',
plainlist = 'plainlist',
sandbox = '/sandbox$',
sectionnum = '^section(%d+)$',
sectnum = '^sect(%d+)$',
style = 'style$',
with_collapsible_groups = 'Template:Navbox with collapsible groups',
with_columns = 'Template:Navbox with columns',
},
arg = {
abbr_and_num = 'abbr%d',
above = 'above',
aboveclass = 'aboveclass',
abovestyle = 'abovestyle',
basestyle = 'basestyle',
below = 'below',
belowclass = 'belowclass',
belowstyle = 'belowstyle',
bodyclass = 'bodyclass',
bodystyle = 'bodystyle',
border = 'border',
content_and_num = 'content%d',
contentstyle = 'contentstyle',
contentstyle_and_num = 'content%dstyle',
colheaderstyle = 'colheaderstyle',
colheader_and_num = 'col%dheader',
colheaderstyle_and_num = 'col%dheaderstyle',
colheadercolspan_and_num = 'col%dheadercolspan',
colstyle = 'colstyle',
col_and_num = 'col%d',
colstyle_and_num = 'col%dstyle',
colwidth = 'colwidth',
colwidth_and_num = 'col%dwidth',
colfooterstyle = 'colfooterstyle',
colfooter_and_num = 'col%dfooter',
colfooterstyle_and_num = 'col%dfooterstyle',
colfootercolspan_and_num = 'col%dfootercolspan',
coltablestyle = 'coltablestyle',
evencolstyle = 'evencolstyle',
evenodd = 'evenodd',
evenstyle = 'evenstyle',
fullwidth = 'fullwidth',
group1 = 'group1',
group2 = 'group2',
group_and_num = 'group%d',
groupclass = 'groupclass',
groupstyle = 'groupstyle',
groupstyle_and_num = 'group%dstyle',
groupwidth = 'groupwidth',
image = 'image',
image_and_num = 'image%d',
imageclass = 'imageclass',
imageleft = 'imageleft',
imageleft_and_num = 'imageleft%d',
imageleftstyle = 'imageleftstyle',
imagestyle = 'imagestyle',
innerstyle = 'innerstyle',
list1padding = 'list1padding',
list_and_num = 'list%d',
listclass = 'listclass',
listclass_and_num = 'list%dclass',
listpadding = 'listpadding',
liststyle = 'liststyle',
liststyle_and_num = 'list%dstyle',
name = 'name',
navbar = 'navbar',
navboxclass = 'navboxclass',
nocat = 'nocat',
nowrapitems = 'nowrapitems',
oddcolstyle = 'oddcolstyle',
oddstyle = 'oddstyle',
orphan = 'orphan',
padding = 'padding',
sect_and_num = 'sect%d',
section_and_num = 'section%d',
sectiontitlestyle_and_num = 'section%dtitlestyle',
secttitlestyle = 'secttitlestyle',
selected = 'selected',
state = 'state',
state_and_num = 'state%d',
style = 'style',
subgroups_and_num = {'subgroup%d', 'child%d', '%d'},
templatestyles = 'templatestyles',
child_templatestyles = 'child templatestyles',
title = 'title',
titleclass = 'titleclass',
titlestyle = 'titlestyle',
tracking = 'tracking',
},
-- names of navbar arguments
navbar = {
name = 1,
fontstyle = 'fontstyle',
mini = 'mini'
}
}
hfe9tuviwm23frg4eyuetl5fcr6lsto
Module:Redirect hatnote
828
1049
9049
2022-09-05T18:21:32Z
en>Nihiltres
0
Updated from sandbox: Migrated p._quote to Module:Hatnote
9049
Scribunto
text/plain
--[[
-- This module produces a "redirect" hatnote. It looks like this:
-- '"X" redirects here. For other uses, see Y.'
-- It implements the {{redirect}} template.
--]]
local mHatnote = require('Module:Hatnote')
local mHatList = require('Module:Hatnote list')
local mArguments --lazily initialize
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitle(...)
--Calls mw.title.new and returns either a title object, or nil on error
local success, titleObj = pcall(mw.title.new, ...)
return success and titleObj or nil
end
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.redirect(frame)
mArguments = require('Module:Arguments')
local args = mArguments.getArgs(frame, {parentOnly=true})
--Get number of redirects
local numRedirects = tonumber(frame.args[1]) or 1
-- Create the options table.
local options = {}
options.selfref = args.selfref
return p._redirect(args, numRedirects, options)
end
function p._redirect(args, numRedirects, options, currentTitle, redirectTitle, targetTitle)
-- Validate the input. Don't bother checking currentTitle, redirectTitle or
-- targetTitle, as they are only used in testing.
checkType('_redirect', 1, args, 'table')
checkType('_redirect', 2, numRedirects, 'number', true)
numRedirects = numRedirects or 1
checkType('_redirect', 3, options, 'table', true)
options = options or {}
currentTitle = currentTitle or mw.title.getCurrentTitle()
-- Get the table of redirects
local redirect = {}
for i = 1, numRedirects do
-- Return an error if a redirect parameter is missing.
if not args[i] then
return mHatnote.makeWikitextError(
'missing redirect parameter',
'Template:Redirect#Errors',
args.category
)
end
redirect[i] = args[i]
end
-- Generate the text.
local formattedRedirect = {}
for k,v in pairs(redirect) do
formattedRedirect[k] = mHatnote.quote(v)
end
local text = {
mHatList.andList(formattedRedirect) .. ' ' .. (#redirect == 1 and 'redirects' or 'redirect') .. ' here.',
mHatList._forSee(args, #redirect + 1, {title = redirect[1], extratext = args.text})
}
text = table.concat(text, ' ')
-- Functionality for adding categories
local categoryTable = {}
local function addCategory(cat)
if cat and cat ~= '' then
-- Add by index to avoid duplicates
categoryTable[string.format('[[Category:%s]]', cat)] = true
end
end
--Generate tracking categories
local mhOptions = {}
local redirTitle
for k,v in pairs(redirect) do
-- We don't need a tracking category if the template invocation has been
-- copied directly from the docs, or if we aren't in main- or category-space.
if not v:find('^REDIRECT%d*$') and v ~= 'TERM' --
and currentTitle.namespace == 0 or currentTitle.namespace == 14
then
redirTitle = redirectTitle or getTitle(v)
if not redirTitle or not redirTitle.exists then
addCategory('Missing redirects')
elseif not redirTitle.isRedirect then
if string.find(redirTitle:getContent(), '#invoke:RfD') then
addCategory('Articles with redirect hatnotes impacted by RfD')
else
addCategory('Articles with redirect hatnotes needing review')
end
else
local target = targetTitle or redirTitle.redirectTarget
if target and target ~= currentTitle then
addCategory('Articles with redirect hatnotes needing review')
end
end
end
-- Generate the options to pass to [[Module:Hatnote]].
if currentTitle.namespace == 0 and not mhOptions.selfref
and redirTitle and redirTitle.namespace ~= 0
then
-- We are on a mainspace page, and the hatnote starts with something
-- like "Wikipedia:Foo redirects here", so automatically label it as
-- a self-reference.
mhOptions.selfref = true
else
mhOptions.selfref = options.selfref
end
end
--concatenate all the categories
local category = ''
for k,v in pairs(categoryTable) do
category = category .. k
end
return mHatnote._hatnote(text, mhOptions) .. category
end
return p
bx3a2usoji3bjy33kez2xj3y12q8smx
9050
9049
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Redirect_hatnote]]
9049
Scribunto
text/plain
--[[
-- This module produces a "redirect" hatnote. It looks like this:
-- '"X" redirects here. For other uses, see Y.'
-- It implements the {{redirect}} template.
--]]
local mHatnote = require('Module:Hatnote')
local mHatList = require('Module:Hatnote list')
local mArguments --lazily initialize
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitle(...)
--Calls mw.title.new and returns either a title object, or nil on error
local success, titleObj = pcall(mw.title.new, ...)
return success and titleObj or nil
end
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.redirect(frame)
mArguments = require('Module:Arguments')
local args = mArguments.getArgs(frame, {parentOnly=true})
--Get number of redirects
local numRedirects = tonumber(frame.args[1]) or 1
-- Create the options table.
local options = {}
options.selfref = args.selfref
return p._redirect(args, numRedirects, options)
end
function p._redirect(args, numRedirects, options, currentTitle, redirectTitle, targetTitle)
-- Validate the input. Don't bother checking currentTitle, redirectTitle or
-- targetTitle, as they are only used in testing.
checkType('_redirect', 1, args, 'table')
checkType('_redirect', 2, numRedirects, 'number', true)
numRedirects = numRedirects or 1
checkType('_redirect', 3, options, 'table', true)
options = options or {}
currentTitle = currentTitle or mw.title.getCurrentTitle()
-- Get the table of redirects
local redirect = {}
for i = 1, numRedirects do
-- Return an error if a redirect parameter is missing.
if not args[i] then
return mHatnote.makeWikitextError(
'missing redirect parameter',
'Template:Redirect#Errors',
args.category
)
end
redirect[i] = args[i]
end
-- Generate the text.
local formattedRedirect = {}
for k,v in pairs(redirect) do
formattedRedirect[k] = mHatnote.quote(v)
end
local text = {
mHatList.andList(formattedRedirect) .. ' ' .. (#redirect == 1 and 'redirects' or 'redirect') .. ' here.',
mHatList._forSee(args, #redirect + 1, {title = redirect[1], extratext = args.text})
}
text = table.concat(text, ' ')
-- Functionality for adding categories
local categoryTable = {}
local function addCategory(cat)
if cat and cat ~= '' then
-- Add by index to avoid duplicates
categoryTable[string.format('[[Category:%s]]', cat)] = true
end
end
--Generate tracking categories
local mhOptions = {}
local redirTitle
for k,v in pairs(redirect) do
-- We don't need a tracking category if the template invocation has been
-- copied directly from the docs, or if we aren't in main- or category-space.
if not v:find('^REDIRECT%d*$') and v ~= 'TERM' --
and currentTitle.namespace == 0 or currentTitle.namespace == 14
then
redirTitle = redirectTitle or getTitle(v)
if not redirTitle or not redirTitle.exists then
addCategory('Missing redirects')
elseif not redirTitle.isRedirect then
if string.find(redirTitle:getContent(), '#invoke:RfD') then
addCategory('Articles with redirect hatnotes impacted by RfD')
else
addCategory('Articles with redirect hatnotes needing review')
end
else
local target = targetTitle or redirTitle.redirectTarget
if target and target ~= currentTitle then
addCategory('Articles with redirect hatnotes needing review')
end
end
end
-- Generate the options to pass to [[Module:Hatnote]].
if currentTitle.namespace == 0 and not mhOptions.selfref
and redirTitle and redirTitle.namespace ~= 0
then
-- We are on a mainspace page, and the hatnote starts with something
-- like "Wikipedia:Foo redirects here", so automatically label it as
-- a self-reference.
mhOptions.selfref = true
else
mhOptions.selfref = options.selfref
end
end
--concatenate all the categories
local category = ''
for k,v in pairs(categoryTable) do
category = category .. k
end
return mHatnote._hatnote(text, mhOptions) .. category
end
return p
bx3a2usoji3bjy33kez2xj3y12q8smx
Tempilet:Em
10
1050
9051
2020-08-09T23:17:35Z
en>Bsherr
0
/* top */as found, replacing [[Template:Tld]] with [[Template:Tlc]] or adding/updating category placement comments, plus general and typo fixes
9051
wikitext
text/x-wiki
<em {{#if:{{{role|}}}|role="{{{role}}}"}} {{#if:{{{class|}}}|class="{{{class}}}"}} {{#if:{{{id|}}}|id="{{{id}}}"}} {{#if:{{{style|}}}|style="{{{style}}}"}} {{#if:{{{title|}}}|title="{{{title}}}"}}>{{{1}}}</em><noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
qihth5vbfna026aqh87kteifb1nb5ot
9052
9051
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Em]]
9051
wikitext
text/x-wiki
<em {{#if:{{{role|}}}|role="{{{role}}}"}} {{#if:{{{class|}}}|class="{{{class}}}"}} {{#if:{{{id|}}}|id="{{{id}}}"}} {{#if:{{{style|}}}|style="{{{style}}}"}} {{#if:{{{title|}}}|title="{{{title}}}"}}>{{{1}}}</em><noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
qihth5vbfna026aqh87kteifb1nb5ot
Module:Color contrast
828
1051
9053
2026-07-27T16:10:39Z
en>Jonesey95
0
Undid revision [[Special:Diff/1366336997|1366336997]] by [[Special:Contributions/Aidan9382|Aidan9382]] ([[User talk:Aidan9382|talk]]). Appears to have broken the layout of Template:basketballbox. See [[Template:Basketballbox/testcases]]
9053
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB (v)
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum(R, G, B)
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum(h, s, l)
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum(c)
if (c == nil) then
return ''
end
-- html '#' entity
c = c:gsub("#", "#")
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- unstrip nowiki strip markers
c = mw.text.unstripNoWiki(c)
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
-- This exports the function for use in other modules.
-- The colour is passed as a string.
function p._lum(color)
return color2lum(color)
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local css = (args['css'] and args['css'] ~= '') and true or false
local v1 = color2lum(args[1] or '')
local c2 = args[2] or 'white'
local v2 = color2lum(c2)
local c3 = args[3] or 'black'
local v3 = color2lum(c3)
local ratio1 = -1;
local ratio2 = -1;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
if css then
local c1 = args[1] or ''
if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c1 = '#' .. c1
end
if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c2 = '#' .. c2
end
if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c3 = '#' .. c3
end
return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'
end
return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''
end
function p._ratio(args)
local v1 = color2lum(args[1])
local v2 = color2lum(args[2])
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', 'black'
local lum_bg, lum_fg = 1, 0
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '#', '#'), ';')
for k = 1,#slist do
local s = slist[k]
local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
--[[
Use {{#invoke:Color contrast|somecolor}} directly or
{{#invoke:Color contrast}} from a wrapper template.
Parameters:
-- |1= — required; A color to check.
--]]
function p.lum(frame)
local color = frame.args[1] or frame:getParent().args[1]
return p._lum(color)
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
bx0blwcv5isqzm2jrxnp01lj4148n73
9054
9053
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Color_contrast]]
9053
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB (v)
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum(R, G, B)
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum(h, s, l)
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum(c)
if (c == nil) then
return ''
end
-- html '#' entity
c = c:gsub("#", "#")
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- unstrip nowiki strip markers
c = mw.text.unstripNoWiki(c)
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
-- This exports the function for use in other modules.
-- The colour is passed as a string.
function p._lum(color)
return color2lum(color)
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local css = (args['css'] and args['css'] ~= '') and true or false
local v1 = color2lum(args[1] or '')
local c2 = args[2] or 'white'
local v2 = color2lum(c2)
local c3 = args[3] or 'black'
local v3 = color2lum(c3)
local ratio1 = -1;
local ratio2 = -1;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
if css then
local c1 = args[1] or ''
if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c1 = '#' .. c1
end
if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c2 = '#' .. c2
end
if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c3 = '#' .. c3
end
return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'
end
return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''
end
function p._ratio(args)
local v1 = color2lum(args[1])
local v2 = color2lum(args[2])
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', 'black'
local lum_bg, lum_fg = 1, 0
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '#', '#'), ';')
for k = 1,#slist do
local s = slist[k]
local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
--[[
Use {{#invoke:Color contrast|somecolor}} directly or
{{#invoke:Color contrast}} from a wrapper template.
Parameters:
-- |1= — required; A color to check.
--]]
function p.lum(frame)
local color = frame.args[1] or frame:getParent().args[1]
return p._lum(color)
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
bx0blwcv5isqzm2jrxnp01lj4148n73
Module:Color contrast/colors
828
1052
9055
2019-01-24T12:30:11Z
en>Galobtter
0
Changed protection level for "[[Module:Color contrast/colors]]": [[WP:High-risk templates|High-risk Lua module]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9055
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
chi69ar1btd4wp6xbk3uez6sfu0vipn
9056
9055
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Color_contrast/colors]]
9055
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
chi69ar1btd4wp6xbk3uez6sfu0vipn
Module:Text
828
1053
9057
2025-04-26T12:19:49Z
en>Hike395
0
update date to last edit
9057
Scribunto
text/plain
local yesNo = require("Module:Yesno")
local Text = { serial = "2024-09-21",
suite = "Text" }
--[=[
Text utilities
]=]
local function fiatQuote( apply, alien, advance )
-- Quote text
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code
-- advance -- number, with level 1 or 2
local r = apply and tostring(apply) or ""
alien = alien or "en"
advance = tonumber(advance) or 0
local suite
local data = mw.loadData('Module:Text/data')
local QuoteLang = data.QuoteLang
local QuoteType = data.QuoteType
local slang = alien:match( "^(%l+)-" )
suite = QuoteLang[alien] or slang and QuoteLang[slang] or QuoteLang["en"]
if suite then
local quotes = QuoteType[ suite ]
if quotes then
local space
if quotes[ 3 ] then
space = " "
else
space = ""
end
quotes = quotes[ advance ]
if quotes then
r = mw.ustring.format( "%s%s%s%s%s",
mw.ustring.char( quotes[ 1 ] ),
space,
apply,
space,
mw.ustring.char( quotes[ 2 ] ) )
end
else
mw.log( "fiatQuote() " .. suite )
end
end
return r
end -- fiatQuote()
Text.char = function ( apply, again, accept )
-- Create string from codepoints
-- Parameter:
-- apply -- table (sequence) with numerical codepoints, or nil
-- again -- number of repetitions, or nil
-- accept -- true, if no error messages to be appended
-- Returns: string
local r = ""
apply = type(apply) == "table" and apply or {}
again = math.floor(tonumber(again) or 1)
if again < 1 then
return ""
end
local bad = { }
local codes = { }
for _, v in ipairs( apply ) do
local n = tonumber(v)
if not n or (n < 32 and n ~= 9 and n ~= 10) then
table.insert(bad, tostring(v))
else
table.insert(codes, math.floor(n))
end
end
if #bad > 0 then
if not accept then
r = tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( "bad codepoints: " .. table.concat( bad, " " )) )
end
return r
end
if #codes > 0 then
r = mw.ustring.char( unpack( codes ) )
if again > 1 then
r = r:rep(again)
end
end
return r
end -- Text.char()
local function trimAndFormat(args, fmt)
local result = {}
if type(args) ~= 'table' then
args = {args}
end
for _, v in ipairs(args) do
v = mw.text.trim(tostring(v))
if v ~= "" then
table.insert(result,fmt and mw.ustring.format(fmt, v) or v)
end
end
return result
end
Text.concatParams = function ( args, apply, adapt )
-- Concat list items into one string
-- Parameter:
-- args -- table (sequence) with numKey=string
-- apply -- string (optional); separator (default: "|")
-- adapt -- string (optional); format including "%s"
-- Returns: string
local collect = { }
return table.concat(trimAndFormat(args,adapt), apply or "|")
end -- Text.concatParams()
Text.containsCJK = function ( s )
-- Is any CJK code within?
-- Parameter:
-- s -- string
-- Returns: true, if CJK detected
s = s and tostring(s) or ""
local patternCJK = mw.loadData('Module:Text/data').PatternCJK
return mw.ustring.find( s, patternCJK ) ~= nil
end -- Text.containsCJK()
Text.removeDelimited = function (s, prefix, suffix)
-- Remove all text in s delimited by prefix and suffix (inclusive)
-- Arguments:
-- s = string to process
-- prefix = initial delimiter
-- suffix = ending delimiter
-- Returns: stripped string
s = s and tostring(s) or ""
prefix = prefix and tostring(prefix) or ""
suffix = suffix and tostring(suffix) or ""
local prefixLen = mw.ustring.len(prefix)
local suffixLen = mw.ustring.len(suffix)
if prefixLen == 0 or suffixLen == 0 then
return s
end
local i = s:find(prefix, 1, true)
local r = s
local j
while i do
j = r:find(suffix, i + prefixLen)
if j then
r = r:sub(1, i - 1)..r:sub(j+suffixLen)
else
r = r:sub(1, i - 1)
end
i = r:find(prefix, 1, true)
end
return r
end
Text.getPlain = function ( adjust )
-- Remove wikisyntax from string, except templates
-- Parameter:
-- adjust -- string
-- Returns: string
local r = Text.removeDelimited(adjust,"<!--","-->")
r = r:gsub( "(</?%l[^>]*>)", "" )
:gsub( "'''", "" )
:gsub( "''", "" )
:gsub( " ", " " )
return r
end -- Text.getPlain()
Text.isLatinRange = function (s)
-- Are characters expected to be latin or symbols within latin texts?
-- Arguments:
-- s = string to analyze
-- Returns: true, if valid for latin only
s = s and tostring(s) or "" --- ensure input is always string
local PatternLatin = mw.loadData('Module:Text/data').PatternLatin
return mw.ustring.match(s, PatternLatin) ~= nil
end -- Text.isLatinRange()
Text.isQuote = function ( s )
-- Is this character any quotation mark?
-- Parameter:
-- s = single character to analyze
-- Returns: true, if s is quotation mark
s = s and tostring(s) or ""
if s == "" then
return false
end
local SeekQuote = mw.loadData('Module:Text/data').SeekQuote
return mw.ustring.find( SeekQuote, s, 1, true ) ~= nil
end -- Text.isQuote()
Text.listToText = function ( args, adapt )
-- Format list items similar to mw.text.listToText()
-- Parameter:
-- args -- table (sequence) with numKey=string
-- adapt -- string (optional); format including "%s"
-- Returns: string
return mw.text.listToText(trimAndFormat(args, adapt))
end -- Text.listToText()
Text.quote = function ( apply, alien, advance )
-- Quote text
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code, or nil
-- advance -- number, with level 1 or 2, or nil
-- Returns: quoted string
apply = apply and tostring(apply) or ""
local mode, slang
if type( alien ) == "string" then
slang = mw.text.trim( alien ):lower()
else
slang = mw.title.getCurrentTitle().pageLanguage
if not slang then
-- TODO FIXME: Introduction expected 2017-04
slang = mw.language.getContentLanguage():getCode()
end
end
if advance == 2 then
mode = 2
else
mode = 1
end
return fiatQuote( mw.text.trim( apply ), slang, mode )
end -- Text.quote()
Text.quoteUnquoted = function ( apply, alien, advance )
-- Quote text, if not yet quoted and not empty
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code, or nil
-- advance -- number, with level 1 or 2, or nil
-- Returns: string; possibly quoted
local r = mw.text.trim( apply and tostring(apply) or "" )
local s = mw.ustring.sub( r, 1, 1 )
if s ~= "" and not Text.isQuote( s, advance ) then
s = mw.ustring.sub( r, -1, 1 )
if not Text.isQuote( s ) then
r = Text.quote( r, alien, advance )
end
end
return r
end -- Text.quoteUnquoted()
Text.removeDiacritics = function ( adjust )
-- Remove all diacritics
-- Parameter:
-- adjust -- string
-- Returns: string; all latin letters should be ASCII
-- or basic greek or cyrillic or symbols etc.
local cleanup, decomposed
local PatternCombined = mw.loadData('Module:Text/data').PatternCombined
decomposed = mw.ustring.toNFD( adjust and tostring(adjust) or "" )
cleanup = mw.ustring.gsub( decomposed, PatternCombined, "" )
return mw.ustring.toNFC( cleanup )
end -- Text.removeDiacritics()
Text.sentenceTerminated = function ( analyse )
-- Is string terminated by dot, question or exclamation mark?
-- Quotation, link termination and so on granted
-- Parameter:
-- analyse -- string
-- Returns: true, if sentence terminated
local r
local PatternTerminated = mw.loadData('Module:Text/data').PatternTerminated
if mw.ustring.find( analyse, PatternTerminated ) then
r = true
else
r = false
end
return r
end -- Text.sentenceTerminated()
Text.ucfirstAll = function ( adjust)
-- Capitalize all words
-- Arguments:
-- adjust = string to adjust
-- Returns: string with all first letters in upper case
adjust = adjust and tostring(adjust) or ""
local r = mw.text.decode(adjust,true)
local i = 1
local c, j, m
m = (r ~= adjust)
r = " "..r
while i do
i = mw.ustring.find( r, "%W%l", i )
if i then
j = i + 1
c = mw.ustring.upper( mw.ustring.sub( r, j, j ) )
r = string.format( "%s%s%s",
mw.ustring.sub( r, 1, i ),
c,
mw.ustring.sub( r, i + 2 ) )
i = j
end
end -- while i
r = r:sub( 2 )
if m then
r = mw.text.encode(r)
end
return r
end -- Text.ucfirstAll()
Text.uprightNonlatin = function ( adjust )
-- Ensure non-italics for non-latin text parts
-- One single greek letter might be granted
-- Precondition:
-- adjust -- string
-- Returns: string with non-latin parts enclosed in <span>
local r
local data = mw.loadData('Module:Text/data')
local PatternLatin = data.PatternLatin
local RangesLatin = data.RangesLatin
local NumLatinRanges = data.NumLatinRanges
if mw.ustring.match( adjust, PatternLatin ) then
-- latin only, horizontal dashes, quotes
r = adjust
else
local c
local j = false
local k = 1
local m = false
local n = mw.ustring.len( adjust )
local span = "%s%s<span dir='auto' style='font-style:normal'>%s</span>"
local flat = function ( a )
-- isLatin
local range
-- NumLatinRanges has to be precomputed because # does not work from loadData
for i = 1, NumLatinRanges do
range = RangesLatin[ i ]
if a >= range[ 1 ] and a <= range[ 2 ] then
return true
end
end -- for i
end -- flat()
local focus = function ( a )
-- char is not ambivalent
local r = ( a > 64 )
if r then
r = ( a < 8192 or a > 8212 )
else
r = ( a == 38 or a == 60 ) -- '&' '<'
end
return r
end -- focus()
local form = function ( a )
return string.format( span,
r,
mw.ustring.sub( adjust, k, j - 1 ),
mw.ustring.sub( adjust, j, a ) )
end -- form()
r = ""
for i = 1, n do
c = mw.ustring.codepoint( adjust, i, i )
if focus( c ) then
if flat( c ) then
if j then
if m then
if i == m then
-- single greek letter.
j = false
end
m = false
end
if j then
local nx = i - 1
local s = ""
for ix = nx, 1, -1 do
c = mw.ustring.sub( adjust, ix, ix )
if c == " " or c == "(" then
nx = nx - 1
s = c .. s
else
break -- for ix
end
end -- for ix
r = form( nx ) .. s
j = false
k = i
end
end
elseif not j then
j = i
if c >= 880 and c <= 1023 then
-- single greek letter?
m = i + 1
else
m = false
end
end
elseif m then
m = m + 1
end
end -- for i
if j and ( not m or m < n ) then
r = form( n )
else
r = r .. mw.ustring.sub( adjust, k )
end
end
return r
end -- Text.uprightNonlatin()
Text.test = function ( about )
local r
if about == "quote" then
data = mw.loadData('Module:Text/data')
r = { }
r.QuoteLang = data.QuoteLang
r.QuoteType = data.QuoteType
end
return r
end -- Text.test()
-- Non Unicode-aware version of mw.text.split and mw.text.gsplit
-- based on [[phab:diffusion/ELUA/browse/master/includes/Engines/LuaCommon/lualib/mw.text.lua]]
-- These run up to 60 times faster than the Unicode-aware versions
Text.split = function ( text, pattern, plain )
local ret = {}
for m in Text.gsplit( text, pattern, plain ) do
ret[#ret+1] = m
end
return ret
end
Text.gsplit = function ( text, pattern, plain )
local s, l = 1, string.len( text )
return function ()
if s then
local e, n = string.find( text, pattern, s, plain )
local ret
if not e then
ret = string.sub( text, s )
s = nil
elseif n < e then
-- Empty separator!
ret = string.sub( text, s, e )
if e < l then
s = e + 1
else
s = nil
end
else
ret = e > s and string.sub( text, s, e - 1 ) or ''
s = n + 1
end
return ret
end
end, nil, nil
end
-- Export
local p = { }
for _, func in ipairs({'containsCJK','isLatinRange','isQuote','sentenceTerminated'}) do
p[func] = function (frame)
return Text[func]( frame.args[ 1 ] or "" ) and "1" or ""
end
end
for _, func in ipairs({'getPlain','removeDiacritics','ucfirstAll','uprightNonlatin'}) do
p[func] = function (frame)
return Text[func]( frame.args[ 1 ] or "" )
end
end
function p.char( frame )
local params = frame:getParent().args
local story = params[ 1 ]
local codes, lenient, multiple
if not story then
params = frame.args
story = params[ 1 ]
end
if story then
local items = mw.text.split( mw.text.trim(story), "%s+" )
if #items > 0 then
local j
lenient = (yesNo(params.errors) == false)
codes = { }
multiple = tonumber( params[ "*" ] )
for _, v in ipairs( items ) do
j = tonumber((v:sub( 1, 1 ) == "x" and "0" or "") .. v)
table.insert( codes, j or v )
end
end
end
return Text.char( codes, multiple, lenient )
end
function p.concatParams( frame )
local args
local template = frame.args.template
if type( template ) == "string" then
template = mw.text.trim( template )
template = ( template == "1" )
end
if template then
args = frame:getParent().args
else
args = frame.args
end
return Text.concatParams( args,
frame.args.separator,
frame.args.format )
end
function p.listToFormat(frame)
local lists = {}
local pformat = frame.args["format"]
local sep = frame.args["sep"] or ";"
-- Parameter parsen: Listen
for k, v in pairs(frame.args) do
local knum = tonumber(k)
if knum then lists[knum] = v end
end
-- Listen splitten
local maxListLen = 0
for i = 1, #lists do
lists[i] = mw.text.split(lists[i], sep)
if #lists[i] > maxListLen then maxListLen = #lists[i] end
end
-- Ergebnisstring generieren
local result = ""
local result_line = ""
for i = 1, maxListLen do
result_line = pformat
for j = 1, #lists do
result_line = mw.ustring.gsub(result_line, "%%s", lists[j][i], 1)
end
result = result .. result_line
end
return result
end
function p.listToText( frame )
local args
local template = frame.args.template
if type( template ) == "string" then
template = mw.text.trim( template )
template = ( template == "1" )
end
if template then
args = frame:getParent().args
else
args = frame.args
end
return Text.listToText( args, frame.args.format )
end
function p.quote( frame )
local slang = frame.args[2]
if type( slang ) == "string" then
slang = mw.text.trim( slang )
if slang == "" then
slang = false
end
end
return Text.quote( frame.args[ 1 ] or "",
slang,
tonumber( frame.args[3] ) )
end
function p.quoteUnquoted( frame )
local slang = frame.args[2]
if type( slang ) == "string" then
slang = mw.text.trim( slang )
if slang == "" then
slang = false
end
end
return Text.quoteUnquoted( frame.args[ 1 ] or "",
slang,
tonumber( frame.args[3] ) )
end
function p.zip(frame)
local lists = {}
local seps = {}
local defaultsep = frame.args["sep"] or ""
local innersep = frame.args["isep"] or ""
local outersep = frame.args["osep"] or ""
-- Parameter parsen
for k, v in pairs(frame.args) do
local knum = tonumber(k)
if knum then lists[knum] = v else
if string.sub(k, 1, 3) == "sep" then
local sepnum = tonumber(string.sub(k, 4))
if sepnum then seps[sepnum] = v end
end
end
end
-- sofern keine expliziten Separatoren angegeben sind, den Standardseparator verwenden
for i = 1, math.max(#seps, #lists) do
if not seps[i] then seps[i] = defaultsep end
end
-- Listen splitten
local maxListLen = 0
for i = 1, #lists do
lists[i] = mw.text.split(lists[i], seps[i])
if #lists[i] > maxListLen then maxListLen = #lists[i] end
end
local result = ""
for i = 1, maxListLen do
if i ~= 1 then result = result .. outersep end
for j = 1, #lists do
if j ~= 1 then result = result .. innersep end
result = result .. (lists[j][i] or "")
end
end
return result
end
function p.split(frame)
local text = frame.args.text or frame.args[1] or ''
local pattern = frame.args.pattern or frame.args[2] or ''
local plain = yesNo(frame.args.plain or frame.args[3])
local index = tonumber(frame.args.index) or tonumber(frame.args[4]) or 1
local a = Text.split(text, pattern, plain)
if index < 0 then index = #a + index + 1 end
return a[index]
end
function p.failsafe()
return Text.serial
end
p.Text = function ()
return Text
end -- p.Text
return p
651uzyv6p5vsoexbfr111b6ilkxeurw
9058
9057
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Text]]
9057
Scribunto
text/plain
local yesNo = require("Module:Yesno")
local Text = { serial = "2024-09-21",
suite = "Text" }
--[=[
Text utilities
]=]
local function fiatQuote( apply, alien, advance )
-- Quote text
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code
-- advance -- number, with level 1 or 2
local r = apply and tostring(apply) or ""
alien = alien or "en"
advance = tonumber(advance) or 0
local suite
local data = mw.loadData('Module:Text/data')
local QuoteLang = data.QuoteLang
local QuoteType = data.QuoteType
local slang = alien:match( "^(%l+)-" )
suite = QuoteLang[alien] or slang and QuoteLang[slang] or QuoteLang["en"]
if suite then
local quotes = QuoteType[ suite ]
if quotes then
local space
if quotes[ 3 ] then
space = " "
else
space = ""
end
quotes = quotes[ advance ]
if quotes then
r = mw.ustring.format( "%s%s%s%s%s",
mw.ustring.char( quotes[ 1 ] ),
space,
apply,
space,
mw.ustring.char( quotes[ 2 ] ) )
end
else
mw.log( "fiatQuote() " .. suite )
end
end
return r
end -- fiatQuote()
Text.char = function ( apply, again, accept )
-- Create string from codepoints
-- Parameter:
-- apply -- table (sequence) with numerical codepoints, or nil
-- again -- number of repetitions, or nil
-- accept -- true, if no error messages to be appended
-- Returns: string
local r = ""
apply = type(apply) == "table" and apply or {}
again = math.floor(tonumber(again) or 1)
if again < 1 then
return ""
end
local bad = { }
local codes = { }
for _, v in ipairs( apply ) do
local n = tonumber(v)
if not n or (n < 32 and n ~= 9 and n ~= 10) then
table.insert(bad, tostring(v))
else
table.insert(codes, math.floor(n))
end
end
if #bad > 0 then
if not accept then
r = tostring( mw.html.create( "span" )
:addClass( "error" )
:wikitext( "bad codepoints: " .. table.concat( bad, " " )) )
end
return r
end
if #codes > 0 then
r = mw.ustring.char( unpack( codes ) )
if again > 1 then
r = r:rep(again)
end
end
return r
end -- Text.char()
local function trimAndFormat(args, fmt)
local result = {}
if type(args) ~= 'table' then
args = {args}
end
for _, v in ipairs(args) do
v = mw.text.trim(tostring(v))
if v ~= "" then
table.insert(result,fmt and mw.ustring.format(fmt, v) or v)
end
end
return result
end
Text.concatParams = function ( args, apply, adapt )
-- Concat list items into one string
-- Parameter:
-- args -- table (sequence) with numKey=string
-- apply -- string (optional); separator (default: "|")
-- adapt -- string (optional); format including "%s"
-- Returns: string
local collect = { }
return table.concat(trimAndFormat(args,adapt), apply or "|")
end -- Text.concatParams()
Text.containsCJK = function ( s )
-- Is any CJK code within?
-- Parameter:
-- s -- string
-- Returns: true, if CJK detected
s = s and tostring(s) or ""
local patternCJK = mw.loadData('Module:Text/data').PatternCJK
return mw.ustring.find( s, patternCJK ) ~= nil
end -- Text.containsCJK()
Text.removeDelimited = function (s, prefix, suffix)
-- Remove all text in s delimited by prefix and suffix (inclusive)
-- Arguments:
-- s = string to process
-- prefix = initial delimiter
-- suffix = ending delimiter
-- Returns: stripped string
s = s and tostring(s) or ""
prefix = prefix and tostring(prefix) or ""
suffix = suffix and tostring(suffix) or ""
local prefixLen = mw.ustring.len(prefix)
local suffixLen = mw.ustring.len(suffix)
if prefixLen == 0 or suffixLen == 0 then
return s
end
local i = s:find(prefix, 1, true)
local r = s
local j
while i do
j = r:find(suffix, i + prefixLen)
if j then
r = r:sub(1, i - 1)..r:sub(j+suffixLen)
else
r = r:sub(1, i - 1)
end
i = r:find(prefix, 1, true)
end
return r
end
Text.getPlain = function ( adjust )
-- Remove wikisyntax from string, except templates
-- Parameter:
-- adjust -- string
-- Returns: string
local r = Text.removeDelimited(adjust,"<!--","-->")
r = r:gsub( "(</?%l[^>]*>)", "" )
:gsub( "'''", "" )
:gsub( "''", "" )
:gsub( " ", " " )
return r
end -- Text.getPlain()
Text.isLatinRange = function (s)
-- Are characters expected to be latin or symbols within latin texts?
-- Arguments:
-- s = string to analyze
-- Returns: true, if valid for latin only
s = s and tostring(s) or "" --- ensure input is always string
local PatternLatin = mw.loadData('Module:Text/data').PatternLatin
return mw.ustring.match(s, PatternLatin) ~= nil
end -- Text.isLatinRange()
Text.isQuote = function ( s )
-- Is this character any quotation mark?
-- Parameter:
-- s = single character to analyze
-- Returns: true, if s is quotation mark
s = s and tostring(s) or ""
if s == "" then
return false
end
local SeekQuote = mw.loadData('Module:Text/data').SeekQuote
return mw.ustring.find( SeekQuote, s, 1, true ) ~= nil
end -- Text.isQuote()
Text.listToText = function ( args, adapt )
-- Format list items similar to mw.text.listToText()
-- Parameter:
-- args -- table (sequence) with numKey=string
-- adapt -- string (optional); format including "%s"
-- Returns: string
return mw.text.listToText(trimAndFormat(args, adapt))
end -- Text.listToText()
Text.quote = function ( apply, alien, advance )
-- Quote text
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code, or nil
-- advance -- number, with level 1 or 2, or nil
-- Returns: quoted string
apply = apply and tostring(apply) or ""
local mode, slang
if type( alien ) == "string" then
slang = mw.text.trim( alien ):lower()
else
slang = mw.title.getCurrentTitle().pageLanguage
if not slang then
-- TODO FIXME: Introduction expected 2017-04
slang = mw.language.getContentLanguage():getCode()
end
end
if advance == 2 then
mode = 2
else
mode = 1
end
return fiatQuote( mw.text.trim( apply ), slang, mode )
end -- Text.quote()
Text.quoteUnquoted = function ( apply, alien, advance )
-- Quote text, if not yet quoted and not empty
-- Parameter:
-- apply -- string, with text
-- alien -- string, with language code, or nil
-- advance -- number, with level 1 or 2, or nil
-- Returns: string; possibly quoted
local r = mw.text.trim( apply and tostring(apply) or "" )
local s = mw.ustring.sub( r, 1, 1 )
if s ~= "" and not Text.isQuote( s, advance ) then
s = mw.ustring.sub( r, -1, 1 )
if not Text.isQuote( s ) then
r = Text.quote( r, alien, advance )
end
end
return r
end -- Text.quoteUnquoted()
Text.removeDiacritics = function ( adjust )
-- Remove all diacritics
-- Parameter:
-- adjust -- string
-- Returns: string; all latin letters should be ASCII
-- or basic greek or cyrillic or symbols etc.
local cleanup, decomposed
local PatternCombined = mw.loadData('Module:Text/data').PatternCombined
decomposed = mw.ustring.toNFD( adjust and tostring(adjust) or "" )
cleanup = mw.ustring.gsub( decomposed, PatternCombined, "" )
return mw.ustring.toNFC( cleanup )
end -- Text.removeDiacritics()
Text.sentenceTerminated = function ( analyse )
-- Is string terminated by dot, question or exclamation mark?
-- Quotation, link termination and so on granted
-- Parameter:
-- analyse -- string
-- Returns: true, if sentence terminated
local r
local PatternTerminated = mw.loadData('Module:Text/data').PatternTerminated
if mw.ustring.find( analyse, PatternTerminated ) then
r = true
else
r = false
end
return r
end -- Text.sentenceTerminated()
Text.ucfirstAll = function ( adjust)
-- Capitalize all words
-- Arguments:
-- adjust = string to adjust
-- Returns: string with all first letters in upper case
adjust = adjust and tostring(adjust) or ""
local r = mw.text.decode(adjust,true)
local i = 1
local c, j, m
m = (r ~= adjust)
r = " "..r
while i do
i = mw.ustring.find( r, "%W%l", i )
if i then
j = i + 1
c = mw.ustring.upper( mw.ustring.sub( r, j, j ) )
r = string.format( "%s%s%s",
mw.ustring.sub( r, 1, i ),
c,
mw.ustring.sub( r, i + 2 ) )
i = j
end
end -- while i
r = r:sub( 2 )
if m then
r = mw.text.encode(r)
end
return r
end -- Text.ucfirstAll()
Text.uprightNonlatin = function ( adjust )
-- Ensure non-italics for non-latin text parts
-- One single greek letter might be granted
-- Precondition:
-- adjust -- string
-- Returns: string with non-latin parts enclosed in <span>
local r
local data = mw.loadData('Module:Text/data')
local PatternLatin = data.PatternLatin
local RangesLatin = data.RangesLatin
local NumLatinRanges = data.NumLatinRanges
if mw.ustring.match( adjust, PatternLatin ) then
-- latin only, horizontal dashes, quotes
r = adjust
else
local c
local j = false
local k = 1
local m = false
local n = mw.ustring.len( adjust )
local span = "%s%s<span dir='auto' style='font-style:normal'>%s</span>"
local flat = function ( a )
-- isLatin
local range
-- NumLatinRanges has to be precomputed because # does not work from loadData
for i = 1, NumLatinRanges do
range = RangesLatin[ i ]
if a >= range[ 1 ] and a <= range[ 2 ] then
return true
end
end -- for i
end -- flat()
local focus = function ( a )
-- char is not ambivalent
local r = ( a > 64 )
if r then
r = ( a < 8192 or a > 8212 )
else
r = ( a == 38 or a == 60 ) -- '&' '<'
end
return r
end -- focus()
local form = function ( a )
return string.format( span,
r,
mw.ustring.sub( adjust, k, j - 1 ),
mw.ustring.sub( adjust, j, a ) )
end -- form()
r = ""
for i = 1, n do
c = mw.ustring.codepoint( adjust, i, i )
if focus( c ) then
if flat( c ) then
if j then
if m then
if i == m then
-- single greek letter.
j = false
end
m = false
end
if j then
local nx = i - 1
local s = ""
for ix = nx, 1, -1 do
c = mw.ustring.sub( adjust, ix, ix )
if c == " " or c == "(" then
nx = nx - 1
s = c .. s
else
break -- for ix
end
end -- for ix
r = form( nx ) .. s
j = false
k = i
end
end
elseif not j then
j = i
if c >= 880 and c <= 1023 then
-- single greek letter?
m = i + 1
else
m = false
end
end
elseif m then
m = m + 1
end
end -- for i
if j and ( not m or m < n ) then
r = form( n )
else
r = r .. mw.ustring.sub( adjust, k )
end
end
return r
end -- Text.uprightNonlatin()
Text.test = function ( about )
local r
if about == "quote" then
data = mw.loadData('Module:Text/data')
r = { }
r.QuoteLang = data.QuoteLang
r.QuoteType = data.QuoteType
end
return r
end -- Text.test()
-- Non Unicode-aware version of mw.text.split and mw.text.gsplit
-- based on [[phab:diffusion/ELUA/browse/master/includes/Engines/LuaCommon/lualib/mw.text.lua]]
-- These run up to 60 times faster than the Unicode-aware versions
Text.split = function ( text, pattern, plain )
local ret = {}
for m in Text.gsplit( text, pattern, plain ) do
ret[#ret+1] = m
end
return ret
end
Text.gsplit = function ( text, pattern, plain )
local s, l = 1, string.len( text )
return function ()
if s then
local e, n = string.find( text, pattern, s, plain )
local ret
if not e then
ret = string.sub( text, s )
s = nil
elseif n < e then
-- Empty separator!
ret = string.sub( text, s, e )
if e < l then
s = e + 1
else
s = nil
end
else
ret = e > s and string.sub( text, s, e - 1 ) or ''
s = n + 1
end
return ret
end
end, nil, nil
end
-- Export
local p = { }
for _, func in ipairs({'containsCJK','isLatinRange','isQuote','sentenceTerminated'}) do
p[func] = function (frame)
return Text[func]( frame.args[ 1 ] or "" ) and "1" or ""
end
end
for _, func in ipairs({'getPlain','removeDiacritics','ucfirstAll','uprightNonlatin'}) do
p[func] = function (frame)
return Text[func]( frame.args[ 1 ] or "" )
end
end
function p.char( frame )
local params = frame:getParent().args
local story = params[ 1 ]
local codes, lenient, multiple
if not story then
params = frame.args
story = params[ 1 ]
end
if story then
local items = mw.text.split( mw.text.trim(story), "%s+" )
if #items > 0 then
local j
lenient = (yesNo(params.errors) == false)
codes = { }
multiple = tonumber( params[ "*" ] )
for _, v in ipairs( items ) do
j = tonumber((v:sub( 1, 1 ) == "x" and "0" or "") .. v)
table.insert( codes, j or v )
end
end
end
return Text.char( codes, multiple, lenient )
end
function p.concatParams( frame )
local args
local template = frame.args.template
if type( template ) == "string" then
template = mw.text.trim( template )
template = ( template == "1" )
end
if template then
args = frame:getParent().args
else
args = frame.args
end
return Text.concatParams( args,
frame.args.separator,
frame.args.format )
end
function p.listToFormat(frame)
local lists = {}
local pformat = frame.args["format"]
local sep = frame.args["sep"] or ";"
-- Parameter parsen: Listen
for k, v in pairs(frame.args) do
local knum = tonumber(k)
if knum then lists[knum] = v end
end
-- Listen splitten
local maxListLen = 0
for i = 1, #lists do
lists[i] = mw.text.split(lists[i], sep)
if #lists[i] > maxListLen then maxListLen = #lists[i] end
end
-- Ergebnisstring generieren
local result = ""
local result_line = ""
for i = 1, maxListLen do
result_line = pformat
for j = 1, #lists do
result_line = mw.ustring.gsub(result_line, "%%s", lists[j][i], 1)
end
result = result .. result_line
end
return result
end
function p.listToText( frame )
local args
local template = frame.args.template
if type( template ) == "string" then
template = mw.text.trim( template )
template = ( template == "1" )
end
if template then
args = frame:getParent().args
else
args = frame.args
end
return Text.listToText( args, frame.args.format )
end
function p.quote( frame )
local slang = frame.args[2]
if type( slang ) == "string" then
slang = mw.text.trim( slang )
if slang == "" then
slang = false
end
end
return Text.quote( frame.args[ 1 ] or "",
slang,
tonumber( frame.args[3] ) )
end
function p.quoteUnquoted( frame )
local slang = frame.args[2]
if type( slang ) == "string" then
slang = mw.text.trim( slang )
if slang == "" then
slang = false
end
end
return Text.quoteUnquoted( frame.args[ 1 ] or "",
slang,
tonumber( frame.args[3] ) )
end
function p.zip(frame)
local lists = {}
local seps = {}
local defaultsep = frame.args["sep"] or ""
local innersep = frame.args["isep"] or ""
local outersep = frame.args["osep"] or ""
-- Parameter parsen
for k, v in pairs(frame.args) do
local knum = tonumber(k)
if knum then lists[knum] = v else
if string.sub(k, 1, 3) == "sep" then
local sepnum = tonumber(string.sub(k, 4))
if sepnum then seps[sepnum] = v end
end
end
end
-- sofern keine expliziten Separatoren angegeben sind, den Standardseparator verwenden
for i = 1, math.max(#seps, #lists) do
if not seps[i] then seps[i] = defaultsep end
end
-- Listen splitten
local maxListLen = 0
for i = 1, #lists do
lists[i] = mw.text.split(lists[i], seps[i])
if #lists[i] > maxListLen then maxListLen = #lists[i] end
end
local result = ""
for i = 1, maxListLen do
if i ~= 1 then result = result .. outersep end
for j = 1, #lists do
if j ~= 1 then result = result .. innersep end
result = result .. (lists[j][i] or "")
end
end
return result
end
function p.split(frame)
local text = frame.args.text or frame.args[1] or ''
local pattern = frame.args.pattern or frame.args[2] or ''
local plain = yesNo(frame.args.plain or frame.args[3])
local index = tonumber(frame.args.index) or tonumber(frame.args[4]) or 1
local a = Text.split(text, pattern, plain)
if index < 0 then index = #a + index + 1 end
return a[index]
end
function p.failsafe()
return Text.serial
end
p.Text = function ()
return Text
end -- p.Text
return p
651uzyv6p5vsoexbfr111b6ilkxeurw
Tempilet:No redirect
10
1054
9061
2025-11-25T21:47:15Z
en>GTrang
0
Used FULLPAGENAME again to fix the "Multi colon escape" lint error.
9061
wikitext
text/x-wiki
{{safesubst:<noinclude/>#if: {{safesubst:<noinclude/>#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{safesubst:<noinclude/>fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span><span style="display: none">[[:{{{1}}}]]</span>
| [[:{{safesubst:<noinclude/>FULLPAGENAME:{{{1}}}}}|{{{2|{{{1}}}}}}]]
}}<noinclude>
{{documentation}}
</noinclude>
5pw8ky320dln3bgzenyzuppz9t6twll
9062
9061
2026-08-22T12:06:28Z
RAPTOR7762
18
1 revision imported from [[:en:Template:No_redirect]]
9061
wikitext
text/x-wiki
{{safesubst:<noinclude/>#if: {{safesubst:<noinclude/>#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{safesubst:<noinclude/>fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span><span style="display: none">[[:{{{1}}}]]</span>
| [[:{{safesubst:<noinclude/>FULLPAGENAME:{{{1}}}}}|{{{2|{{{1}}}}}}]]
}}<noinclude>
{{documentation}}
</noinclude>
5pw8ky320dln3bgzenyzuppz9t6twll
Module:Shortcut
828
1055
9063
2024-03-11T03:26:56Z
en>Izno
0
Undid revision [[Special:Diff/1212853521|1212853521]] by [[Special:Contributions/Jdlrobson|Jdlrobson]] ([[User talk:Jdlrobson|talk]]) no, that class is exclusive to the module in which it appears
9063
Scribunto
text/plain
-- This module implements {{shortcut}}.
-- Set constants
local CONFIG_MODULE = 'Module:Shortcut/config'
-- Load required modules
local checkType = require('libraryUtil').checkType
local yesno = require('Module:Yesno')
local p = {}
local function message(msg, ...)
return mw.message.newRawMessage(msg, ...):plain()
end
local function makeCategoryLink(cat)
return string.format('[[%s:%s]]', mw.site.namespaces[14].name, cat)
end
function p._main(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local templateMode = options.template and yesno(options.template)
local redirectMode = options.redirect and yesno(options.redirect)
local isCategorized = not options.category or yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
local templatePath, prefix
if templateMode then
-- Namespace detection
local titleObj = mw.title.new(shortcut, 10)
if titleObj.namespace == 10 then
templatePath = titleObj.fullText
else
templatePath = shortcut
end
prefix = options['pre' .. i] or options.pre or ''
end
if options.target and yesno(options.target) then
listItems[i] = templateMode
and string.format("{{%s[[%s|%s]]}}", prefix, templatePath, shortcut)
or string.format("[[%s]]", shortcut)
else
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = templateMode and {templatePath, shortcut} or {shortcut, shortcut}
}
if templateMode then
listItems[i] = string.format("{{%s%s}}", prefix, listItems[i])
end
end
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Module:Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
local headingMsg = options['shortcut-heading'] or
redirectMode and cfg['redirect-heading'] or
cfg['shortcut-heading']
shortcutHeading = message(headingMsg, nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain noprint')
:attr('role', 'note')
if options.float and options.float:lower() == 'left' then
shortcutList:addClass('module-shortcutboxleft')
end
if options.clear and options.clear ~= '' then
shortcutList:css('clear', options.clear)
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local ubl = require('Module:List').unbulleted(listItems)
shortcutList:wikitext(ubl)
return tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame)
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._main(shortcuts, options, frame)
end
return p
0grxrt10usr45p0y9yes29aw6xnxg7j
9064
9063
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Shortcut]]
9063
Scribunto
text/plain
-- This module implements {{shortcut}}.
-- Set constants
local CONFIG_MODULE = 'Module:Shortcut/config'
-- Load required modules
local checkType = require('libraryUtil').checkType
local yesno = require('Module:Yesno')
local p = {}
local function message(msg, ...)
return mw.message.newRawMessage(msg, ...):plain()
end
local function makeCategoryLink(cat)
return string.format('[[%s:%s]]', mw.site.namespaces[14].name, cat)
end
function p._main(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local templateMode = options.template and yesno(options.template)
local redirectMode = options.redirect and yesno(options.redirect)
local isCategorized = not options.category or yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
local templatePath, prefix
if templateMode then
-- Namespace detection
local titleObj = mw.title.new(shortcut, 10)
if titleObj.namespace == 10 then
templatePath = titleObj.fullText
else
templatePath = shortcut
end
prefix = options['pre' .. i] or options.pre or ''
end
if options.target and yesno(options.target) then
listItems[i] = templateMode
and string.format("{{%s[[%s|%s]]}}", prefix, templatePath, shortcut)
or string.format("[[%s]]", shortcut)
else
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = templateMode and {templatePath, shortcut} or {shortcut, shortcut}
}
if templateMode then
listItems[i] = string.format("{{%s%s}}", prefix, listItems[i])
end
end
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Module:Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
local headingMsg = options['shortcut-heading'] or
redirectMode and cfg['redirect-heading'] or
cfg['shortcut-heading']
shortcutHeading = message(headingMsg, nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain noprint')
:attr('role', 'note')
if options.float and options.float:lower() == 'left' then
shortcutList:addClass('module-shortcutboxleft')
end
if options.clear and options.clear ~= '' then
shortcutList:css('clear', options.clear)
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local ubl = require('Module:List').unbulleted(listItems)
shortcutList:wikitext(ubl)
return tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame)
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._main(shortcuts, options, frame)
end
return p
0grxrt10usr45p0y9yes29aw6xnxg7j
Module:Shortcut/config
828
1056
9065
2021-02-16T18:43:45Z
en>Nardog
0
9065
Scribunto
text/plain
-- This module holds configuration data for [[Module:Shortcut]].
return {
-- The heading at the top of the shortcut box. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['shortcut-heading'] = '[[Wikipedia:Shortcut|{{PLURAL:$1|Shortcut|Shortcuts}}]]',
-- The heading when |redirect=yes is given. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['redirect-heading'] = '[[Wikipedia:Redirect|{{PLURAL:$1|Redirect|Redirects}}]]',
-- The error message to display when a shortcut is invalid (is not a string, or
-- is the blank string). It accepts the following parameter:
-- $1 - the number of the shortcut in the argument list. (required)
['invalid-shortcut-error'] = 'shortcut #$1 was invalid (shortcuts must be ' ..
'strings of at least one character in length)',
-- The error message to display when no shortcuts or other displayable content
-- were specified. (required)
['no-content-error'] = 'Error: no shortcuts were specified and the ' ..
mw.text.nowiki('|msg=') ..
' parameter was not set.',
-- A category to add when the no-content-error message is displayed. (optional)
['no-content-error-category'] = 'Shortcut templates with missing parameters',
}
t6jiszehpcz1mpvmzl8esji0vdvjr4p
9066
9065
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Shortcut/config]]
9065
Scribunto
text/plain
-- This module holds configuration data for [[Module:Shortcut]].
return {
-- The heading at the top of the shortcut box. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['shortcut-heading'] = '[[Wikipedia:Shortcut|{{PLURAL:$1|Shortcut|Shortcuts}}]]',
-- The heading when |redirect=yes is given. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['redirect-heading'] = '[[Wikipedia:Redirect|{{PLURAL:$1|Redirect|Redirects}}]]',
-- The error message to display when a shortcut is invalid (is not a string, or
-- is the blank string). It accepts the following parameter:
-- $1 - the number of the shortcut in the argument list. (required)
['invalid-shortcut-error'] = 'shortcut #$1 was invalid (shortcuts must be ' ..
'strings of at least one character in length)',
-- The error message to display when no shortcuts or other displayable content
-- were specified. (required)
['no-content-error'] = 'Error: no shortcuts were specified and the ' ..
mw.text.nowiki('|msg=') ..
' parameter was not set.',
-- A category to add when the no-content-error message is displayed. (optional)
['no-content-error-category'] = 'Shortcut templates with missing parameters',
}
t6jiszehpcz1mpvmzl8esji0vdvjr4p
Tempilet:Icon link
10
1057
9067
2024-05-22T19:22:36Z
en>SilverLocust
0
safesubst
9067
wikitext
text/x-wiki
{{SAFESUBST:<noinclude/>#invoke:icon|link}}<noinclude>
{{Documentation}}
</noinclude>
laziz53pk64f56hbi1f4x07wapkwht1
9068
9067
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Icon_link]]
9067
wikitext
text/x-wiki
{{SAFESUBST:<noinclude/>#invoke:icon|link}}<noinclude>
{{Documentation}}
</noinclude>
laziz53pk64f56hbi1f4x07wapkwht1
Tempilet:Inline cleanup tags
10
1058
9073
2026-07-19T10:32:03Z
en>HudecEmil
0
Failed replication
9073
wikitext
text/x-wiki
{{Navbox
| name = Inline cleanup tags
| state = {{{state|autocollapse}}}
| bodyclass = hlist
| title = Inline cleanup tags
| evenodd = off
| group1 = Attribution
| list1 =
* {{tl|According to whom}}
* {{tl|Among whom}}
* {{tl|Attribution needed}}
* {{tl|By what}}
* {{tl|By whom}}
* {{tl|For whom}}
* {{tl|From whom?}}
* {{tl|Like whom?}}
* {{tl|To whom?}}
* {{tl|Who}}
* {{tl|Whose}}
* {{tl|With whom}}
| group2 = Clarity
| list2 =
* {{tl|Ambiguous}}
* {{tl|Circular definition}}
* {{tl|Clarify}}
* {{tl|Clarify span}}
* {{tl|Clarify timeframe}}
* {{tl|Context inline}}
* {{tl|Expand acronym}}
* {{tl|Incomprehensible inline}}
* {{tl|Incomprehensible span}}
* {{tl|Key needed}}
* {{tl|Non sequitur}}
* {{tl|Sentence fragment}}
* {{tl|Sic?}}
* {{tl|Which calendar}}
* {{tl|Which lang}}
| group3 = Miscellaneous
| list3 =
* {{tl|Chinese script needed inline}}
* {{tl|Chinese script needed inline span}}
* {{tl|Cleanup inline}}
* {{tl|Copyvio}}
* {{tl|Copyvio link}}
* {{tl|Data missing}}
* {{tl|Disambiguation needed}}
* {{tl|External links inline}}
* {{tl|Improve caption}}
* {{tl|Japanese script needed inline}}
* {{tl|MisleadingNameLink}}
* {{tl|Needs IPA}}
* {{tl|Not English inline}}
* {{tl|Not in body}}
* {{tl|Original research inline}}
* {{tl|Original research span}}
* {{tl|Pronunciation needed}}
* {{tl|Qualify evidence}}
* {{tl|Romanization needed}}
* {{tl|Script needed inline}}
* {{tl|Spam link}}
* {{tl|Synthesis inline}}
* {{tl|Synthesis span}}
* {{tl|Typo help inline}}
* {{tl|Under discussion inline}}
* {{tl|Verify spelling}}
* {{tl|Whose translation}}
| group4 = Neutrality
| list4 =
* {{tl|Buzzword inline}}
* {{tl|Compared to?}}
* {{tl|Contentious label inline}}
* {{tl|Editorializing}}
* {{tl|Fact or opinion}}
* {{tl|Opinion}}
* {{tl|Peacock inline}}
* {{tl|POV statement}}
* {{tl|Promotion inline}}
* {{tl|Unbalanced opinion}}
* {{tl|Weasel inline}}
| group5 = Precision
| list5 =
{{Navbox |child
| evenodd = off
| list1 =
* {{tl|By how much}}
* {{tl|Definition}}
* {{tl|Definition span}}
* {{tl|Definition needed}}
* {{tl|Example needed}}
* {{tl|Example needed span}}
* {{tl|Explain}}
* {{tl|Explain-wrap}}
* {{tl|From where}}
* {{tl|How}}
* {{tl|How often}}
* {{tl|Misquoted}}
* {{tl|More detail needed}}
* {{tl|Of what}}
* {{tl|Quantify}}
* {{tl|Specify}}
* {{tl|Vague}}
* {{tl|When}}
* {{tl|Where}}
* {{tl|Where-geo}}
* {{tl|Which}}
* {{tl|Who else}}
* {{tl|Why}}
* {{tl|Year needed}}
| group2 = Excessive
| list2 =
* {{tl|Duplication span}}
* {{tl|Globalize inline}}
* {{tl|Importance example}}
* {{tl|Importance inline}}
* {{tl|Infobox clutter}}
* {{tl|List entry too long}}
* {{tl|Long quote}}
* {{tl|Off topic paragraph}}
* {{tl|Off topic sentence}}
* {{tl|Overly detailed inline}}
* {{tl|Over-explained}}
* {{tl|Relevance inline}}
* {{tl|Undue weight inline}}
}}
| group6 = Time-sensitivity
| list6 =
* {{tl|Anachronism inline}}
* {{tl|As of?}}
* {{tl|Clarify timeframe}}
* {{tl|Current event inline}}
* {{tl|Is this date calibrated?}}
* {{tl|Outdated statistic}}
* {{tl|Until when}}
* {{tl|Update after}}
* {{tl|Update inline}}
* {{tl|Update span}}
| group7 = Verifiability
| list7 =
{{Navbox|child
| evenodd = off
| groupstyle = white-space: normal;
| group1 = Dubious
| list1 =
* {{tl|Contradictory inline}}
* {{tl|Discuss}}
* {{tl|Disputed inline}}
* {{tl|Dubious}}
* {{tl|Dubious span}}
* {{tl|Inconsistent}}
* {{tl|Needs independent confirmation}}
* {{tl|Speculation inline}}
| group2 = [[WP:Bare URLs|Bare URLs]]
| list2 =
* {{tl|Bare URL inline}}
* {{tl|Bare URL AV media}}
* {{tl|Bare URL DOC}}
* {{tl|Bare URL image}}
* {{tl|Bare URL non-HTML}}
* {{tl|Bare URL PDF}}
* {{tl|Bare URL plain text}}
* {{tl|Bare URL spreadsheet}}
| group3 = Incomplete or broken citation
| list3 =
* {{tl|Author incomplete}}
* {{tl|Author missing}}
* {{tl|Broken footnote}}
* {{tl|Date missing}}
* {{tl|Dead link}}
* {{tl|Dead YouTube link}}
* {{tl|Deep link needed}}
* {{tl|Edition needed}}
* {{tl|Episode needed}}
* {{tl|Full citation needed}}
* {{tl|Incomplete short citation}}
* {{tl|ISBN missing}}
* {{tl|Missing long citation}}
* {{tl|Moved resource}}
* {{tl|Page needed}}
* {{tl|Pages needed}}
* {{tl|Permanent dead link}}
* {{tl|Place missing}}
* {{tl|Publisher missing}}
* {{tl|Season needed}}
* {{tl|Time needed}}
* {{tl|Title incomplete}}
* {{tl|Title missing}}
* {{tl|Unused source}}
* {{tl|Volume needed}}
* {{tl|Year missing}}
| group4 = Missing or problematic reference
| list4 =
* {{tl|Additional citation needed}}
* {{tl|AI-generated inline}}
* {{tl|AI-generated source?}}
* {{tl|AI-retrieved source}}
* {{tl|Better source needed}}
* {{tl|Better source needed example}}
* {{tl|Check quotation}}
* {{tl|Chronology citation needed}}
* {{tl|Circular reference}}
* {{tl|Circular reporting}}
* {{tl|Citation needed}}
* {{tl|Citation needed span}}
* {{tl|Citation needed paragraph}}
* {{tl|Citation not found}}
* {{tl|Close paraphrasing inline}}
* {{tl|COI source}}
* {{tl|Deprecated inline}}
* {{tl|Excessive citations inline}}
* {{tl|Failed replication}}
* {{tl|Failed verification}}
* {{tl|Failed verification span}}
* {{tl|Image reference needed}}
* {{tl|Independent source inline}}
* {{tl|Irrelevant citation}}
* {{tl|Marketing material}}
* {{tl|Medical citation needed}}
* {{tl|Medical citation needed span}}
* {{tl|Misplaced footnote}}
* {{tl|Nonspecific}}
* {{tl|Not verified in body}}
* {{tl|Not verified in body span}}
* {{tl|Obsolete source}}
* {{tl|Page range too broad}}
* {{tl|Primary source inline}}
* {{tl|Promotional source}}
* {{tl|Quote without source}}
* {{tl|Request quotation}}
* {{tl|Request quotation span}}
* {{tl|Retracted}}
* {{tl|Scientific citation needed}}
* {{tl|Self-published inline}}
* {{tl|Self-published source}}
* {{tl|Shallow reference inline}}
* {{tl|Tertiary source inline}}
* {{tl|Text-source inline}}
* {{tl|Unreliable source?}}
* {{tl|Unreliable fringe source}}
* {{tl|Unreliable medical source}}
* {{tl|Unreliable scientific source}}
* {{tl|User-generated inline}}
* {{tl|User-generated source}}
* {{tl|Verify quote}}
* {{tl|Verify source}}
* {{tl|Whose quote}}
}}
| group8 = Wording
| list8 =
* {{tl|Buzzword inline}}
* {{tl|Colloquialism}}
* {{tl|Copy edit inline}}
* {{tl|Copy edit span}}
* {{tl|Idiom}}
* {{tl|Neologism inline}}
* {{tl|Technical inline}}
* {{tl|Tone inline}}
| group9 = General advice
| list9 =
* [[Wikipedia:Citing sources|Citing sources]]
* [[Wikipedia:Reliable sources|Reliable sources]]
* [[Help:Maintenance template removal |Maintenance template removal]]
* [[Wikipedia:Citation needed|Citation needed]]
* [[Help:Find sources|Find sources]]
* [[Wikipedia:Combining sources|Combining sources]]
* [[Help:Overview of referencing styles|Referencing styles]]
| belowstyle = font-weight:bold;
| below =
* {{icon|Category}} {{Category link without namespace|Inline cleanup templates}}
* {{icon link|WikiProject|Wikipedia:WikiProject Inline Templates|WikiProject Inline Templates}}
}}<noinclude>
{{documentation}}
</noinclude>
nh35a4fk2wzfjkxt7z31dnlhegw5g2a
9074
9073
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Inline_cleanup_tags]]
9073
wikitext
text/x-wiki
{{Navbox
| name = Inline cleanup tags
| state = {{{state|autocollapse}}}
| bodyclass = hlist
| title = Inline cleanup tags
| evenodd = off
| group1 = Attribution
| list1 =
* {{tl|According to whom}}
* {{tl|Among whom}}
* {{tl|Attribution needed}}
* {{tl|By what}}
* {{tl|By whom}}
* {{tl|For whom}}
* {{tl|From whom?}}
* {{tl|Like whom?}}
* {{tl|To whom?}}
* {{tl|Who}}
* {{tl|Whose}}
* {{tl|With whom}}
| group2 = Clarity
| list2 =
* {{tl|Ambiguous}}
* {{tl|Circular definition}}
* {{tl|Clarify}}
* {{tl|Clarify span}}
* {{tl|Clarify timeframe}}
* {{tl|Context inline}}
* {{tl|Expand acronym}}
* {{tl|Incomprehensible inline}}
* {{tl|Incomprehensible span}}
* {{tl|Key needed}}
* {{tl|Non sequitur}}
* {{tl|Sentence fragment}}
* {{tl|Sic?}}
* {{tl|Which calendar}}
* {{tl|Which lang}}
| group3 = Miscellaneous
| list3 =
* {{tl|Chinese script needed inline}}
* {{tl|Chinese script needed inline span}}
* {{tl|Cleanup inline}}
* {{tl|Copyvio}}
* {{tl|Copyvio link}}
* {{tl|Data missing}}
* {{tl|Disambiguation needed}}
* {{tl|External links inline}}
* {{tl|Improve caption}}
* {{tl|Japanese script needed inline}}
* {{tl|MisleadingNameLink}}
* {{tl|Needs IPA}}
* {{tl|Not English inline}}
* {{tl|Not in body}}
* {{tl|Original research inline}}
* {{tl|Original research span}}
* {{tl|Pronunciation needed}}
* {{tl|Qualify evidence}}
* {{tl|Romanization needed}}
* {{tl|Script needed inline}}
* {{tl|Spam link}}
* {{tl|Synthesis inline}}
* {{tl|Synthesis span}}
* {{tl|Typo help inline}}
* {{tl|Under discussion inline}}
* {{tl|Verify spelling}}
* {{tl|Whose translation}}
| group4 = Neutrality
| list4 =
* {{tl|Buzzword inline}}
* {{tl|Compared to?}}
* {{tl|Contentious label inline}}
* {{tl|Editorializing}}
* {{tl|Fact or opinion}}
* {{tl|Opinion}}
* {{tl|Peacock inline}}
* {{tl|POV statement}}
* {{tl|Promotion inline}}
* {{tl|Unbalanced opinion}}
* {{tl|Weasel inline}}
| group5 = Precision
| list5 =
{{Navbox |child
| evenodd = off
| list1 =
* {{tl|By how much}}
* {{tl|Definition}}
* {{tl|Definition span}}
* {{tl|Definition needed}}
* {{tl|Example needed}}
* {{tl|Example needed span}}
* {{tl|Explain}}
* {{tl|Explain-wrap}}
* {{tl|From where}}
* {{tl|How}}
* {{tl|How often}}
* {{tl|Misquoted}}
* {{tl|More detail needed}}
* {{tl|Of what}}
* {{tl|Quantify}}
* {{tl|Specify}}
* {{tl|Vague}}
* {{tl|When}}
* {{tl|Where}}
* {{tl|Where-geo}}
* {{tl|Which}}
* {{tl|Who else}}
* {{tl|Why}}
* {{tl|Year needed}}
| group2 = Excessive
| list2 =
* {{tl|Duplication span}}
* {{tl|Globalize inline}}
* {{tl|Importance example}}
* {{tl|Importance inline}}
* {{tl|Infobox clutter}}
* {{tl|List entry too long}}
* {{tl|Long quote}}
* {{tl|Off topic paragraph}}
* {{tl|Off topic sentence}}
* {{tl|Overly detailed inline}}
* {{tl|Over-explained}}
* {{tl|Relevance inline}}
* {{tl|Undue weight inline}}
}}
| group6 = Time-sensitivity
| list6 =
* {{tl|Anachronism inline}}
* {{tl|As of?}}
* {{tl|Clarify timeframe}}
* {{tl|Current event inline}}
* {{tl|Is this date calibrated?}}
* {{tl|Outdated statistic}}
* {{tl|Until when}}
* {{tl|Update after}}
* {{tl|Update inline}}
* {{tl|Update span}}
| group7 = Verifiability
| list7 =
{{Navbox|child
| evenodd = off
| groupstyle = white-space: normal;
| group1 = Dubious
| list1 =
* {{tl|Contradictory inline}}
* {{tl|Discuss}}
* {{tl|Disputed inline}}
* {{tl|Dubious}}
* {{tl|Dubious span}}
* {{tl|Inconsistent}}
* {{tl|Needs independent confirmation}}
* {{tl|Speculation inline}}
| group2 = [[WP:Bare URLs|Bare URLs]]
| list2 =
* {{tl|Bare URL inline}}
* {{tl|Bare URL AV media}}
* {{tl|Bare URL DOC}}
* {{tl|Bare URL image}}
* {{tl|Bare URL non-HTML}}
* {{tl|Bare URL PDF}}
* {{tl|Bare URL plain text}}
* {{tl|Bare URL spreadsheet}}
| group3 = Incomplete or broken citation
| list3 =
* {{tl|Author incomplete}}
* {{tl|Author missing}}
* {{tl|Broken footnote}}
* {{tl|Date missing}}
* {{tl|Dead link}}
* {{tl|Dead YouTube link}}
* {{tl|Deep link needed}}
* {{tl|Edition needed}}
* {{tl|Episode needed}}
* {{tl|Full citation needed}}
* {{tl|Incomplete short citation}}
* {{tl|ISBN missing}}
* {{tl|Missing long citation}}
* {{tl|Moved resource}}
* {{tl|Page needed}}
* {{tl|Pages needed}}
* {{tl|Permanent dead link}}
* {{tl|Place missing}}
* {{tl|Publisher missing}}
* {{tl|Season needed}}
* {{tl|Time needed}}
* {{tl|Title incomplete}}
* {{tl|Title missing}}
* {{tl|Unused source}}
* {{tl|Volume needed}}
* {{tl|Year missing}}
| group4 = Missing or problematic reference
| list4 =
* {{tl|Additional citation needed}}
* {{tl|AI-generated inline}}
* {{tl|AI-generated source?}}
* {{tl|AI-retrieved source}}
* {{tl|Better source needed}}
* {{tl|Better source needed example}}
* {{tl|Check quotation}}
* {{tl|Chronology citation needed}}
* {{tl|Circular reference}}
* {{tl|Circular reporting}}
* {{tl|Citation needed}}
* {{tl|Citation needed span}}
* {{tl|Citation needed paragraph}}
* {{tl|Citation not found}}
* {{tl|Close paraphrasing inline}}
* {{tl|COI source}}
* {{tl|Deprecated inline}}
* {{tl|Excessive citations inline}}
* {{tl|Failed replication}}
* {{tl|Failed verification}}
* {{tl|Failed verification span}}
* {{tl|Image reference needed}}
* {{tl|Independent source inline}}
* {{tl|Irrelevant citation}}
* {{tl|Marketing material}}
* {{tl|Medical citation needed}}
* {{tl|Medical citation needed span}}
* {{tl|Misplaced footnote}}
* {{tl|Nonspecific}}
* {{tl|Not verified in body}}
* {{tl|Not verified in body span}}
* {{tl|Obsolete source}}
* {{tl|Page range too broad}}
* {{tl|Primary source inline}}
* {{tl|Promotional source}}
* {{tl|Quote without source}}
* {{tl|Request quotation}}
* {{tl|Request quotation span}}
* {{tl|Retracted}}
* {{tl|Scientific citation needed}}
* {{tl|Self-published inline}}
* {{tl|Self-published source}}
* {{tl|Shallow reference inline}}
* {{tl|Tertiary source inline}}
* {{tl|Text-source inline}}
* {{tl|Unreliable source?}}
* {{tl|Unreliable fringe source}}
* {{tl|Unreliable medical source}}
* {{tl|Unreliable scientific source}}
* {{tl|User-generated inline}}
* {{tl|User-generated source}}
* {{tl|Verify quote}}
* {{tl|Verify source}}
* {{tl|Whose quote}}
}}
| group8 = Wording
| list8 =
* {{tl|Buzzword inline}}
* {{tl|Colloquialism}}
* {{tl|Copy edit inline}}
* {{tl|Copy edit span}}
* {{tl|Idiom}}
* {{tl|Neologism inline}}
* {{tl|Technical inline}}
* {{tl|Tone inline}}
| group9 = General advice
| list9 =
* [[Wikipedia:Citing sources|Citing sources]]
* [[Wikipedia:Reliable sources|Reliable sources]]
* [[Help:Maintenance template removal |Maintenance template removal]]
* [[Wikipedia:Citation needed|Citation needed]]
* [[Help:Find sources|Find sources]]
* [[Wikipedia:Combining sources|Combining sources]]
* [[Help:Overview of referencing styles|Referencing styles]]
| belowstyle = font-weight:bold;
| below =
* {{icon|Category}} {{Category link without namespace|Inline cleanup templates}}
* {{icon link|WikiProject|Wikipedia:WikiProject Inline Templates|WikiProject Inline Templates}}
}}<noinclude>
{{documentation}}
</noinclude>
nh35a4fk2wzfjkxt7z31dnlhegw5g2a
Module:Transclusion count/data/D
828
1059
9075
2026-08-16T05:07:20Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9075
Scribunto
text/plain
return {
["D&D_to-do"] = 6600,
["DANFS"] = 8100,
["DBCatsURL"] = 2000,
["DCS_Sri_Lanka"] = 2000,
["DDR"] = 2900,
["DEC"] = 11000,
["DECADE"] = 321000,
["DEN"] = 7500,
["DEU"] = 19000,
["DGRBM"] = 2000,
["DMC"] = 54000,
["DMCA"] = 3280000,
["DNB"] = 9600,
["DNB-Portal"] = 2300,
["DNB_portal"] = 3600,
["DNK"] = 8600,
["DNZB"] = 3700,
["DOM"] = 2400,
["DOWs"] = 2800,
["DRV_links"] = 4300,
["DWT"] = 2600,
["DYKC"] = 6700,
["DYKF"] = 2100,
["DYK_blue"] = 3400,
["DYK_checklist"] = 24000,
["DYK_conditions"] = 64000,
["DYK_files"] = 2100,
["DYK_header"] = 58000,
["DYK_nompage_links"] = 103000,
["DYK_talk"] = 110000,
["DYK_talk/date"] = 110000,
["DYK_tools"] = 81000,
["DYK_tools/styles.css"] = 81000,
["DYKfile"] = 13000,
["DZA"] = 3100,
["Dab"] = 21000,
["Dagger"] = 25000,
["Dark_red"] = 3400,
["Darkred"] = 3200,
["Dash"] = 2700,
["Dashboard.wikiedu.org_assignment"] = 35000,
["Dashboard.wikiedu.org_bibliography/bibliography"] = 12000,
["Dashboard.wikiedu.org_bibliography/guide"] = 19000,
["Dashboard.wikiedu.org_bibliography/outline"] = 12000,
["Dashboard.wikiedu.org_course_header"] = 8300,
["Dashboard.wikiedu.org_course_header/edit-note"] = 8300,
["Dashboard.wikiedu.org_draft_template/about_this_sandbox"] = 20000,
["Dashboard.wikiedu.org_evaluate_article/guide"] = 24000,
["Dashboard.wikiedu.org_peer_review/guide"] = 27000,
["Dashboard.wikiedu.org_sandbox"] = 129000,
["Dashboard.wikiedu.org_student_editor"] = 118000,
["Dashboard.wikiedu.org_student_program_sandbox"] = 128000,
["Dashboard.wikiedu.org_talk_course_link"] = 120000,
["Dashboard.wikiedu.org_user_talk"] = 2200,
["Date"] = 53000,
["Date-mf"] = 64000,
["Date_table_sorting"] = 46000,
["Dated_maintenance_category"] = 3370000,
["Dated_maintenance_category_(articles)"] = 3320000,
["Dated_maintenance_category_by_type_(articles)"] = 23000,
["Davis_Cup_player"] = 2600,
["Day+1"] = 6900,
["Day-1"] = 8300,
["Dbox"] = 3000,
["Dda"] = 2900,
["Dead_YouTube_link"] = 2300,
["Dead_link"] = 374000,
["Deadweight_tonnage"] = 2700,
["Death-date_and_age"] = 5500,
["Death_date"] = 15000,
["Death_date_and_age"] = 532000,
["Death_date_and_given_age"] = 4600,
["Death_date_text"] = 6100,
["Death_year"] = 4500,
["Death_year_and_age"] = 29000,
["Death_year_category_header"] = 2000,
["Decade_link"] = 38000,
["Decimals"] = 3600,
["Declination"] = 11000,
["Decline"] = 2700,
["Declined"] = 3600,
["Decrease"] = 51000,
["Define"] = 4300,
["Deg2DMS"] = 3300,
["Deleted_on_Commons"] = 5700,
["Deletion_review_log_header"] = 6700,
["Deletion_review_log_header/Core"] = 6700,
["Delink"] = 1950000,
["Delink_question_hyphen-minus"] = 443000,
["Delrevxfd"] = 4000,
["Democratic_Party_(US)/meta/shading"] = 19000,
["Deprecated_archive"] = 47000,
["Description_missing"] = 5500,
["Designation/text"] = 18000,
["Designation_list"] = 7700,
["Details"] = 3400,
["DetailsLink"] = 5400,
["Details_link"] = 6500,
["Detect_singular"] = 256000,
["Deutsche_Bahn_station_codes"] = 2200,
["DfE_performance_tables"] = 4500,
["Dictionary_of_National_Biography"] = 9600,
["Diff"] = 33000,
["Diff2"] = 15000,
["Diffusing_occupation_by_nationality_and_century_category_header"] = 4300,
["Diffusing_occupation_by_nationality_and_century_category_header/core"] = 7600,
["Digits"] = 6200,
["Directories_box"] = 3200,
["Disamb"] = 2200,
["Disambig"] = 63000,
["Disambig-Class"] = 12000,
["Disambiguation"] = 235000,
["Disambiguation/cat"] = 234000,
["Disambiguation_page_short_description"] = 380000,
["Discogs_artist"] = 25000,
["Discogs_master"] = 16000,
["Discogs_release"] = 3700,
["Discussion_bottom"] = 14000,
["Discussion_top"] = 15000,
["Disestablishment_category_in_country"] = 10000,
["Disestablishment_category_in_country/core"] = 10000,
["Disestablishment_category_in_country_by_decade"] = 2600,
["Disestablishment_category_in_country_by_decade/core"] = 2600,
["DisestcatCountry"] = 10000,
["DisestcatCountry/core"] = 10000,
["DisestcatUSstate"] = 5200,
["DisestcatUSstate/core"] = 5200,
["Disputed"] = 2100,
["Distinguish"] = 128000,
["Disused_Rail_Start"] = 4000,
["Disused_rail_start"] = 4300,
["Div_col"] = 496000,
["Div_col/styles.css"] = 498000,
["Div_col_end"] = 361000,
["Divbox"] = 490000,
["Divbox/styles.css"] = 490000,
["Dividing_line"] = 4500,
["Dmbox"] = 510000,
["Dmbox/styles.css"] = 510000,
["Do_not_move_to_Commons"] = 24000,
["Doc"] = 3800,
["Documentation"] = 153000,
["Documentation_subpage"] = 101000,
["Dog_opentask"] = 4200,
["Doi"] = 29000,
["Doing"] = 4100,
["Don't_edit_this_line"] = 150000,
["Don't_edit_this_line_always_display"] = 653000,
["Don't_edit_this_line_extinct"] = 653000,
["Don't_edit_this_line_link_target"] = 653000,
["Don't_edit_this_line_link_text"] = 653000,
["Don't_edit_this_line_parent"] = 653000,
["Don't_edit_this_line_rank"] = 653000,
["Don't_edit_this_line_refs"] = 150000,
["Don't_edit_this_line_same_as"] = 653000,
["Done"] = 124000,
["Doppelganger"] = 2900,
["Double+single"] = 4400,
["Double-dagger"] = 29000,
["Dow_tooltip"] = 2500,
["Dr"] = 3400,
["Dr-logno"] = 3400,
["Dr-make"] = 3400,
["Dr-yr"] = 3400,
["Draft_article"] = 10000,
["Draft_article_check"] = 10000,
["Draft_categories"] = 10000,
["Draft_other"] = 117000,
["Draft_topics"] = 29000,
["Drafts_moved_from_mainspace"] = 9300,
["Draw"] = 4700,
["Draw_key"] = 21000,
["Draw_links"] = 16000,
["Drep"] = 3400,
["DriverDB_driver"] = 2900,
["Drugbankcite"] = 4200,
["Drugbox"] = 6300,
["Drugs.com"] = 3300,
["Dts"] = 44000,
["Dubious"] = 8600,
["Duck"] = 3300,
["Dummytab"] = 6700,
["Duration"] = 44000,
["Dutch_municipality"] = 2700,
["Dyktalk"] = 39000,
["Dynamic_list"] = 14000,
["Module:DYK_checklist"] = 24000,
["Module:DYK_checklist/data"] = 24000,
["Module:DYK_nompage_links"] = 103000,
["Module:Data"] = 111000,
["Module:Date"] = 2110000,
["Module:DateI18n"] = 47000,
["Module:Date_table_sorting"] = 49000,
["Module:Date_time"] = 563000,
["Module:DecodeEncode"] = 149000,
["Module:Delink"] = 4340000,
["Module:Deprecated_archive"] = 47000,
["Module:Designation"] = 106000,
["Module:Designation/list"] = 106000,
["Module:Designation/lookup"] = 25000,
["Module:Detect_singular"] = 3070000,
["Module:Diff"] = 3400,
["Module:Disambiguation"] = 23000,
["Module:Disambiguation/templates"] = 13300000,
["Module:Distinguish"] = 128000,
["Module:Documentation"] = 208000,
["Module:Documentation/config"] = 208000,
["Module:Documentation/styles.css"] = 207000,
["Module:Domain_handler"] = 14000,
["Module:Draft_topics"] = 29000,
["Module:Dts"] = 3400,
["Module:Duration"] = 253000,
}
l2rfzbl0htdohf4kjhqjtweo1vmuidf
9076
9075
2026-08-22T12:06:29Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/D]]
9075
Scribunto
text/plain
return {
["D&D_to-do"] = 6600,
["DANFS"] = 8100,
["DBCatsURL"] = 2000,
["DCS_Sri_Lanka"] = 2000,
["DDR"] = 2900,
["DEC"] = 11000,
["DECADE"] = 321000,
["DEN"] = 7500,
["DEU"] = 19000,
["DGRBM"] = 2000,
["DMC"] = 54000,
["DMCA"] = 3280000,
["DNB"] = 9600,
["DNB-Portal"] = 2300,
["DNB_portal"] = 3600,
["DNK"] = 8600,
["DNZB"] = 3700,
["DOM"] = 2400,
["DOWs"] = 2800,
["DRV_links"] = 4300,
["DWT"] = 2600,
["DYKC"] = 6700,
["DYKF"] = 2100,
["DYK_blue"] = 3400,
["DYK_checklist"] = 24000,
["DYK_conditions"] = 64000,
["DYK_files"] = 2100,
["DYK_header"] = 58000,
["DYK_nompage_links"] = 103000,
["DYK_talk"] = 110000,
["DYK_talk/date"] = 110000,
["DYK_tools"] = 81000,
["DYK_tools/styles.css"] = 81000,
["DYKfile"] = 13000,
["DZA"] = 3100,
["Dab"] = 21000,
["Dagger"] = 25000,
["Dark_red"] = 3400,
["Darkred"] = 3200,
["Dash"] = 2700,
["Dashboard.wikiedu.org_assignment"] = 35000,
["Dashboard.wikiedu.org_bibliography/bibliography"] = 12000,
["Dashboard.wikiedu.org_bibliography/guide"] = 19000,
["Dashboard.wikiedu.org_bibliography/outline"] = 12000,
["Dashboard.wikiedu.org_course_header"] = 8300,
["Dashboard.wikiedu.org_course_header/edit-note"] = 8300,
["Dashboard.wikiedu.org_draft_template/about_this_sandbox"] = 20000,
["Dashboard.wikiedu.org_evaluate_article/guide"] = 24000,
["Dashboard.wikiedu.org_peer_review/guide"] = 27000,
["Dashboard.wikiedu.org_sandbox"] = 129000,
["Dashboard.wikiedu.org_student_editor"] = 118000,
["Dashboard.wikiedu.org_student_program_sandbox"] = 128000,
["Dashboard.wikiedu.org_talk_course_link"] = 120000,
["Dashboard.wikiedu.org_user_talk"] = 2200,
["Date"] = 53000,
["Date-mf"] = 64000,
["Date_table_sorting"] = 46000,
["Dated_maintenance_category"] = 3370000,
["Dated_maintenance_category_(articles)"] = 3320000,
["Dated_maintenance_category_by_type_(articles)"] = 23000,
["Davis_Cup_player"] = 2600,
["Day+1"] = 6900,
["Day-1"] = 8300,
["Dbox"] = 3000,
["Dda"] = 2900,
["Dead_YouTube_link"] = 2300,
["Dead_link"] = 374000,
["Deadweight_tonnage"] = 2700,
["Death-date_and_age"] = 5500,
["Death_date"] = 15000,
["Death_date_and_age"] = 532000,
["Death_date_and_given_age"] = 4600,
["Death_date_text"] = 6100,
["Death_year"] = 4500,
["Death_year_and_age"] = 29000,
["Death_year_category_header"] = 2000,
["Decade_link"] = 38000,
["Decimals"] = 3600,
["Declination"] = 11000,
["Decline"] = 2700,
["Declined"] = 3600,
["Decrease"] = 51000,
["Define"] = 4300,
["Deg2DMS"] = 3300,
["Deleted_on_Commons"] = 5700,
["Deletion_review_log_header"] = 6700,
["Deletion_review_log_header/Core"] = 6700,
["Delink"] = 1950000,
["Delink_question_hyphen-minus"] = 443000,
["Delrevxfd"] = 4000,
["Democratic_Party_(US)/meta/shading"] = 19000,
["Deprecated_archive"] = 47000,
["Description_missing"] = 5500,
["Designation/text"] = 18000,
["Designation_list"] = 7700,
["Details"] = 3400,
["DetailsLink"] = 5400,
["Details_link"] = 6500,
["Detect_singular"] = 256000,
["Deutsche_Bahn_station_codes"] = 2200,
["DfE_performance_tables"] = 4500,
["Dictionary_of_National_Biography"] = 9600,
["Diff"] = 33000,
["Diff2"] = 15000,
["Diffusing_occupation_by_nationality_and_century_category_header"] = 4300,
["Diffusing_occupation_by_nationality_and_century_category_header/core"] = 7600,
["Digits"] = 6200,
["Directories_box"] = 3200,
["Disamb"] = 2200,
["Disambig"] = 63000,
["Disambig-Class"] = 12000,
["Disambiguation"] = 235000,
["Disambiguation/cat"] = 234000,
["Disambiguation_page_short_description"] = 380000,
["Discogs_artist"] = 25000,
["Discogs_master"] = 16000,
["Discogs_release"] = 3700,
["Discussion_bottom"] = 14000,
["Discussion_top"] = 15000,
["Disestablishment_category_in_country"] = 10000,
["Disestablishment_category_in_country/core"] = 10000,
["Disestablishment_category_in_country_by_decade"] = 2600,
["Disestablishment_category_in_country_by_decade/core"] = 2600,
["DisestcatCountry"] = 10000,
["DisestcatCountry/core"] = 10000,
["DisestcatUSstate"] = 5200,
["DisestcatUSstate/core"] = 5200,
["Disputed"] = 2100,
["Distinguish"] = 128000,
["Disused_Rail_Start"] = 4000,
["Disused_rail_start"] = 4300,
["Div_col"] = 496000,
["Div_col/styles.css"] = 498000,
["Div_col_end"] = 361000,
["Divbox"] = 490000,
["Divbox/styles.css"] = 490000,
["Dividing_line"] = 4500,
["Dmbox"] = 510000,
["Dmbox/styles.css"] = 510000,
["Do_not_move_to_Commons"] = 24000,
["Doc"] = 3800,
["Documentation"] = 153000,
["Documentation_subpage"] = 101000,
["Dog_opentask"] = 4200,
["Doi"] = 29000,
["Doing"] = 4100,
["Don't_edit_this_line"] = 150000,
["Don't_edit_this_line_always_display"] = 653000,
["Don't_edit_this_line_extinct"] = 653000,
["Don't_edit_this_line_link_target"] = 653000,
["Don't_edit_this_line_link_text"] = 653000,
["Don't_edit_this_line_parent"] = 653000,
["Don't_edit_this_line_rank"] = 653000,
["Don't_edit_this_line_refs"] = 150000,
["Don't_edit_this_line_same_as"] = 653000,
["Done"] = 124000,
["Doppelganger"] = 2900,
["Double+single"] = 4400,
["Double-dagger"] = 29000,
["Dow_tooltip"] = 2500,
["Dr"] = 3400,
["Dr-logno"] = 3400,
["Dr-make"] = 3400,
["Dr-yr"] = 3400,
["Draft_article"] = 10000,
["Draft_article_check"] = 10000,
["Draft_categories"] = 10000,
["Draft_other"] = 117000,
["Draft_topics"] = 29000,
["Drafts_moved_from_mainspace"] = 9300,
["Draw"] = 4700,
["Draw_key"] = 21000,
["Draw_links"] = 16000,
["Drep"] = 3400,
["DriverDB_driver"] = 2900,
["Drugbankcite"] = 4200,
["Drugbox"] = 6300,
["Drugs.com"] = 3300,
["Dts"] = 44000,
["Dubious"] = 8600,
["Duck"] = 3300,
["Dummytab"] = 6700,
["Duration"] = 44000,
["Dutch_municipality"] = 2700,
["Dyktalk"] = 39000,
["Dynamic_list"] = 14000,
["Module:DYK_checklist"] = 24000,
["Module:DYK_checklist/data"] = 24000,
["Module:DYK_nompage_links"] = 103000,
["Module:Data"] = 111000,
["Module:Date"] = 2110000,
["Module:DateI18n"] = 47000,
["Module:Date_table_sorting"] = 49000,
["Module:Date_time"] = 563000,
["Module:DecodeEncode"] = 149000,
["Module:Delink"] = 4340000,
["Module:Deprecated_archive"] = 47000,
["Module:Designation"] = 106000,
["Module:Designation/list"] = 106000,
["Module:Designation/lookup"] = 25000,
["Module:Detect_singular"] = 3070000,
["Module:Diff"] = 3400,
["Module:Disambiguation"] = 23000,
["Module:Disambiguation/templates"] = 13300000,
["Module:Distinguish"] = 128000,
["Module:Documentation"] = 208000,
["Module:Documentation/config"] = 208000,
["Module:Documentation/styles.css"] = 207000,
["Module:Domain_handler"] = 14000,
["Module:Draft_topics"] = 29000,
["Module:Dts"] = 3400,
["Module:Duration"] = 253000,
}
l2rfzbl0htdohf4kjhqjtweo1vmuidf
Tempilet:Cite xxx
10
1060
9077
2025-03-25T18:00:30Z
en>MusikBot II
0
Protected "[[Template:Cite xxx]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 250 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9077
wikitext
text/x-wiki
{{#tag:{{#if:{{{1|}}}|code|span}}|{{<nowiki />[[Wikipedia:Citation templates#Examples|cite xxx]]{{#if:{{{1|}}}|{{!}}{{{1}}}}}<nowiki />}}}}<noinclude>
{{documentation}}
</noinclude>
mv4hr72y8xiqgv9ztqqttizgnx77znr
9078
9077
2026-08-22T12:06:30Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cite_xxx]]
9077
wikitext
text/x-wiki
{{#tag:{{#if:{{{1|}}}|code|span}}|{{<nowiki />[[Wikipedia:Citation templates#Examples|cite xxx]]{{#if:{{{1|}}}|{{!}}{{{1}}}}}<nowiki />}}}}<noinclude>
{{documentation}}
</noinclude>
mv4hr72y8xiqgv9ztqqttizgnx77znr
Tempilet:Dead link/doc
10
1061
9079
2026-07-19T13:28:30Z
en>W.andrea
0
/* TemplateData */ Might as well set an autovalue for "fix attempted". It's not a boolean, strictly speaking.
9079
wikitext
text/x-wiki
{{redirect|Template:DL|the equivalent of the HTML {{tag|dl|o}} tag|Template:Glossary|"described" links|Template:Annotated link}}
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])--><noinclude>
{{pp-template|small=yes}}</noinclude>{{High-use}}
<!-- Redirect regex: [Dd]ead[ _]+link|[Dd]l|[Dd]eadlink|[Cc]leanup-link|[Dd]l-s|404|[Bb]roken[ _]+link|[Bb]rokenlink -->
{{Template shortcut|404|dl|deadlink|dead|Broken link|broken}}
This template is used to mark [[WP:Link rot|dead links]], either within a paragraph or within a [[WP:Citing sources |reference citation]]. Marking dead links signals to editors and to [[WP:Link rot]] bots that this link needs to be replaced with an archive link. Sometimes dead links can be repaired manually; see [[Link rot]] for suggestions.
== Usage ==
Before considering whether to use the {{tl|dead link}} template it is often useful to make a search for an [[Wikipedia:LR#Internet archives|archive copy]] of the dead link, or find the new URL of a moved link or an alternative source using methods from [[WP:DEADLINK]], and thereby avoid using the tag altogether. All {{cite xxx}} templates have the facility for adding {{para|archive-date}} and {{para|archive-url}} parameters for linking to an archive copy. Non-{{cite xxx}} citations can use {{tl|webarchive}}.
Using {{Tl|Dead link}} will place a note by the URL and add the article to one of the [[:Category:Articles with dead external links]] categories.
Append this template '''directly after''' the link (after the link code's terminating <code>]</code> if you are using [[wikitext]]), or, if you are using a {{cite xxx}} template, '''directly after''' the {{cite xxx}} transclusion (not inside it), but inside the reference, if any, i.e. before the <code></ref></code>, in all cases leaving the original link intact:
: <code><nowiki><ref>{{cite web|url=http://www.example.org|title=The Example Website|access-date=22 September 2012}}</nowiki><b style="color:green"><nowiki>{{Dead link|date=</nowiki>{{CURRENTMONTHNAME}} {{CURRENTYEAR}}<nowiki>}}</nowiki></b><nowiki></ref></nowiki></code>
For bare links, leave a space after the end of the URL and the template:
:<code>* http://www.example.org <nowiki>{{Dead link|date=</nowiki>{{CURRENTMONTHNAME}} {{CURRENTYEAR}}<nowiki>}}</nowiki></code>
Otherwise automated tools can have trouble determining where the URL ends, because it will ambiguously contain [[percent encoding|URL-encoding]] and wiki-encoding mixed together.
Not following these syntax rules might hinder detection by automated tools. If the citation contains multiple URLs (e.g. chapter-url and url) in a template, and only one is broken, you can use wiki comments like <code><nowiki><!-- <your hidden explanation here> --></nowiki></code> to explain which one is broken.
If the article uses [[WP:Footnotes|clickable footnotes]], then this template should be placed just before the <code></ref></code> that contains the dead link. The notice will then correctly appear in the reference section instead of in the body of the text, and so [[WP:Link rot]] bots can properly find and fix the link.
If you are placing this template inside a <code><nowiki><ref> </ref></nowiki></code> reference, do not leave any [[Special:Permalink/1105953472|substitution template]] such as <code><nowiki>{{subst:CURRENTMONTHNAME}}</nowiki></code> or <code><nowiki>{{subst:CURRENTYEAR}}</nowiki></code>, because substitutions fail inside ref tags.
Avoid using this template when the reference is fully adequate without the link. In this case, simply remove the link. For example, if a <code>{{tl|cite journal}}</code> template is used with a [[Digital object identifier|DOI]], remove the {{para|url}} parameter.
; Common form (with current date)
{{Tlx|Dead link|date{{=}}{{CURRENTMONTHNAME}} {{CURRENTYEAR}}}}
=== Optional parameters ===
; <code>url</code>: Provides a history of the linked page via the [[Wayback Machine]]. Set '''only''' if history actually exists, as otherwise it is misleading to users and editors.
; <code>date</code>: The date parameter consists of the full English name of the current month with initial capital, a space, and the year, not full dates; e.g., "January 2013", but not "jan13" or " 15 January 2013". {{Em|Any deviation from these two rules will result in an "invalid date parameter" error}}.
; <code>bot</code>: [[WP:Bots|Bot accounts]] specify the <code>|bot=</code> parameter as a sign that the tag was added by an automated process. Set as <code>bot=<bot name></code>.
; <code>fix-attempted</code>: Set this to "yes" if you have tried unsuccessfully to find an archived copy, or a copy with a different URL. This will put the page in [[:Category:Articles with permanently dead external links]], and the annotation will be rendered as "{{dead link |date=July 2022 |fix-attempted=yes}}" instead of just "{{dead link |date=July 2022}}". Note that this currently will occur for any value supplied, including "no", so if a fix was not attempted, simply leave this parameter off, or set it to be blank. Also note that if a page cannot be found in the [[Internet Archive]] (Wayback Machine), [[WP:DEADREF |often a live copy can be found]] via a web search for the full title, in quotes, on the original website, or on the Internet at large. Alternatively, you can use {{Tl|Permanent dead link}} as a shortcut to using this parameter.
'''Notes''':
* The date-substitution template may be used to automatically generate the date, e.g., <code><nowiki>{{Dead link|{{subst:DATE}}}}</nowiki></code>. See [[Help:Substitution]] for more information.
* The <code>date=</code> parameter need not be added by the editor: if not entered, a [[Wikipedia:Bots|bot]] will soon add it.
== Examples ==
* <code><nowiki><ref>{{cite web |url=http://www.example.org |title=Web page title |website=Example.com |access-date=22 September 2012}} {{Dead link |date=September 2012}}</ref></nowiki></code> <br />→ <span style="background:white"><ref>{{cite web |url=http://www.example.org |title=Web page title |website=Example.com |access-date=22 September 2012}} {{Dead link |date=September 2012}}</ref></span>
* <code><nowiki><ref>{{cite news |title=Sorrell accuses Murdoch of panic buying |author=Plunkett, John |url=http://media.guardian.co.uk/site/story/0,14173,1601858,00.html |newspaper=[[The Guardian]] |date=27 October 2005 |access-date=22 September 2012}} {{Dead link}}</ref></nowiki></code> <br />→ <span style="background:white"><ref>{{cite news |title=Sorrell accuses Murdoch of panic buying |author=Plunkett, John |url=http://media.guardian.co.uk/site/story/0,14173,1601858,00.html |newspaper=[[The Guardian]] |date=27 October 2005 |access-date=22 September 2012}} {{Dead link}}</ref></span>
{{Reflist}}
=== Caveats ===
* Avoid using free/bare links without a separator (e.g. <code><nowiki>http://www.example.org/{{Permanent dead link}}</nowiki></code>). Frequently software is unable to differentiate the URL from the template, and will interpret the template as a literal part of the URL. Add square brackets or a space separating the template from the URL. Correct: <code><nowiki>http://www.example.org/ {{Permanent dead link}}</nowiki></code> and Correct: <code><nowiki>[http://www.example.org/]{{Permanent dead link}}</nowiki></code>
* Avoid complicated formatting. Nesting inside another template is not generally supported.
* Avoid using <kbd>[ ] { | } < ></kbd> characters between the end of the external link and <nowiki>{{Permanent dead link}}</nowiki>, as they are often used to format text.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "A template to indicate that the preceding URL is dead",
"params": {
"date": {
"label": "Month and year",
"description": "The month and year the URL was found to be dead, like \"June 2013\"",
"type": "string",
"autovalue": "{{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}}",
"suggested": true
},
"bot": {
"label": "Bot name",
"description": "The name of the bot used to identify the dead link (not used by regular editors)",
"type": "wiki-user-name"
},
"url": {
"label": "Wayback URL",
"description": "The dead URL, used only if there is a Wayback Machine archive",
"type": "url"
},
"fix-attempted": {
"label": "Fix attempted",
"description": "Setting to 'yes' (or any non-blank value) indicates that no archive copy is available",
"type": "string",
"autovalue": "yes"
}
},
"format": "inline"
}
</templatedata>
== See also ==
* {{Tl|Citations broken}}
* {{Tl|Cleanup bare URLs}} header
* {{Tl|Closed access}} and {{Tl|Open access}} citation flags
* {{Tl|Dead YouTube link}}
* {{Tl|Full citation needed}} (inline) to be used when a reference suffers from a more severe problem than a mere [[HTTP 404|broken link]]
* [[Wikipedia:Link rot|Link rot]]
* {{Tl|Permanent dead link}}
* {{Tl|Registration required}} citation flag
* {{Tl|Subscription or libraries}} citation flag for when a subscription or library access may be required
* {{Tl|Subscription required}} citation flag
* {{Tl|Webarchive}}
* [[WP:DEADREF|What to do when a reference link goes dead]]
* {{Tl|Website defunct}} to be used in place of the {{tl|URL}} parameter in infoboxes for defunct websites
=== Dead link tools ===
* Probably of historical interest only:
** [[User:Dispenser/Checklinks|Checklinks]]
** [[User:DeadLinkBOT|DeadLinkBOT]]
** [[User:WebCiteBOT|WebCiteBOT]]
{{Inline cleanup tags}}<includeonly>
{{Sandbox other||
<!-- Categories below this line, please; interwikis at Wikidata -->
[[Category:External link maintenance templates]]
[[Category:Inline citation cleanup templates]]
}}</includeonly>
d5qqbhr0empeyp6iwhc1y2z6iq0soqd
9080
9079
2026-08-22T12:06:30Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Dead_link/doc]]
9079
wikitext
text/x-wiki
{{redirect|Template:DL|the equivalent of the HTML {{tag|dl|o}} tag|Template:Glossary|"described" links|Template:Annotated link}}
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])--><noinclude>
{{pp-template|small=yes}}</noinclude>{{High-use}}
<!-- Redirect regex: [Dd]ead[ _]+link|[Dd]l|[Dd]eadlink|[Cc]leanup-link|[Dd]l-s|404|[Bb]roken[ _]+link|[Bb]rokenlink -->
{{Template shortcut|404|dl|deadlink|dead|Broken link|broken}}
This template is used to mark [[WP:Link rot|dead links]], either within a paragraph or within a [[WP:Citing sources |reference citation]]. Marking dead links signals to editors and to [[WP:Link rot]] bots that this link needs to be replaced with an archive link. Sometimes dead links can be repaired manually; see [[Link rot]] for suggestions.
== Usage ==
Before considering whether to use the {{tl|dead link}} template it is often useful to make a search for an [[Wikipedia:LR#Internet archives|archive copy]] of the dead link, or find the new URL of a moved link or an alternative source using methods from [[WP:DEADLINK]], and thereby avoid using the tag altogether. All {{cite xxx}} templates have the facility for adding {{para|archive-date}} and {{para|archive-url}} parameters for linking to an archive copy. Non-{{cite xxx}} citations can use {{tl|webarchive}}.
Using {{Tl|Dead link}} will place a note by the URL and add the article to one of the [[:Category:Articles with dead external links]] categories.
Append this template '''directly after''' the link (after the link code's terminating <code>]</code> if you are using [[wikitext]]), or, if you are using a {{cite xxx}} template, '''directly after''' the {{cite xxx}} transclusion (not inside it), but inside the reference, if any, i.e. before the <code></ref></code>, in all cases leaving the original link intact:
: <code><nowiki><ref>{{cite web|url=http://www.example.org|title=The Example Website|access-date=22 September 2012}}</nowiki><b style="color:green"><nowiki>{{Dead link|date=</nowiki>{{CURRENTMONTHNAME}} {{CURRENTYEAR}}<nowiki>}}</nowiki></b><nowiki></ref></nowiki></code>
For bare links, leave a space after the end of the URL and the template:
:<code>* http://www.example.org <nowiki>{{Dead link|date=</nowiki>{{CURRENTMONTHNAME}} {{CURRENTYEAR}}<nowiki>}}</nowiki></code>
Otherwise automated tools can have trouble determining where the URL ends, because it will ambiguously contain [[percent encoding|URL-encoding]] and wiki-encoding mixed together.
Not following these syntax rules might hinder detection by automated tools. If the citation contains multiple URLs (e.g. chapter-url and url) in a template, and only one is broken, you can use wiki comments like <code><nowiki><!-- <your hidden explanation here> --></nowiki></code> to explain which one is broken.
If the article uses [[WP:Footnotes|clickable footnotes]], then this template should be placed just before the <code></ref></code> that contains the dead link. The notice will then correctly appear in the reference section instead of in the body of the text, and so [[WP:Link rot]] bots can properly find and fix the link.
If you are placing this template inside a <code><nowiki><ref> </ref></nowiki></code> reference, do not leave any [[Special:Permalink/1105953472|substitution template]] such as <code><nowiki>{{subst:CURRENTMONTHNAME}}</nowiki></code> or <code><nowiki>{{subst:CURRENTYEAR}}</nowiki></code>, because substitutions fail inside ref tags.
Avoid using this template when the reference is fully adequate without the link. In this case, simply remove the link. For example, if a <code>{{tl|cite journal}}</code> template is used with a [[Digital object identifier|DOI]], remove the {{para|url}} parameter.
; Common form (with current date)
{{Tlx|Dead link|date{{=}}{{CURRENTMONTHNAME}} {{CURRENTYEAR}}}}
=== Optional parameters ===
; <code>url</code>: Provides a history of the linked page via the [[Wayback Machine]]. Set '''only''' if history actually exists, as otherwise it is misleading to users and editors.
; <code>date</code>: The date parameter consists of the full English name of the current month with initial capital, a space, and the year, not full dates; e.g., "January 2013", but not "jan13" or " 15 January 2013". {{Em|Any deviation from these two rules will result in an "invalid date parameter" error}}.
; <code>bot</code>: [[WP:Bots|Bot accounts]] specify the <code>|bot=</code> parameter as a sign that the tag was added by an automated process. Set as <code>bot=<bot name></code>.
; <code>fix-attempted</code>: Set this to "yes" if you have tried unsuccessfully to find an archived copy, or a copy with a different URL. This will put the page in [[:Category:Articles with permanently dead external links]], and the annotation will be rendered as "{{dead link |date=July 2022 |fix-attempted=yes}}" instead of just "{{dead link |date=July 2022}}". Note that this currently will occur for any value supplied, including "no", so if a fix was not attempted, simply leave this parameter off, or set it to be blank. Also note that if a page cannot be found in the [[Internet Archive]] (Wayback Machine), [[WP:DEADREF |often a live copy can be found]] via a web search for the full title, in quotes, on the original website, or on the Internet at large. Alternatively, you can use {{Tl|Permanent dead link}} as a shortcut to using this parameter.
'''Notes''':
* The date-substitution template may be used to automatically generate the date, e.g., <code><nowiki>{{Dead link|{{subst:DATE}}}}</nowiki></code>. See [[Help:Substitution]] for more information.
* The <code>date=</code> parameter need not be added by the editor: if not entered, a [[Wikipedia:Bots|bot]] will soon add it.
== Examples ==
* <code><nowiki><ref>{{cite web |url=http://www.example.org |title=Web page title |website=Example.com |access-date=22 September 2012}} {{Dead link |date=September 2012}}</ref></nowiki></code> <br />→ <span style="background:white"><ref>{{cite web |url=http://www.example.org |title=Web page title |website=Example.com |access-date=22 September 2012}} {{Dead link |date=September 2012}}</ref></span>
* <code><nowiki><ref>{{cite news |title=Sorrell accuses Murdoch of panic buying |author=Plunkett, John |url=http://media.guardian.co.uk/site/story/0,14173,1601858,00.html |newspaper=[[The Guardian]] |date=27 October 2005 |access-date=22 September 2012}} {{Dead link}}</ref></nowiki></code> <br />→ <span style="background:white"><ref>{{cite news |title=Sorrell accuses Murdoch of panic buying |author=Plunkett, John |url=http://media.guardian.co.uk/site/story/0,14173,1601858,00.html |newspaper=[[The Guardian]] |date=27 October 2005 |access-date=22 September 2012}} {{Dead link}}</ref></span>
{{Reflist}}
=== Caveats ===
* Avoid using free/bare links without a separator (e.g. <code><nowiki>http://www.example.org/{{Permanent dead link}}</nowiki></code>). Frequently software is unable to differentiate the URL from the template, and will interpret the template as a literal part of the URL. Add square brackets or a space separating the template from the URL. Correct: <code><nowiki>http://www.example.org/ {{Permanent dead link}}</nowiki></code> and Correct: <code><nowiki>[http://www.example.org/]{{Permanent dead link}}</nowiki></code>
* Avoid complicated formatting. Nesting inside another template is not generally supported.
* Avoid using <kbd>[ ] { | } < ></kbd> characters between the end of the external link and <nowiki>{{Permanent dead link}}</nowiki>, as they are often used to format text.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "A template to indicate that the preceding URL is dead",
"params": {
"date": {
"label": "Month and year",
"description": "The month and year the URL was found to be dead, like \"June 2013\"",
"type": "string",
"autovalue": "{{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}}",
"suggested": true
},
"bot": {
"label": "Bot name",
"description": "The name of the bot used to identify the dead link (not used by regular editors)",
"type": "wiki-user-name"
},
"url": {
"label": "Wayback URL",
"description": "The dead URL, used only if there is a Wayback Machine archive",
"type": "url"
},
"fix-attempted": {
"label": "Fix attempted",
"description": "Setting to 'yes' (or any non-blank value) indicates that no archive copy is available",
"type": "string",
"autovalue": "yes"
}
},
"format": "inline"
}
</templatedata>
== See also ==
* {{Tl|Citations broken}}
* {{Tl|Cleanup bare URLs}} header
* {{Tl|Closed access}} and {{Tl|Open access}} citation flags
* {{Tl|Dead YouTube link}}
* {{Tl|Full citation needed}} (inline) to be used when a reference suffers from a more severe problem than a mere [[HTTP 404|broken link]]
* [[Wikipedia:Link rot|Link rot]]
* {{Tl|Permanent dead link}}
* {{Tl|Registration required}} citation flag
* {{Tl|Subscription or libraries}} citation flag for when a subscription or library access may be required
* {{Tl|Subscription required}} citation flag
* {{Tl|Webarchive}}
* [[WP:DEADREF|What to do when a reference link goes dead]]
* {{Tl|Website defunct}} to be used in place of the {{tl|URL}} parameter in infoboxes for defunct websites
=== Dead link tools ===
* Probably of historical interest only:
** [[User:Dispenser/Checklinks|Checklinks]]
** [[User:DeadLinkBOT|DeadLinkBOT]]
** [[User:WebCiteBOT|WebCiteBOT]]
{{Inline cleanup tags}}<includeonly>
{{Sandbox other||
<!-- Categories below this line, please; interwikis at Wikidata -->
[[Category:External link maintenance templates]]
[[Category:Inline citation cleanup templates]]
}}</includeonly>
d5qqbhr0empeyp6iwhc1y2z6iq0soqd
Module:Shortcut/styles.css
828
1062
9083
2025-10-03T21:27:48Z
en>Izno
0
shorterhand padding
9083
sanitized-css
text/css
/* {{pp-template}} */
.module-shortcutboxplain {
float: right;
margin: 0 0 0 1em;
border: 1px solid var(--border-color-base, #a2a9b1);
background-color: var(--background-color-base, #fff);
padding: 0.3em 0.6em 0.2em 0.6em;
text-align: center;
font-size: 85%;
}
.module-shortcutboxleft {
float: left;
margin: 0 1em 0 0;
}
.module-shortcutlist {
display: inline-block;
border-bottom: 1px solid var(--border-color-base, #a2a9b1);
margin-bottom: 0.2em;
}
.module-shortcutboxplain ul {
font-weight: bold;
}
.module-shortcutanchordiv {
position: relative;
top: -3em;
}
li .module-shortcutanchordiv {
float: right; /* IE/Edge in list items */
}
.mbox-imageright .module-shortcutboxplain {
padding: 0.4em 1em;
line-height: 1.3;
margin: 0;
float: initial;
}
iy0abv0s7wkq06bjcild5vh6fo8vjrr
9084
9083
2026-08-22T12:06:30Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Shortcut/styles.css]]
9083
sanitized-css
text/css
/* {{pp-template}} */
.module-shortcutboxplain {
float: right;
margin: 0 0 0 1em;
border: 1px solid var(--border-color-base, #a2a9b1);
background-color: var(--background-color-base, #fff);
padding: 0.3em 0.6em 0.2em 0.6em;
text-align: center;
font-size: 85%;
}
.module-shortcutboxleft {
float: left;
margin: 0 1em 0 0;
}
.module-shortcutlist {
display: inline-block;
border-bottom: 1px solid var(--border-color-base, #a2a9b1);
margin-bottom: 0.2em;
}
.module-shortcutboxplain ul {
font-weight: bold;
}
.module-shortcutanchordiv {
position: relative;
top: -3em;
}
li .module-shortcutanchordiv {
float: right; /* IE/Edge in list items */
}
.mbox-imageright .module-shortcutboxplain {
padding: 0.4em 1em;
line-height: 1.3;
margin: 0;
float: initial;
}
iy0abv0s7wkq06bjcild5vh6fo8vjrr
Tempilet:Category link without namespace
10
1063
9085
2024-06-02T14:03:48Z
en>HouseBlaster
0
HouseBlaster moved page [[Template:C]] to [[Template:Category link without namespace]]: expand template name per [[WP:TPN]]
9085
wikitext
text/x-wiki
[[:Category:{{PAGENAME:{{{1}}}}}|{{{2|{{PAGENAME:{{{1}}}}}}}}]]<noinclude>
{{Documentation}}
</noinclude>
5ihlenrrtiyl0onp17hzt1jb0im35x9
9086
9085
2026-08-22T12:06:30Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Category_link_without_namespace]]
9085
wikitext
text/x-wiki
[[:Category:{{PAGENAME:{{{1}}}}}|{{{2|{{PAGENAME:{{{1}}}}}}}}]]<noinclude>
{{Documentation}}
</noinclude>
5ihlenrrtiyl0onp17hzt1jb0im35x9
MediaWiki:Scribunto-doc-page-does-not-exist
8
1064
9089
2026-08-22T14:12:43Z
RAPTOR7762
18
Created page with "{{#invoke:documentation|nonexistent|_content={{ {{#invoke:documentation|contentTitle}}}}}}"
9089
wikitext
text/x-wiki
{{#invoke:documentation|nonexistent|_content={{ {{#invoke:documentation|contentTitle}}}}}}
k0diz3djp7h5ii35up05t7cttpbb5z9
Tempilet:Protection padlock
10
1065
9093
2026-08-16T14:03:04Z
en>RMCD bot
0
Notifying subject page of move discussion on [[Template talk:Protection padlock#Requested move 16 August 2026|Template talk:Protection padlock]]
9093
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Protected page|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
bivafhpdzqot8aqh2pxo1ns5dmt7awb
9094
9093
2026-08-22T14:37:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Protection_padlock]]
9093
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Protected page|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
bivafhpdzqot8aqh2pxo1ns5dmt7awb
9212
9094
2026-08-23T03:30:55Z
RAPTOR7762
18
/* */
9212
wikitext
text/x-wiki
<includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
0q651nfr0ibf5g4bbb3sw2qkj47h3ic
9213
9212
2026-08-23T03:31:36Z
RAPTOR7762
18
Protected "[[Tempilet:Protection padlock]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite))
9212
wikitext
text/x-wiki
<includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
0q651nfr0ibf5g4bbb3sw2qkj47h3ic
Tempilet:C
10
1066
9097
2024-06-02T14:03:48Z
en>HouseBlaster
0
HouseBlaster moved page [[Template:C]] to [[Template:Category link without namespace]]: expand template name per [[WP:TPN]]
9097
wikitext
text/x-wiki
#REDIRECT [[Template:Category link without namespace]]
{{Redirect category shell|
{{R from move}}
}}
3qa60t6mwxjkjff4k91jtkyn2wfm6h0
9098
9097
2026-08-22T14:37:07Z
RAPTOR7762
18
1 revision imported from [[:en:Template:C]]
9097
wikitext
text/x-wiki
#REDIRECT [[Template:Category link without namespace]]
{{Redirect category shell|
{{R from move}}
}}
3qa60t6mwxjkjff4k91jtkyn2wfm6h0
Tempilet:Strong
10
1067
9099
2017-09-16T03:10:40Z
en>Matt Fitzpatrick
0
added role parameter and attribute
9099
wikitext
text/x-wiki
<strong {{#if:{{{role|}}}|role="{{{role}}}"}} {{#if:{{{class|}}}|class="{{{class}}}"}} {{#if:{{{id|}}}|id="{{{id}}}"}} {{#if:{{{style|}}}|style="{{{style}}}"}} {{#if:{{{title|}}}|title="{{{title}}}"}}>{{{1}}}</strong><noinclude>
{{documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
jhbv1h6fd9kjc1d4eovhzvnxrpqq09r
9100
9099
2026-08-22T14:37:07Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Strong]]
9099
wikitext
text/x-wiki
<strong {{#if:{{{role|}}}|role="{{{role}}}"}} {{#if:{{{class|}}}|class="{{{class}}}"}} {{#if:{{{id|}}}|id="{{{id}}}"}} {{#if:{{{style|}}}|style="{{{style}}}"}} {{#if:{{{title|}}}|title="{{{title}}}"}}>{{{1}}}</strong><noinclude>
{{documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
jhbv1h6fd9kjc1d4eovhzvnxrpqq09r
Tempilet:Replace
10
1068
9101
2024-08-19T20:57:32Z
en>Pppery
0
Set plain explicitly per request
9101
wikitext
text/x-wiki
<includeonly>{{safesubst:#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|plain={{safesubst:#if:{{{plain|}}}|{{{plain}}}|true}}|count={{{count|}}}}}</includeonly><noinclude>
{{documentation}}
</noinclude>
r178n7opmwh460jjikowaqng5m5fzrn
9102
9101
2026-08-22T14:37:07Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Replace]]
9101
wikitext
text/x-wiki
<includeonly>{{safesubst:#invoke:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|plain={{safesubst:#if:{{{plain|}}}|{{{plain}}}|true}}|count={{{count|}}}}}</includeonly><noinclude>
{{documentation}}
</noinclude>
r178n7opmwh460jjikowaqng5m5fzrn
Tempilet:Aligned table
10
1069
9103
2020-08-09T16:18:21Z
en>Bsherr
0
adding comment
9103
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:aligned table|table}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
atstqes86pjj6hoiczcmfvhjlawblhx
9104
9103
2026-08-22T14:37:08Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Aligned_table]]
9103
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:aligned table|table}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
atstqes86pjj6hoiczcmfvhjlawblhx
Module:Aligned table
828
1070
9105
2021-01-13T21:53:43Z
en>Plastikspork
0
Optional rowclass
9105
Scribunto
text/plain
-- This module implements {{aligned table}}
local p = {}
local function isnotempty(s)
return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end
function p.table(frame)
local args = (frame.args[3] ~= nil) and frame.args or frame:getParent().args
local entries = {}
local colclass = {}
local colstyle = {}
local cols = tonumber(args['cols']) or 2
-- create the root table
local root = mw.html.create('table')
-- add table style for fullwidth
if isnotempty(args['fullwidth']) then
root
:css('width', '100%')
:css('border-collapse', 'collapse')
:css('border-spacing', '0px 0px')
:css('border', 'none')
end
-- add table classes
if isnotempty(args['class']) then
root:addClass(args['class'])
end
-- add table style
if isnotempty(args['style']) then
root:cssText(args['style'])
end
-- build arrays with the column styles and classes
if isnotempty(args['leftright']) then
colstyle[1] = 'text-align:left;'
colstyle[2] = 'text-align:right;'
end
if isnotempty(args['rightleft']) then
colstyle[1] = 'text-align:right;'
colstyle[2] = 'text-align:left;'
end
for i = 1,cols do
colclass[ i ] = colclass[ i ] or ''
colstyle[ i ] = colstyle[ i ] or ''
if isnotempty(args['colstyle']) then
colstyle[ i ] = args['colstyle'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colalign' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['colalign' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'align']) then
colstyle[ i ] = 'text-align:' .. args['col' .. tostring(i) .. 'align'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['align' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['align' .. tostring(i)] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colnowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'nowrap']) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['nowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
end
if isnotempty(args['colwidth' .. tostring(i)]) then
colstyle[ i ] = 'width:' .. args['colwidth' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'width']) then
colstyle[ i ] = 'width:' .. args['col' .. tostring(i) .. 'width'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['colwidth']) then
colstyle[ i ] = 'width:' .. args['colwidth'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colstyle' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['colstyle' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'style']) then
colstyle[ i ] = colstyle[ i ] .. args['col' .. tostring(i) .. 'style']
elseif isnotempty(args['style' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['style' .. tostring(i)]
end
if isnotempty(args['colclass' .. tostring(i)]) then
colclass[ i ] = args['colclass' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'class']) then
colclass[ i ] = args['col' .. tostring(i) .. 'class']
elseif isnotempty(args['class' .. tostring(i)]) then
colclass[ i ] = args['class' .. tostring(i)]
end
end
-- compute the maximum cell index
local cellcount = 0
for k, v in pairs( args ) do
if type( k ) == 'number' then
cellcount = math.max(cellcount, k)
end
end
-- compute the number of rows
local rows = math.ceil(cellcount / cols)
-- build the table content
if isnotempty(args['title']) then
local caption = root:tag('caption')
caption:cssText(args['titlestyle'])
caption:wikitext(args['title'])
end
if isnotempty(args['above']) then
local row = root:tag('tr')
local cell = row:tag('th')
cell:attr('colspan', cols)
cell:cssText(args['abovestyle'])
cell:wikitext(args['above'])
end
for j=1,rows do
-- start a new row
local row = root:tag('tr')
if isnotempty(args['rowstyle']) then
row:cssText(args['rowstyle'])
else
row:css('vertical-align', 'top')
end
if isnotempty(args['rowclass']) then
row:addClass(args['rowclass'])
end
-- loop over the cells in the row
for i=1,cols do
local cell
if isnotempty(args['row' .. tostring(j) .. 'header']) then
cell = row:tag('th'):attr('scope','col')
elseif isnotempty(args['col' .. tostring(i) .. 'header']) then
cell = row:tag('th'):attr('scope','row')
else
cell = row:tag('td')
end
if args['class' .. tostring(j) .. '.' .. tostring(i)] then
cell:addClass(args['class' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowclass' .. tostring(j)] then
cell:addClass(args['rowclass' .. tostring(j)])
elseif args['row' .. tostring(j) .. 'class'] then
cell:addClass(args['row' .. tostring(j) .. 'class'])
elseif args['rowevenclass'] and math.fmod(j,2) == 0 then
cell:addClass(args['rowevenclass'])
elseif args['rowoddclass'] and math.fmod(j,2) == 1 then
cell:addClass(args['rowoddclass'])
end
if colclass[i] ~= '' then
cell:addClass(colclass[i])
end
end
if args['style' .. tostring(j) .. '.' .. tostring(i)] then
cell:cssText(args['style' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowstyle' .. tostring(j)] then
cell:cssText(args['rowstyle' .. tostring(j)])
elseif args['rowevenstyle'] and math.fmod(j,2) == 0 then
cell:cssText(args['rowevenstyle'])
elseif args['rowoddstyle'] and math.fmod(j,2) == 1 then
cell:cssText(args['rowoddstyle'])
elseif args['row' .. tostring(j) .. 'style'] then
cell:cssText(args['row' .. tostring(j) .. 'style'])
end
if isnotempty(colstyle[i]) then
cell:cssText(colstyle[i])
end
end
cell:wikitext(mw.ustring.gsub(args[cols*(j - 1) + i] or '', '^(.-)%s*$', '%1') or '')
end
end
-- return the root table
return tostring(root)
end
return p
m9dwn0950shw2aiodgy0z837cvdja2z
9106
9105
2026-08-22T14:37:08Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Aligned_table]]
9105
Scribunto
text/plain
-- This module implements {{aligned table}}
local p = {}
local function isnotempty(s)
return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end
function p.table(frame)
local args = (frame.args[3] ~= nil) and frame.args or frame:getParent().args
local entries = {}
local colclass = {}
local colstyle = {}
local cols = tonumber(args['cols']) or 2
-- create the root table
local root = mw.html.create('table')
-- add table style for fullwidth
if isnotempty(args['fullwidth']) then
root
:css('width', '100%')
:css('border-collapse', 'collapse')
:css('border-spacing', '0px 0px')
:css('border', 'none')
end
-- add table classes
if isnotempty(args['class']) then
root:addClass(args['class'])
end
-- add table style
if isnotempty(args['style']) then
root:cssText(args['style'])
end
-- build arrays with the column styles and classes
if isnotempty(args['leftright']) then
colstyle[1] = 'text-align:left;'
colstyle[2] = 'text-align:right;'
end
if isnotempty(args['rightleft']) then
colstyle[1] = 'text-align:right;'
colstyle[2] = 'text-align:left;'
end
for i = 1,cols do
colclass[ i ] = colclass[ i ] or ''
colstyle[ i ] = colstyle[ i ] or ''
if isnotempty(args['colstyle']) then
colstyle[ i ] = args['colstyle'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colalign' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['colalign' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'align']) then
colstyle[ i ] = 'text-align:' .. args['col' .. tostring(i) .. 'align'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['align' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['align' .. tostring(i)] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colnowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'nowrap']) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['nowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
end
if isnotempty(args['colwidth' .. tostring(i)]) then
colstyle[ i ] = 'width:' .. args['colwidth' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'width']) then
colstyle[ i ] = 'width:' .. args['col' .. tostring(i) .. 'width'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['colwidth']) then
colstyle[ i ] = 'width:' .. args['colwidth'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colstyle' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['colstyle' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'style']) then
colstyle[ i ] = colstyle[ i ] .. args['col' .. tostring(i) .. 'style']
elseif isnotempty(args['style' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['style' .. tostring(i)]
end
if isnotempty(args['colclass' .. tostring(i)]) then
colclass[ i ] = args['colclass' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'class']) then
colclass[ i ] = args['col' .. tostring(i) .. 'class']
elseif isnotempty(args['class' .. tostring(i)]) then
colclass[ i ] = args['class' .. tostring(i)]
end
end
-- compute the maximum cell index
local cellcount = 0
for k, v in pairs( args ) do
if type( k ) == 'number' then
cellcount = math.max(cellcount, k)
end
end
-- compute the number of rows
local rows = math.ceil(cellcount / cols)
-- build the table content
if isnotempty(args['title']) then
local caption = root:tag('caption')
caption:cssText(args['titlestyle'])
caption:wikitext(args['title'])
end
if isnotempty(args['above']) then
local row = root:tag('tr')
local cell = row:tag('th')
cell:attr('colspan', cols)
cell:cssText(args['abovestyle'])
cell:wikitext(args['above'])
end
for j=1,rows do
-- start a new row
local row = root:tag('tr')
if isnotempty(args['rowstyle']) then
row:cssText(args['rowstyle'])
else
row:css('vertical-align', 'top')
end
if isnotempty(args['rowclass']) then
row:addClass(args['rowclass'])
end
-- loop over the cells in the row
for i=1,cols do
local cell
if isnotempty(args['row' .. tostring(j) .. 'header']) then
cell = row:tag('th'):attr('scope','col')
elseif isnotempty(args['col' .. tostring(i) .. 'header']) then
cell = row:tag('th'):attr('scope','row')
else
cell = row:tag('td')
end
if args['class' .. tostring(j) .. '.' .. tostring(i)] then
cell:addClass(args['class' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowclass' .. tostring(j)] then
cell:addClass(args['rowclass' .. tostring(j)])
elseif args['row' .. tostring(j) .. 'class'] then
cell:addClass(args['row' .. tostring(j) .. 'class'])
elseif args['rowevenclass'] and math.fmod(j,2) == 0 then
cell:addClass(args['rowevenclass'])
elseif args['rowoddclass'] and math.fmod(j,2) == 1 then
cell:addClass(args['rowoddclass'])
end
if colclass[i] ~= '' then
cell:addClass(colclass[i])
end
end
if args['style' .. tostring(j) .. '.' .. tostring(i)] then
cell:cssText(args['style' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowstyle' .. tostring(j)] then
cell:cssText(args['rowstyle' .. tostring(j)])
elseif args['rowevenstyle'] and math.fmod(j,2) == 0 then
cell:cssText(args['rowevenstyle'])
elseif args['rowoddstyle'] and math.fmod(j,2) == 1 then
cell:cssText(args['rowoddstyle'])
elseif args['row' .. tostring(j) .. 'style'] then
cell:cssText(args['row' .. tostring(j) .. 'style'])
end
if isnotempty(colstyle[i]) then
cell:cssText(colstyle[i])
end
end
cell:wikitext(mw.ustring.gsub(args[cols*(j - 1) + i] or '', '^(.-)%s*$', '%1') or '')
end
end
-- return the root table
return tostring(root)
end
return p
m9dwn0950shw2aiodgy0z837cvdja2z
Tempilet:Str len
10
1071
9107
2021-06-13T14:08:05Z
en>Plastikspork
0
Fix for |=foo bug
9107
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:String|len|s={{{1|}}}}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
2n0p928wu8hdh499dl0eaxtmt6t1tr4
9108
9107
2026-08-22T14:37:08Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Str_len]]
9107
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:String|len|s={{{1|}}}}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
2n0p928wu8hdh499dl0eaxtmt6t1tr4
Tempilet:Twinkle standard installation
10
1072
9109
2025-12-29T01:02:32Z
en>Steel1943
0
Apparently Twinkle has a new logo
9109
wikitext
text/x-wiki
{{Mbox
| image = [[File:Twinkle logo.svg|50x40px|alt=Logo of Twinkle|link=]]
| text = Any [[Template:Twinkle standard installation#"Breaking changes"|breaking changes]] to this template, including moving it or nominating it for deletion, {{strong|must be communicated in advance}} to [[Wikipedia:Twinkle|Twinkle]]'s users and maintainers at [[Wikipedia talk:Twinkle]]. The standard installation of Twinkle relies on this template. Thank you.{{#if:{{{1|}}}|<br>
{{{1}}}}}}}<includeonly>{{#if:{{{nocat|}}}||{{#ifeq:{{PAGENAME}}|{{BASEPAGENAME}}|[[Category:Templates used by Twinkle|{{PAGENAME}}]]}}}}</includeonly><noinclude>
{{Documentation}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
n3w4a7frflh3vhrxeyq51em6fbi1qhm
9110
9109
2026-08-22T14:37:09Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Twinkle_standard_installation]]
9109
wikitext
text/x-wiki
{{Mbox
| image = [[File:Twinkle logo.svg|50x40px|alt=Logo of Twinkle|link=]]
| text = Any [[Template:Twinkle standard installation#"Breaking changes"|breaking changes]] to this template, including moving it or nominating it for deletion, {{strong|must be communicated in advance}} to [[Wikipedia:Twinkle|Twinkle]]'s users and maintainers at [[Wikipedia talk:Twinkle]]. The standard installation of Twinkle relies on this template. Thank you.{{#if:{{{1|}}}|<br>
{{{1}}}}}}}<includeonly>{{#if:{{{nocat|}}}||{{#ifeq:{{PAGENAME}}|{{BASEPAGENAME}}|[[Category:Templates used by Twinkle|{{PAGENAME}}]]}}}}</includeonly><noinclude>
{{Documentation}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
n3w4a7frflh3vhrxeyq51em6fbi1qhm
Tempilet:Param value
10
1073
9111
2025-12-08T18:41:13Z
en>Pigsonthewing
0
sync from sandbox per request
9111
wikitext
text/x-wiki
<templatestyles src="Template:Param value/styles.css"/><span class="tpl-pval__wrapper"><code class="tpl-pval__code" style="{{#if:{{{border|{{{b|}}}}}}|border:{{{border|{{{b|}}}}}};}} {{#if:{{{bg-color|}}}|background-color: {{{bg-color}}}; color: {{Greater color contrast ratio|{{{bg-color}}}}};}} {{#if:{{{bg|}}}|color: {{Greater color contrast ratio|{{{bg}}}}};}} {{#ifexpr:{{str len|{{{1|}}}}} > 25|white-space: wrap;|}} {{{style|}}}">{{replace|{{replace|{{replace|{{replace|{{replace|<includeonly>⊗ϑ{{{1|}}}⊗ϑ</includeonly><noinclude>value</noinclude>| |{{{space|{{{sp| }}}}}}}}|#|#}}|*|*}}|:|:}}|⊗ϑ|}}</code></span><noinclude>
{{Documentation}}
</noinclude>
oyd3jpyy59x812wn9xbrqm63nh7f7d7
9112
9111
2026-08-22T14:37:09Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Param_value]]
9111
wikitext
text/x-wiki
<templatestyles src="Template:Param value/styles.css"/><span class="tpl-pval__wrapper"><code class="tpl-pval__code" style="{{#if:{{{border|{{{b|}}}}}}|border:{{{border|{{{b|}}}}}};}} {{#if:{{{bg-color|}}}|background-color: {{{bg-color}}}; color: {{Greater color contrast ratio|{{{bg-color}}}}};}} {{#if:{{{bg|}}}|color: {{Greater color contrast ratio|{{{bg}}}}};}} {{#ifexpr:{{str len|{{{1|}}}}} > 25|white-space: wrap;|}} {{{style|}}}">{{replace|{{replace|{{replace|{{replace|{{replace|<includeonly>⊗ϑ{{{1|}}}⊗ϑ</includeonly><noinclude>value</noinclude>| |{{{space|{{{sp| }}}}}}}}|#|#}}|*|*}}|:|:}}|⊗ϑ|}}</code></span><noinclude>
{{Documentation}}
</noinclude>
oyd3jpyy59x812wn9xbrqm63nh7f7d7
Tempilet:Pval
10
1074
9113
2024-08-25T12:16:24Z
en>Warudo
0
+rcat
9113
wikitext
text/x-wiki
#REDIRECT [[Template:Param value]]
{{Rcat shell|
{{R shortcut}}
}}
brfkzkf9futzxnw5ien0erejft2lgre
9114
9113
2026-08-22T14:37:09Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pval]]
9113
wikitext
text/x-wiki
#REDIRECT [[Template:Param value]]
{{Rcat shell|
{{R shortcut}}
}}
brfkzkf9futzxnw5ien0erejft2lgre
Tempilet:Tsh
10
1075
9115
2026-03-27T18:00:12Z
en>MusikBot II
0
Changed protection settings for "[[Template:Tsh]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 2516 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require extended confirmed access] (indefinite) [Move=Require extended confirmed access] (indefinite))
9115
wikitext
text/x-wiki
#REDIRECT [[Template:Template shortcut]]
{{rcatsh|
{{R tsh}}
}}
dbgssn12xup12fq1n1zhkcktef0d05l
9116
9115
2026-08-22T14:37:09Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tsh]]
9115
wikitext
text/x-wiki
#REDIRECT [[Template:Template shortcut]]
{{rcatsh|
{{R tsh}}
}}
dbgssn12xup12fq1n1zhkcktef0d05l
Tempilet:Protection templates
10
1076
9117
2026-05-04T00:13:17Z
en>JHD0919
0
The "permanent" template has been renamed & moved, and the "temporary" template has been deleted.
9117
wikitext
text/x-wiki
{{Navbox
| state = {{{state|{{{1|<includeonly>{{#ifeq:{{NAMESPACE}}|Module||collapsed}}</includeonly>}}}}}}
| title = {{c|Protection templates}}
| image<!--left--> = <!--[[File:Padlock.svg|40px|link=|alt=]]-->
| tracking = no <!-- keep all the documented templates out of the hlist tracking category -->
| inner-style = table-format:fixed;
| list1 = <div style="overflow:auto">{{Aligned table
|cols=5 |style=table-format:fixed;border:1px solid #aaa;margin:0 auto<!-- 0.2em-->;
|colstyle=vertical-align:middle;padding-left:1.0em;<!--font-family:monospace;-->padding-right:1.0em;
<!--row#-->
|row1header=on |row1style=padding-bottom:0.25em;border-bottom:1px solid #bbf;
<!-- 1 --> | | Edit | Move | [[Wikipedia:Pending changes|Pending changes]] | Upload
<!-- 2 --> | Generic | {{tl|pp}} | {{tl|pp-move}} | {{tl|pp-pc}} | {{tl|pp-upload}}
<!-- 3 --> | [[Wikipedia:Biographies of living persons|BLP]] | {{tl|pp-blp}} | – | – | –
<!-- 4 --> | Blocked user's talk page | {{tl|pp-usertalk}} | – | – | –
<!-- 5 --> | Dispute | {{tl|pp-dispute}} | {{tl|pp-move-dispute}} | – | –
<!-- 6 --> | [[Wikipedia:Protection_policy#Extended_confirmed_protection|Extended confirmed protection]] | {{tl|pp-extended}} | – | – | –
<!-- 7 --> | Indefinite | {{tl|pp-semi-indef}} | {{tl|pp-move-indef}} | – | –
<!-- 8 --> | [[Main Page]] image | {{tl|pp-main-page}} | – | – | –
<!-- 9 --> | [[Wikipedia:Office actions|Office]] | {{tl|pp-office}} | – | – | –
<!-- 10--> | [[Wikipedia:Sockpuppetry|Sockpuppetry]] | {{tl|pp-sock}} | – | – | –
<!-- 11 --> | Templates and images | {{tl|pp-template}} | – | – | {{tl|pp-upload}}
<!-- 12 --> | Vandalism | {{tl|pp-vandalism}} | {{tl|pp-move-vandalism}} | – | –
<!-- 13 --> | Talk page | {{tl|Indefinitely protected}} | – | – | –
}}</div>
| below = [[Module:Protection banner]]
}}<noinclude>
{{Documentation|content=
{{Collapsible option |statename=optional |default=collapsed}}
{{Sandbox other||
[[Category:Documentation see also templates]]
[[Category:Wikipedia administration templates]]
}}}}<!--(end Documentation)-->
</noinclude>
n1kcstoc2yv7pztv9swgzwfgr0pu0zp
9118
9117
2026-08-22T14:37:10Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Protection_templates]]
9117
wikitext
text/x-wiki
{{Navbox
| state = {{{state|{{{1|<includeonly>{{#ifeq:{{NAMESPACE}}|Module||collapsed}}</includeonly>}}}}}}
| title = {{c|Protection templates}}
| image<!--left--> = <!--[[File:Padlock.svg|40px|link=|alt=]]-->
| tracking = no <!-- keep all the documented templates out of the hlist tracking category -->
| inner-style = table-format:fixed;
| list1 = <div style="overflow:auto">{{Aligned table
|cols=5 |style=table-format:fixed;border:1px solid #aaa;margin:0 auto<!-- 0.2em-->;
|colstyle=vertical-align:middle;padding-left:1.0em;<!--font-family:monospace;-->padding-right:1.0em;
<!--row#-->
|row1header=on |row1style=padding-bottom:0.25em;border-bottom:1px solid #bbf;
<!-- 1 --> | | Edit | Move | [[Wikipedia:Pending changes|Pending changes]] | Upload
<!-- 2 --> | Generic | {{tl|pp}} | {{tl|pp-move}} | {{tl|pp-pc}} | {{tl|pp-upload}}
<!-- 3 --> | [[Wikipedia:Biographies of living persons|BLP]] | {{tl|pp-blp}} | – | – | –
<!-- 4 --> | Blocked user's talk page | {{tl|pp-usertalk}} | – | – | –
<!-- 5 --> | Dispute | {{tl|pp-dispute}} | {{tl|pp-move-dispute}} | – | –
<!-- 6 --> | [[Wikipedia:Protection_policy#Extended_confirmed_protection|Extended confirmed protection]] | {{tl|pp-extended}} | – | – | –
<!-- 7 --> | Indefinite | {{tl|pp-semi-indef}} | {{tl|pp-move-indef}} | – | –
<!-- 8 --> | [[Main Page]] image | {{tl|pp-main-page}} | – | – | –
<!-- 9 --> | [[Wikipedia:Office actions|Office]] | {{tl|pp-office}} | – | – | –
<!-- 10--> | [[Wikipedia:Sockpuppetry|Sockpuppetry]] | {{tl|pp-sock}} | – | – | –
<!-- 11 --> | Templates and images | {{tl|pp-template}} | – | – | {{tl|pp-upload}}
<!-- 12 --> | Vandalism | {{tl|pp-vandalism}} | {{tl|pp-move-vandalism}} | – | –
<!-- 13 --> | Talk page | {{tl|Indefinitely protected}} | – | – | –
}}</div>
| below = [[Module:Protection banner]]
}}<noinclude>
{{Documentation|content=
{{Collapsible option |statename=optional |default=collapsed}}
{{Sandbox other||
[[Category:Documentation see also templates]]
[[Category:Wikipedia administration templates]]
}}}}<!--(end Documentation)-->
</noinclude>
n1kcstoc2yv7pztv9swgzwfgr0pu0zp
Module:Transclusion count/data/P
828
1077
9119
2026-08-16T05:09:20Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9119
Scribunto
text/plain
return {
["P"] = 6400,
["P-1"] = 4800,
["P-phrases"] = 4200,
["P."] = 4000,
["P1"] = 232000,
["P2"] = 512000,
["PAGENAMEBASE"] = 1900000,
["PAGENAMEU"] = 56000,
["PAK"] = 3500,
["PD-US"] = 8600,
["PD-US-1923-abroad"] = 5400,
["PD-US-expired"] = 5000,
["PD-US-expired-abroad"] = 8700,
["PD-US-no_notice"] = 2300,
["PD-art"] = 3200,
["PD-ineligible-USonly"] = 7700,
["PD-notice"] = 26000,
["PD-old-100"] = 3200,
["PD-self"] = 31000,
["PD-textlogo"] = 6200,
["PDB_Gallery"] = 2900,
["PDanube"] = 3300,
["PER"] = 3500,
["PHI"] = 2700,
["PHL"] = 3700,
["PH_census"] = 2000,
["PLANTS"] = 4300,
["PM20"] = 3300,
["PMID"] = 6500,
["PNsign"] = 2100,
["POL"] = 68000,
["POR"] = 5600,
["POTD/Day"] = 2900,
["POTD_archive"] = 2500,
["POTD_archive/footer"] = 2500,
["POTD_default"] = 12000,
["POTD_image"] = 3800,
["POTD_image1"] = 2500,
["POTD_image2"] = 2500,
["POTD_navigation"] = 7800,
["POTD_texttitle"] = 2600,
["POTDlink"] = 8200,
["POV"] = 3100,
["POW"] = 2500,
["PR/header"] = 3100,
["PR/heading"] = 7200,
["PRI"] = 2200,
["PRT"] = 6400,
["PR_link"] = 118000,
["PS"] = 3100,
["Pad"] = 51000,
["Paddle_Steamer"] = 3100,
["Page"] = 4400,
["Page_name_sub"] = 52000,
["Page_needed"] = 23000,
["Page_tabs"] = 4100,
["Page_tabs/styles.css"] = 4100,
["Pagelinks"] = 74000,
["Pagelist"] = 15000,
["Pagetype"] = 11300000,
["Paid"] = 17000,
["Pakistani_English"] = 4000,
["Para"] = 2850000,
["Parabr"] = 3800,
["Paragraph_break"] = 2150000,
["Param_value"] = 152000,
["Param_value/styles.css"] = 152000,
["Parameter"] = 3000000,
["Parameter_names_example"] = 2700,
["ParmPart"] = 15000,
["Partial"] = 5800,
["Partial_minor_planet_designation"] = 5700,
["Partly_done"] = 4200,
["Party_color"] = 82000,
["Party_color_cell"] = 6600,
["Party_index_link"] = 3300,
["Party_name_with_color"] = 7200,
["Party_name_with_colour"] = 4200,
["Party_shading/Democratic"] = 19000,
["Party_shading/Independent"] = 3400,
["Party_shading/Republican"] = 18000,
["Party_stripe"] = 17000,
["Pass"] = 3300,
["Pb"] = 2120000,
["Pd-notice"] = 2200,
["Pedigree"] = 4400,
["Peer_review/heading"] = 10000,
["Peer_review_links"] = 3200,
["Peer_review_tools"] = 9600,
["Penalty_shoot-out"] = 5900,
["Pending"] = 6300,
["Pending_DYK_American_hooks"] = 5100,
["Pending_DYK_biographies"] = 11000,
["Pending_film"] = 2700,
["Pending_films_key"] = 2600,
["Pengoal"] = 12000,
["Penmiss"] = 14000,
["Percentage"] = 18000,
["Performance_key"] = 2800,
["Performance_key/styles.css"] = 2800,
["Period_color"] = 28000,
["Period_end"] = 26000,
["Period_id"] = 29000,
["Period_start"] = 29000,
["Personal_attack_removed"] = 2100,
["PeruTasks"] = 19000,
["Phab"] = 8100,
["Phabricator"] = 8300,
["Phanerozoic_250px"] = 25000,
["PharmNavFootnote"] = 5600,
["Philippine_census_reference"] = 2000,
["Philippine_name"] = 4200,
["Photo"] = 2200,
["Photo_montage"] = 4900,
["Photo_requested"] = 108000,
["Photograph_requested"] = 4600,
["Photomontage"] = 4400,
["Photoreq"] = 2900,
["Picture_of_the_day"] = 8200,
["Pie_chart"] = 8300,
["Pie_chart/styles.css"] = 8300,
["Ping"] = 284000,
["Pipe"] = 97000,
["Place_name_disambiguation"] = 40000,
["Plain_link"] = 119000,
["Plain_list"] = 16000,
["Plain_text"] = 109000,
["Plainlink"] = 30000,
["Plainlist"] = 390000,
["Plainlist/styles.css"] = 3110000,
["Player"] = 3900,
["Player2"] = 2900,
["Please_check_ISSN"] = 16000,
["Plural"] = 107000,
["Pluralize_from_text"] = 2780000,
["Pn"] = 2800,
["Poem_quote"] = 3900,
["Poemquote"] = 2700,
["Politician_icon"] = 34000,
["Politician_icon2"] = 34000,
["Politics_sidebar_below"] = 19000,
["Politics_sidebar_title"] = 19000,
["Polluted_category"] = 2500,
["Polparty"] = 31000,
["Pop_density"] = 10000,
["Population_Germany"] = 14000,
["Portal"] = 10800000,
["Portal-Class"] = 8100,
["Portal-inline"] = 245000,
["Portal_and_project"] = 261000,
["Portal_bar"] = 185000,
["Portal_box"] = 2200,
["Portalbar"] = 10000,
["Portuguese_name"] = 10000,
["Possible"] = 4000,
["Possibly_empty_category"] = 70000,
["Post-nominals"] = 63000,
["Post-nominals/AUS"] = 8500,
["Post-nominals/CAN"] = 10000,
["Post-nominals/GBR"] = 33000,
["Post-nominals/NZL"] = 4500,
["Postnominals"] = 11000,
["Pp"] = 8800,
["Pp-book-cover"] = 52000,
["Pp-extended"] = 10000,
["Pp-move"] = 11000,
["Pp-pc"] = 4400,
["Pp-protected"] = 13000,
["Pp-semi"] = 6800,
["Pp-semi-indef"] = 4800,
["Pp-template"] = 4400,
["Pp-vandalism"] = 2800,
["Precision"] = 6000,
["Preferences"] = 18000,
["Preferences/section"] = 3100,
["PresFoot"] = 3300,
["PresHead"] = 3900,
["PresRow"] = 3900,
["Press"] = 5700,
["Preview_warning"] = 603000,
["Primary_source_inline"] = 8100,
["Primary_sources"] = 33000,
["Principal_rank"] = 653000,
["Prisoner_of_war"] = 2600,
["Prl"] = 118000,
["ProCyclingStats"] = 2400,
["ProQuest"] = 35000,
["Professional_wrestling_profiles"] = 3200,
["Professional_wrestling_results_table"] = 3200,
["Profit"] = 3600,
["Progress_box"] = 19000,
["Project-Class"] = 13000,
["Project_other"] = 18000,
["Promotional"] = 18000,
["Proper_name"] = 2800,
["Prose"] = 3300,
["Protected_page_maintenance_message"] = 42000,
["Protection_padlock"] = 25000,
["Proxy_block"] = 2200,
["Pso"] = 5000,
["Purge"] = 567000,
["Purge_button"] = 19000,
["Purge_button/styles.css"] = 19000,
["Module:POTD_titletext"] = 2500,
["Module:Page"] = 122000,
["Module:PageLinks"] = 75000,
["Module:Page_tabs"] = 4100,
["Module:Pagelist"] = 15000,
["Module:Pagetype"] = 19000000,
["Module:Pagetype/config"] = 19000000,
["Module:Pagetype/disambiguation"] = 13300000,
["Module:Pagetype/rfd"] = 17100000,
["Module:Pagetype/setindex"] = 13500000,
["Module:Pagetype/softredirect"] = 17800000,
["Module:ParameterCount"] = 1650000,
["Module:Parameter_names_example"] = 2700,
["Module:Parameter_validation"] = 165000,
["Module:Parameter_validation/default_config"] = 165000,
["Module:Party_name_with_color"] = 13000,
["Module:Percentage"] = 18000,
["Module:Person_date"] = 1780000,
["Module:Person_height"] = 283000,
["Module:Person_length"] = 7700,
["Module:Person_weight"] = 85000,
["Module:Phone_size"] = 2100,
["Module:Photo_montage"] = 4900,
["Module:Piechart"] = 8300,
["Module:Piechart/cuts.json"] = 8300,
["Module:Plain_text"] = 1880000,
["Module:Pn"] = 4800,
["Module:Political_party"] = 150000,
["Module:Political_party/A"] = 27000,
["Module:Political_party/B"] = 20000,
["Module:Political_party/C"] = 49000,
["Module:Political_party/D"] = 58000,
["Module:Political_party/E"] = 6900,
["Module:Political_party/F"] = 15000,
["Module:Political_party/G"] = 22000,
["Module:Political_party/H"] = 7500,
["Module:Political_party/I"] = 62000,
["Module:Political_party/J"] = 10000,
["Module:Political_party/K"] = 6200,
["Module:Political_party/L"] = 47000,
["Module:Political_party/M"] = 15000,
["Module:Political_party/N"] = 38000,
["Module:Political_party/O"] = 7100,
["Module:Political_party/P"] = 34000,
["Module:Political_party/R"] = 58000,
["Module:Political_party/S"] = 37000,
["Module:Political_party/T"] = 15000,
["Module:Political_party/U"] = 22000,
["Module:Political_party/V"] = 8000,
["Module:Political_party/W"] = 15000,
["Module:Political_party/Y"] = 2400,
["Module:Pop_density"] = 10000,
["Module:PopulationFromWikidata"] = 15000,
["Module:Portal"] = 11300000,
["Module:Portal-inline"] = 251000,
["Module:Portal/images/a"] = 2040000,
["Module:Portal/images/aliases"] = 348000,
["Module:Portal/images/b"] = 3560000,
["Module:Portal/images/c"] = 2220000,
["Module:Portal/images/d"] = 120000,
["Module:Portal/images/e"] = 592000,
["Module:Portal/images/f"] = 1010000,
["Module:Portal/images/g"] = 700000,
["Module:Portal/images/h"] = 546000,
["Module:Portal/images/i"] = 1300000,
["Module:Portal/images/j"] = 346000,
["Module:Portal/images/k"] = 88000,
["Module:Portal/images/l"] = 522000,
["Module:Portal/images/m"] = 770000,
["Module:Portal/images/n"] = 840000,
["Module:Portal/images/o"] = 460000,
["Module:Portal/images/other"] = 271000,
["Module:Portal/images/p"] = 978000,
["Module:Portal/images/q"] = 3300,
["Module:Portal/images/r"] = 441000,
["Module:Portal/images/s"] = 2000000,
["Module:Portal/images/t"] = 859000,
["Module:Portal/images/u"] = 1390000,
["Module:Portal/images/v"] = 345000,
["Module:Portal/images/w"] = 213000,
["Module:Portal/images/y"] = 39000,
["Module:Portal/images/z"] = 6400,
["Module:Portal/styles.css"] = 10800000,
["Module:Portal_bar"] = 205000,
["Module:Portal_bar/styles.css"] = 205000,
["Module:PrevalenceData"] = 8300,
["Module:Professional_wrestling_profiles"] = 3200,
["Module:Professional_wrestling_results_table"] = 3200,
["Module:Progress_box"] = 19000,
["Module:Progress_box/config"] = 19000,
["Module:Progress_box/styles.css"] = 19000,
["Module:Protect"] = 126000,
["Module:Protected_edit_request"] = 59000,
["Module:Protection_banner"] = 74000,
["Module:Protection_banner/config"] = 74000,
["Module:Purge"] = 590000,
}
8iwdtzzjpd2ovoc7o5z0xefe3jcnquc
9120
9119
2026-08-22T14:37:10Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/P]]
9119
Scribunto
text/plain
return {
["P"] = 6400,
["P-1"] = 4800,
["P-phrases"] = 4200,
["P."] = 4000,
["P1"] = 232000,
["P2"] = 512000,
["PAGENAMEBASE"] = 1900000,
["PAGENAMEU"] = 56000,
["PAK"] = 3500,
["PD-US"] = 8600,
["PD-US-1923-abroad"] = 5400,
["PD-US-expired"] = 5000,
["PD-US-expired-abroad"] = 8700,
["PD-US-no_notice"] = 2300,
["PD-art"] = 3200,
["PD-ineligible-USonly"] = 7700,
["PD-notice"] = 26000,
["PD-old-100"] = 3200,
["PD-self"] = 31000,
["PD-textlogo"] = 6200,
["PDB_Gallery"] = 2900,
["PDanube"] = 3300,
["PER"] = 3500,
["PHI"] = 2700,
["PHL"] = 3700,
["PH_census"] = 2000,
["PLANTS"] = 4300,
["PM20"] = 3300,
["PMID"] = 6500,
["PNsign"] = 2100,
["POL"] = 68000,
["POR"] = 5600,
["POTD/Day"] = 2900,
["POTD_archive"] = 2500,
["POTD_archive/footer"] = 2500,
["POTD_default"] = 12000,
["POTD_image"] = 3800,
["POTD_image1"] = 2500,
["POTD_image2"] = 2500,
["POTD_navigation"] = 7800,
["POTD_texttitle"] = 2600,
["POTDlink"] = 8200,
["POV"] = 3100,
["POW"] = 2500,
["PR/header"] = 3100,
["PR/heading"] = 7200,
["PRI"] = 2200,
["PRT"] = 6400,
["PR_link"] = 118000,
["PS"] = 3100,
["Pad"] = 51000,
["Paddle_Steamer"] = 3100,
["Page"] = 4400,
["Page_name_sub"] = 52000,
["Page_needed"] = 23000,
["Page_tabs"] = 4100,
["Page_tabs/styles.css"] = 4100,
["Pagelinks"] = 74000,
["Pagelist"] = 15000,
["Pagetype"] = 11300000,
["Paid"] = 17000,
["Pakistani_English"] = 4000,
["Para"] = 2850000,
["Parabr"] = 3800,
["Paragraph_break"] = 2150000,
["Param_value"] = 152000,
["Param_value/styles.css"] = 152000,
["Parameter"] = 3000000,
["Parameter_names_example"] = 2700,
["ParmPart"] = 15000,
["Partial"] = 5800,
["Partial_minor_planet_designation"] = 5700,
["Partly_done"] = 4200,
["Party_color"] = 82000,
["Party_color_cell"] = 6600,
["Party_index_link"] = 3300,
["Party_name_with_color"] = 7200,
["Party_name_with_colour"] = 4200,
["Party_shading/Democratic"] = 19000,
["Party_shading/Independent"] = 3400,
["Party_shading/Republican"] = 18000,
["Party_stripe"] = 17000,
["Pass"] = 3300,
["Pb"] = 2120000,
["Pd-notice"] = 2200,
["Pedigree"] = 4400,
["Peer_review/heading"] = 10000,
["Peer_review_links"] = 3200,
["Peer_review_tools"] = 9600,
["Penalty_shoot-out"] = 5900,
["Pending"] = 6300,
["Pending_DYK_American_hooks"] = 5100,
["Pending_DYK_biographies"] = 11000,
["Pending_film"] = 2700,
["Pending_films_key"] = 2600,
["Pengoal"] = 12000,
["Penmiss"] = 14000,
["Percentage"] = 18000,
["Performance_key"] = 2800,
["Performance_key/styles.css"] = 2800,
["Period_color"] = 28000,
["Period_end"] = 26000,
["Period_id"] = 29000,
["Period_start"] = 29000,
["Personal_attack_removed"] = 2100,
["PeruTasks"] = 19000,
["Phab"] = 8100,
["Phabricator"] = 8300,
["Phanerozoic_250px"] = 25000,
["PharmNavFootnote"] = 5600,
["Philippine_census_reference"] = 2000,
["Philippine_name"] = 4200,
["Photo"] = 2200,
["Photo_montage"] = 4900,
["Photo_requested"] = 108000,
["Photograph_requested"] = 4600,
["Photomontage"] = 4400,
["Photoreq"] = 2900,
["Picture_of_the_day"] = 8200,
["Pie_chart"] = 8300,
["Pie_chart/styles.css"] = 8300,
["Ping"] = 284000,
["Pipe"] = 97000,
["Place_name_disambiguation"] = 40000,
["Plain_link"] = 119000,
["Plain_list"] = 16000,
["Plain_text"] = 109000,
["Plainlink"] = 30000,
["Plainlist"] = 390000,
["Plainlist/styles.css"] = 3110000,
["Player"] = 3900,
["Player2"] = 2900,
["Please_check_ISSN"] = 16000,
["Plural"] = 107000,
["Pluralize_from_text"] = 2780000,
["Pn"] = 2800,
["Poem_quote"] = 3900,
["Poemquote"] = 2700,
["Politician_icon"] = 34000,
["Politician_icon2"] = 34000,
["Politics_sidebar_below"] = 19000,
["Politics_sidebar_title"] = 19000,
["Polluted_category"] = 2500,
["Polparty"] = 31000,
["Pop_density"] = 10000,
["Population_Germany"] = 14000,
["Portal"] = 10800000,
["Portal-Class"] = 8100,
["Portal-inline"] = 245000,
["Portal_and_project"] = 261000,
["Portal_bar"] = 185000,
["Portal_box"] = 2200,
["Portalbar"] = 10000,
["Portuguese_name"] = 10000,
["Possible"] = 4000,
["Possibly_empty_category"] = 70000,
["Post-nominals"] = 63000,
["Post-nominals/AUS"] = 8500,
["Post-nominals/CAN"] = 10000,
["Post-nominals/GBR"] = 33000,
["Post-nominals/NZL"] = 4500,
["Postnominals"] = 11000,
["Pp"] = 8800,
["Pp-book-cover"] = 52000,
["Pp-extended"] = 10000,
["Pp-move"] = 11000,
["Pp-pc"] = 4400,
["Pp-protected"] = 13000,
["Pp-semi"] = 6800,
["Pp-semi-indef"] = 4800,
["Pp-template"] = 4400,
["Pp-vandalism"] = 2800,
["Precision"] = 6000,
["Preferences"] = 18000,
["Preferences/section"] = 3100,
["PresFoot"] = 3300,
["PresHead"] = 3900,
["PresRow"] = 3900,
["Press"] = 5700,
["Preview_warning"] = 603000,
["Primary_source_inline"] = 8100,
["Primary_sources"] = 33000,
["Principal_rank"] = 653000,
["Prisoner_of_war"] = 2600,
["Prl"] = 118000,
["ProCyclingStats"] = 2400,
["ProQuest"] = 35000,
["Professional_wrestling_profiles"] = 3200,
["Professional_wrestling_results_table"] = 3200,
["Profit"] = 3600,
["Progress_box"] = 19000,
["Project-Class"] = 13000,
["Project_other"] = 18000,
["Promotional"] = 18000,
["Proper_name"] = 2800,
["Prose"] = 3300,
["Protected_page_maintenance_message"] = 42000,
["Protection_padlock"] = 25000,
["Proxy_block"] = 2200,
["Pso"] = 5000,
["Purge"] = 567000,
["Purge_button"] = 19000,
["Purge_button/styles.css"] = 19000,
["Module:POTD_titletext"] = 2500,
["Module:Page"] = 122000,
["Module:PageLinks"] = 75000,
["Module:Page_tabs"] = 4100,
["Module:Pagelist"] = 15000,
["Module:Pagetype"] = 19000000,
["Module:Pagetype/config"] = 19000000,
["Module:Pagetype/disambiguation"] = 13300000,
["Module:Pagetype/rfd"] = 17100000,
["Module:Pagetype/setindex"] = 13500000,
["Module:Pagetype/softredirect"] = 17800000,
["Module:ParameterCount"] = 1650000,
["Module:Parameter_names_example"] = 2700,
["Module:Parameter_validation"] = 165000,
["Module:Parameter_validation/default_config"] = 165000,
["Module:Party_name_with_color"] = 13000,
["Module:Percentage"] = 18000,
["Module:Person_date"] = 1780000,
["Module:Person_height"] = 283000,
["Module:Person_length"] = 7700,
["Module:Person_weight"] = 85000,
["Module:Phone_size"] = 2100,
["Module:Photo_montage"] = 4900,
["Module:Piechart"] = 8300,
["Module:Piechart/cuts.json"] = 8300,
["Module:Plain_text"] = 1880000,
["Module:Pn"] = 4800,
["Module:Political_party"] = 150000,
["Module:Political_party/A"] = 27000,
["Module:Political_party/B"] = 20000,
["Module:Political_party/C"] = 49000,
["Module:Political_party/D"] = 58000,
["Module:Political_party/E"] = 6900,
["Module:Political_party/F"] = 15000,
["Module:Political_party/G"] = 22000,
["Module:Political_party/H"] = 7500,
["Module:Political_party/I"] = 62000,
["Module:Political_party/J"] = 10000,
["Module:Political_party/K"] = 6200,
["Module:Political_party/L"] = 47000,
["Module:Political_party/M"] = 15000,
["Module:Political_party/N"] = 38000,
["Module:Political_party/O"] = 7100,
["Module:Political_party/P"] = 34000,
["Module:Political_party/R"] = 58000,
["Module:Political_party/S"] = 37000,
["Module:Political_party/T"] = 15000,
["Module:Political_party/U"] = 22000,
["Module:Political_party/V"] = 8000,
["Module:Political_party/W"] = 15000,
["Module:Political_party/Y"] = 2400,
["Module:Pop_density"] = 10000,
["Module:PopulationFromWikidata"] = 15000,
["Module:Portal"] = 11300000,
["Module:Portal-inline"] = 251000,
["Module:Portal/images/a"] = 2040000,
["Module:Portal/images/aliases"] = 348000,
["Module:Portal/images/b"] = 3560000,
["Module:Portal/images/c"] = 2220000,
["Module:Portal/images/d"] = 120000,
["Module:Portal/images/e"] = 592000,
["Module:Portal/images/f"] = 1010000,
["Module:Portal/images/g"] = 700000,
["Module:Portal/images/h"] = 546000,
["Module:Portal/images/i"] = 1300000,
["Module:Portal/images/j"] = 346000,
["Module:Portal/images/k"] = 88000,
["Module:Portal/images/l"] = 522000,
["Module:Portal/images/m"] = 770000,
["Module:Portal/images/n"] = 840000,
["Module:Portal/images/o"] = 460000,
["Module:Portal/images/other"] = 271000,
["Module:Portal/images/p"] = 978000,
["Module:Portal/images/q"] = 3300,
["Module:Portal/images/r"] = 441000,
["Module:Portal/images/s"] = 2000000,
["Module:Portal/images/t"] = 859000,
["Module:Portal/images/u"] = 1390000,
["Module:Portal/images/v"] = 345000,
["Module:Portal/images/w"] = 213000,
["Module:Portal/images/y"] = 39000,
["Module:Portal/images/z"] = 6400,
["Module:Portal/styles.css"] = 10800000,
["Module:Portal_bar"] = 205000,
["Module:Portal_bar/styles.css"] = 205000,
["Module:PrevalenceData"] = 8300,
["Module:Professional_wrestling_profiles"] = 3200,
["Module:Professional_wrestling_results_table"] = 3200,
["Module:Progress_box"] = 19000,
["Module:Progress_box/config"] = 19000,
["Module:Progress_box/styles.css"] = 19000,
["Module:Protect"] = 126000,
["Module:Protected_edit_request"] = 59000,
["Module:Protection_banner"] = 74000,
["Module:Protection_banner/config"] = 74000,
["Module:Purge"] = 590000,
}
8iwdtzzjpd2ovoc7o5z0xefe3jcnquc
9327
9120
2026-08-23T05:09:55Z
Ahechtbot
346
[[Wikipedia:BOT|Bot]]: Updated page.
9327
Scribunto
text/plain
return {
["P"] = 6400,
["P-1"] = 4800,
["P-phrases"] = 4200,
["P."] = 4000,
["P1"] = 233000,
["P2"] = 513000,
["PAGENAMEBASE"] = 1900000,
["PAGENAMEU"] = 56000,
["PAK"] = 3500,
["PD-US"] = 8600,
["PD-US-1923-abroad"] = 5400,
["PD-US-expired"] = 5000,
["PD-US-expired-abroad"] = 8700,
["PD-US-no_notice"] = 2300,
["PD-art"] = 3200,
["PD-ineligible-USonly"] = 7700,
["PD-notice"] = 26000,
["PD-old-100"] = 3200,
["PD-self"] = 31000,
["PD-textlogo"] = 6200,
["PDB_Gallery"] = 2900,
["PDanube"] = 3300,
["PER"] = 3500,
["PHI"] = 2700,
["PHL"] = 3700,
["PH_census"] = 2000,
["PLANTS"] = 4300,
["PM20"] = 3300,
["PMID"] = 6500,
["PNsign"] = 2100,
["POL"] = 68000,
["POR"] = 5600,
["POTD/Day"] = 2900,
["POTD_archive"] = 2500,
["POTD_archive/footer"] = 2500,
["POTD_default"] = 12000,
["POTD_image"] = 3900,
["POTD_image1"] = 2500,
["POTD_image2"] = 2500,
["POTD_navigation"] = 7800,
["POTD_texttitle"] = 2600,
["POTDlink"] = 8200,
["POV"] = 3100,
["POW"] = 2500,
["PR/header"] = 3100,
["PR/heading"] = 7200,
["PRI"] = 2200,
["PRT"] = 6400,
["PR_link"] = 118000,
["PS"] = 3100,
["Pad"] = 51000,
["Paddle_Steamer"] = 3100,
["Page"] = 4400,
["Page_name_sub"] = 52000,
["Page_needed"] = 23000,
["Page_tabs"] = 4100,
["Page_tabs/styles.css"] = 4100,
["Pagelinks"] = 75000,
["Pagelist"] = 15000,
["Pagetype"] = 11300000,
["Paid"] = 17000,
["Pakistani_English"] = 4000,
["Para"] = 2880000,
["Parabr"] = 3800,
["Paragraph_break"] = 2150000,
["Param_value"] = 152000,
["Param_value/styles.css"] = 152000,
["Parameter"] = 3040000,
["Parameter_names_example"] = 2700,
["ParmPart"] = 15000,
["Partial"] = 5800,
["Partial_minor_planet_designation"] = 5700,
["Partly_done"] = 4300,
["Party_color"] = 82000,
["Party_color_cell"] = 6600,
["Party_index_link"] = 3300,
["Party_name_with_color"] = 7200,
["Party_name_with_colour"] = 4200,
["Party_shading/Democratic"] = 19000,
["Party_shading/Independent"] = 3400,
["Party_shading/Republican"] = 18000,
["Party_stripe"] = 17000,
["Pass"] = 3300,
["Pb"] = 2120000,
["Pd-notice"] = 2200,
["Pedigree"] = 4400,
["Peer_review/heading"] = 10000,
["Peer_review_links"] = 3200,
["Peer_review_tools"] = 9600,
["Penalty_shoot-out"] = 6000,
["Pending"] = 6400,
["Pending_DYK_American_hooks"] = 5100,
["Pending_DYK_biographies"] = 11000,
["Pending_film"] = 2700,
["Pending_films_key"] = 2600,
["Pengoal"] = 12000,
["Penmiss"] = 15000,
["Percentage"] = 18000,
["Performance_key"] = 2800,
["Performance_key/styles.css"] = 2800,
["Period_color"] = 28000,
["Period_end"] = 26000,
["Period_id"] = 29000,
["Period_start"] = 29000,
["Personal_attack_removed"] = 2100,
["PeruTasks"] = 19000,
["Phab"] = 8100,
["Phabricator"] = 8300,
["Phanerozoic_250px"] = 25000,
["PharmNavFootnote"] = 5600,
["Philippine_census_reference"] = 2000,
["Philippine_name"] = 4300,
["Photo"] = 2200,
["Photo_montage"] = 4900,
["Photo_requested"] = 108000,
["Photograph_requested"] = 4600,
["Photomontage"] = 4400,
["Photoreq"] = 2900,
["Picture_of_the_day"] = 8200,
["Pie_chart"] = 8300,
["Pie_chart/styles.css"] = 8300,
["Ping"] = 284000,
["Pipe"] = 97000,
["Place_name_disambiguation"] = 40000,
["Plain_link"] = 119000,
["Plain_list"] = 16000,
["Plain_text"] = 109000,
["Plainlink"] = 30000,
["Plainlist"] = 390000,
["Plainlist/styles.css"] = 3110000,
["Player"] = 3900,
["Player2"] = 2900,
["Please_check_ISSN"] = 16000,
["Plural"] = 107000,
["Pluralize_from_text"] = 2830000,
["Pn"] = 2800,
["Poem_quote"] = 3900,
["Poemquote"] = 2700,
["Politician_icon"] = 34000,
["Politician_icon2"] = 34000,
["Politics_sidebar_below"] = 19000,
["Politics_sidebar_title"] = 19000,
["Polluted_category"] = 2500,
["Polparty"] = 31000,
["Pop_density"] = 10000,
["Population_Germany"] = 14000,
["Portal"] = 10800000,
["Portal-Class"] = 8100,
["Portal-inline"] = 245000,
["Portal_and_project"] = 261000,
["Portal_bar"] = 185000,
["Portal_box"] = 2100,
["Portalbar"] = 9900,
["Portuguese_name"] = 10000,
["Possible"] = 4000,
["Possibly_empty_category"] = 70000,
["Post-nominals"] = 63000,
["Post-nominals/AUS"] = 8500,
["Post-nominals/CAN"] = 10000,
["Post-nominals/GBR"] = 33000,
["Post-nominals/NZL"] = 4500,
["Postnominals"] = 11000,
["Pp"] = 8800,
["Pp-book-cover"] = 52000,
["Pp-extended"] = 11000,
["Pp-move"] = 11000,
["Pp-pc"] = 4400,
["Pp-protected"] = 13000,
["Pp-semi"] = 6800,
["Pp-semi-indef"] = 4800,
["Pp-template"] = 4400,
["Pp-vandalism"] = 2800,
["Precision"] = 6000,
["Preferences"] = 18000,
["Preferences/section"] = 3100,
["PresFoot"] = 3300,
["PresHead"] = 3900,
["PresRow"] = 3900,
["Press"] = 5800,
["Preview_warning"] = 608000,
["Primary_source_inline"] = 8200,
["Primary_sources"] = 33000,
["Principal_rank"] = 653000,
["Prisoner_of_war"] = 2600,
["Prl"] = 118000,
["ProCyclingStats"] = 2400,
["ProQuest"] = 35000,
["Professional_wrestling_profiles"] = 3200,
["Professional_wrestling_results_table"] = 3200,
["Profit"] = 3600,
["Progress_box"] = 19000,
["Project-Class"] = 13000,
["Project_other"] = 18000,
["Promotional"] = 18000,
["Proper_name"] = 2800,
["Prose"] = 3300,
["Protected_page_maintenance_message"] = 42000,
["Protection_padlock"] = 25000,
["Proxy_block"] = 2200,
["Pso"] = 5000,
["Purge"] = 568000,
["Purge_button"] = 19000,
["Purge_button/styles.css"] = 19000,
["Module:POTD_titletext"] = 2500,
["Module:Page"] = 123000,
["Module:PageLinks"] = 75000,
["Module:Page_tabs"] = 4100,
["Module:Pagelist"] = 15000,
["Module:Pagetype"] = 19100000,
["Module:Pagetype/config"] = 19100000,
["Module:Pagetype/disambiguation"] = 13300000,
["Module:Pagetype/rfd"] = 17200000,
["Module:Pagetype/setindex"] = 13500000,
["Module:Pagetype/softredirect"] = 17800000,
["Module:ParameterCount"] = 1700000,
["Module:Parameter_names_example"] = 2700,
["Module:Parameter_validation"] = 165000,
["Module:Parameter_validation/default_config"] = 165000,
["Module:Party_name_with_color"] = 13000,
["Module:Percentage"] = 18000,
["Module:Person_date"] = 1780000,
["Module:Person_height"] = 283000,
["Module:Person_length"] = 7700,
["Module:Person_weight"] = 85000,
["Module:Phone_size"] = 2100,
["Module:Photo_montage"] = 4900,
["Module:Piechart"] = 8300,
["Module:Piechart/cuts.json"] = 8300,
["Module:Plain_text"] = 1880000,
["Module:Pn"] = 4800,
["Module:Political_party"] = 150000,
["Module:Political_party/A"] = 27000,
["Module:Political_party/B"] = 20000,
["Module:Political_party/C"] = 49000,
["Module:Political_party/D"] = 58000,
["Module:Political_party/E"] = 6900,
["Module:Political_party/F"] = 15000,
["Module:Political_party/G"] = 22000,
["Module:Political_party/H"] = 7500,
["Module:Political_party/I"] = 62000,
["Module:Political_party/J"] = 10000,
["Module:Political_party/K"] = 6200,
["Module:Political_party/L"] = 47000,
["Module:Political_party/M"] = 15000,
["Module:Political_party/N"] = 38000,
["Module:Political_party/O"] = 7100,
["Module:Political_party/P"] = 34000,
["Module:Political_party/R"] = 58000,
["Module:Political_party/S"] = 37000,
["Module:Political_party/T"] = 15000,
["Module:Political_party/U"] = 22000,
["Module:Political_party/V"] = 7900,
["Module:Political_party/W"] = 15000,
["Module:Political_party/Y"] = 2400,
["Module:Pop_density"] = 10000,
["Module:PopulationFromWikidata"] = 15000,
["Module:Portal"] = 11300000,
["Module:Portal-inline"] = 250000,
["Module:Portal/images/a"] = 2050000,
["Module:Portal/images/aliases"] = 356000,
["Module:Portal/images/b"] = 3560000,
["Module:Portal/images/c"] = 2260000,
["Module:Portal/images/d"] = 120000,
["Module:Portal/images/e"] = 594000,
["Module:Portal/images/f"] = 1020000,
["Module:Portal/images/g"] = 700000,
["Module:Portal/images/h"] = 546000,
["Module:Portal/images/i"] = 1300000,
["Module:Portal/images/j"] = 346000,
["Module:Portal/images/k"] = 88000,
["Module:Portal/images/l"] = 530000,
["Module:Portal/images/m"] = 771000,
["Module:Portal/images/n"] = 840000,
["Module:Portal/images/o"] = 460000,
["Module:Portal/images/other"] = 271000,
["Module:Portal/images/p"] = 979000,
["Module:Portal/images/q"] = 3300,
["Module:Portal/images/r"] = 441000,
["Module:Portal/images/s"] = 2000000,
["Module:Portal/images/t"] = 860000,
["Module:Portal/images/u"] = 1390000,
["Module:Portal/images/v"] = 346000,
["Module:Portal/images/w"] = 213000,
["Module:Portal/images/y"] = 39000,
["Module:Portal/images/z"] = 6500,
["Module:Portal/styles.css"] = 10800000,
["Module:Portal_bar"] = 206000,
["Module:Portal_bar/styles.css"] = 206000,
["Module:PrevalenceData"] = 8300,
["Module:Professional_wrestling_profiles"] = 3200,
["Module:Professional_wrestling_results_table"] = 3200,
["Module:Progress_box"] = 19000,
["Module:Progress_box/config"] = 19000,
["Module:Progress_box/styles.css"] = 19000,
["Module:Protect"] = 126000,
["Module:Protected_edit_request"] = 60000,
["Module:Protection_banner"] = 74000,
["Module:Protection_banner/config"] = 74000,
["Module:Purge"] = 591000,
}
7esc1ag0vtespwi4dle2ds32xzhjm7c
9328
9327
2026-08-23T08:17:43Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/P]]
9327
Scribunto
text/plain
return {
["P"] = 6400,
["P-1"] = 4800,
["P-phrases"] = 4200,
["P."] = 4000,
["P1"] = 233000,
["P2"] = 513000,
["PAGENAMEBASE"] = 1900000,
["PAGENAMEU"] = 56000,
["PAK"] = 3500,
["PD-US"] = 8600,
["PD-US-1923-abroad"] = 5400,
["PD-US-expired"] = 5000,
["PD-US-expired-abroad"] = 8700,
["PD-US-no_notice"] = 2300,
["PD-art"] = 3200,
["PD-ineligible-USonly"] = 7700,
["PD-notice"] = 26000,
["PD-old-100"] = 3200,
["PD-self"] = 31000,
["PD-textlogo"] = 6200,
["PDB_Gallery"] = 2900,
["PDanube"] = 3300,
["PER"] = 3500,
["PHI"] = 2700,
["PHL"] = 3700,
["PH_census"] = 2000,
["PLANTS"] = 4300,
["PM20"] = 3300,
["PMID"] = 6500,
["PNsign"] = 2100,
["POL"] = 68000,
["POR"] = 5600,
["POTD/Day"] = 2900,
["POTD_archive"] = 2500,
["POTD_archive/footer"] = 2500,
["POTD_default"] = 12000,
["POTD_image"] = 3900,
["POTD_image1"] = 2500,
["POTD_image2"] = 2500,
["POTD_navigation"] = 7800,
["POTD_texttitle"] = 2600,
["POTDlink"] = 8200,
["POV"] = 3100,
["POW"] = 2500,
["PR/header"] = 3100,
["PR/heading"] = 7200,
["PRI"] = 2200,
["PRT"] = 6400,
["PR_link"] = 118000,
["PS"] = 3100,
["Pad"] = 51000,
["Paddle_Steamer"] = 3100,
["Page"] = 4400,
["Page_name_sub"] = 52000,
["Page_needed"] = 23000,
["Page_tabs"] = 4100,
["Page_tabs/styles.css"] = 4100,
["Pagelinks"] = 75000,
["Pagelist"] = 15000,
["Pagetype"] = 11300000,
["Paid"] = 17000,
["Pakistani_English"] = 4000,
["Para"] = 2880000,
["Parabr"] = 3800,
["Paragraph_break"] = 2150000,
["Param_value"] = 152000,
["Param_value/styles.css"] = 152000,
["Parameter"] = 3040000,
["Parameter_names_example"] = 2700,
["ParmPart"] = 15000,
["Partial"] = 5800,
["Partial_minor_planet_designation"] = 5700,
["Partly_done"] = 4300,
["Party_color"] = 82000,
["Party_color_cell"] = 6600,
["Party_index_link"] = 3300,
["Party_name_with_color"] = 7200,
["Party_name_with_colour"] = 4200,
["Party_shading/Democratic"] = 19000,
["Party_shading/Independent"] = 3400,
["Party_shading/Republican"] = 18000,
["Party_stripe"] = 17000,
["Pass"] = 3300,
["Pb"] = 2120000,
["Pd-notice"] = 2200,
["Pedigree"] = 4400,
["Peer_review/heading"] = 10000,
["Peer_review_links"] = 3200,
["Peer_review_tools"] = 9600,
["Penalty_shoot-out"] = 6000,
["Pending"] = 6400,
["Pending_DYK_American_hooks"] = 5100,
["Pending_DYK_biographies"] = 11000,
["Pending_film"] = 2700,
["Pending_films_key"] = 2600,
["Pengoal"] = 12000,
["Penmiss"] = 15000,
["Percentage"] = 18000,
["Performance_key"] = 2800,
["Performance_key/styles.css"] = 2800,
["Period_color"] = 28000,
["Period_end"] = 26000,
["Period_id"] = 29000,
["Period_start"] = 29000,
["Personal_attack_removed"] = 2100,
["PeruTasks"] = 19000,
["Phab"] = 8100,
["Phabricator"] = 8300,
["Phanerozoic_250px"] = 25000,
["PharmNavFootnote"] = 5600,
["Philippine_census_reference"] = 2000,
["Philippine_name"] = 4300,
["Photo"] = 2200,
["Photo_montage"] = 4900,
["Photo_requested"] = 108000,
["Photograph_requested"] = 4600,
["Photomontage"] = 4400,
["Photoreq"] = 2900,
["Picture_of_the_day"] = 8200,
["Pie_chart"] = 8300,
["Pie_chart/styles.css"] = 8300,
["Ping"] = 284000,
["Pipe"] = 97000,
["Place_name_disambiguation"] = 40000,
["Plain_link"] = 119000,
["Plain_list"] = 16000,
["Plain_text"] = 109000,
["Plainlink"] = 30000,
["Plainlist"] = 390000,
["Plainlist/styles.css"] = 3110000,
["Player"] = 3900,
["Player2"] = 2900,
["Please_check_ISSN"] = 16000,
["Plural"] = 107000,
["Pluralize_from_text"] = 2830000,
["Pn"] = 2800,
["Poem_quote"] = 3900,
["Poemquote"] = 2700,
["Politician_icon"] = 34000,
["Politician_icon2"] = 34000,
["Politics_sidebar_below"] = 19000,
["Politics_sidebar_title"] = 19000,
["Polluted_category"] = 2500,
["Polparty"] = 31000,
["Pop_density"] = 10000,
["Population_Germany"] = 14000,
["Portal"] = 10800000,
["Portal-Class"] = 8100,
["Portal-inline"] = 245000,
["Portal_and_project"] = 261000,
["Portal_bar"] = 185000,
["Portal_box"] = 2100,
["Portalbar"] = 9900,
["Portuguese_name"] = 10000,
["Possible"] = 4000,
["Possibly_empty_category"] = 70000,
["Post-nominals"] = 63000,
["Post-nominals/AUS"] = 8500,
["Post-nominals/CAN"] = 10000,
["Post-nominals/GBR"] = 33000,
["Post-nominals/NZL"] = 4500,
["Postnominals"] = 11000,
["Pp"] = 8800,
["Pp-book-cover"] = 52000,
["Pp-extended"] = 11000,
["Pp-move"] = 11000,
["Pp-pc"] = 4400,
["Pp-protected"] = 13000,
["Pp-semi"] = 6800,
["Pp-semi-indef"] = 4800,
["Pp-template"] = 4400,
["Pp-vandalism"] = 2800,
["Precision"] = 6000,
["Preferences"] = 18000,
["Preferences/section"] = 3100,
["PresFoot"] = 3300,
["PresHead"] = 3900,
["PresRow"] = 3900,
["Press"] = 5800,
["Preview_warning"] = 608000,
["Primary_source_inline"] = 8200,
["Primary_sources"] = 33000,
["Principal_rank"] = 653000,
["Prisoner_of_war"] = 2600,
["Prl"] = 118000,
["ProCyclingStats"] = 2400,
["ProQuest"] = 35000,
["Professional_wrestling_profiles"] = 3200,
["Professional_wrestling_results_table"] = 3200,
["Profit"] = 3600,
["Progress_box"] = 19000,
["Project-Class"] = 13000,
["Project_other"] = 18000,
["Promotional"] = 18000,
["Proper_name"] = 2800,
["Prose"] = 3300,
["Protected_page_maintenance_message"] = 42000,
["Protection_padlock"] = 25000,
["Proxy_block"] = 2200,
["Pso"] = 5000,
["Purge"] = 568000,
["Purge_button"] = 19000,
["Purge_button/styles.css"] = 19000,
["Module:POTD_titletext"] = 2500,
["Module:Page"] = 123000,
["Module:PageLinks"] = 75000,
["Module:Page_tabs"] = 4100,
["Module:Pagelist"] = 15000,
["Module:Pagetype"] = 19100000,
["Module:Pagetype/config"] = 19100000,
["Module:Pagetype/disambiguation"] = 13300000,
["Module:Pagetype/rfd"] = 17200000,
["Module:Pagetype/setindex"] = 13500000,
["Module:Pagetype/softredirect"] = 17800000,
["Module:ParameterCount"] = 1700000,
["Module:Parameter_names_example"] = 2700,
["Module:Parameter_validation"] = 165000,
["Module:Parameter_validation/default_config"] = 165000,
["Module:Party_name_with_color"] = 13000,
["Module:Percentage"] = 18000,
["Module:Person_date"] = 1780000,
["Module:Person_height"] = 283000,
["Module:Person_length"] = 7700,
["Module:Person_weight"] = 85000,
["Module:Phone_size"] = 2100,
["Module:Photo_montage"] = 4900,
["Module:Piechart"] = 8300,
["Module:Piechart/cuts.json"] = 8300,
["Module:Plain_text"] = 1880000,
["Module:Pn"] = 4800,
["Module:Political_party"] = 150000,
["Module:Political_party/A"] = 27000,
["Module:Political_party/B"] = 20000,
["Module:Political_party/C"] = 49000,
["Module:Political_party/D"] = 58000,
["Module:Political_party/E"] = 6900,
["Module:Political_party/F"] = 15000,
["Module:Political_party/G"] = 22000,
["Module:Political_party/H"] = 7500,
["Module:Political_party/I"] = 62000,
["Module:Political_party/J"] = 10000,
["Module:Political_party/K"] = 6200,
["Module:Political_party/L"] = 47000,
["Module:Political_party/M"] = 15000,
["Module:Political_party/N"] = 38000,
["Module:Political_party/O"] = 7100,
["Module:Political_party/P"] = 34000,
["Module:Political_party/R"] = 58000,
["Module:Political_party/S"] = 37000,
["Module:Political_party/T"] = 15000,
["Module:Political_party/U"] = 22000,
["Module:Political_party/V"] = 7900,
["Module:Political_party/W"] = 15000,
["Module:Political_party/Y"] = 2400,
["Module:Pop_density"] = 10000,
["Module:PopulationFromWikidata"] = 15000,
["Module:Portal"] = 11300000,
["Module:Portal-inline"] = 250000,
["Module:Portal/images/a"] = 2050000,
["Module:Portal/images/aliases"] = 356000,
["Module:Portal/images/b"] = 3560000,
["Module:Portal/images/c"] = 2260000,
["Module:Portal/images/d"] = 120000,
["Module:Portal/images/e"] = 594000,
["Module:Portal/images/f"] = 1020000,
["Module:Portal/images/g"] = 700000,
["Module:Portal/images/h"] = 546000,
["Module:Portal/images/i"] = 1300000,
["Module:Portal/images/j"] = 346000,
["Module:Portal/images/k"] = 88000,
["Module:Portal/images/l"] = 530000,
["Module:Portal/images/m"] = 771000,
["Module:Portal/images/n"] = 840000,
["Module:Portal/images/o"] = 460000,
["Module:Portal/images/other"] = 271000,
["Module:Portal/images/p"] = 979000,
["Module:Portal/images/q"] = 3300,
["Module:Portal/images/r"] = 441000,
["Module:Portal/images/s"] = 2000000,
["Module:Portal/images/t"] = 860000,
["Module:Portal/images/u"] = 1390000,
["Module:Portal/images/v"] = 346000,
["Module:Portal/images/w"] = 213000,
["Module:Portal/images/y"] = 39000,
["Module:Portal/images/z"] = 6500,
["Module:Portal/styles.css"] = 10800000,
["Module:Portal_bar"] = 206000,
["Module:Portal_bar/styles.css"] = 206000,
["Module:PrevalenceData"] = 8300,
["Module:Professional_wrestling_profiles"] = 3200,
["Module:Professional_wrestling_results_table"] = 3200,
["Module:Progress_box"] = 19000,
["Module:Progress_box/config"] = 19000,
["Module:Progress_box/styles.css"] = 19000,
["Module:Protect"] = 126000,
["Module:Protected_edit_request"] = 60000,
["Module:Protection_banner"] = 74000,
["Module:Protection_banner/config"] = 74000,
["Module:Purge"] = 591000,
}
7esc1ag0vtespwi4dle2ds32xzhjm7c
Module:Protection banner/documentation
828
1078
9121
2016-03-21T01:07:12Z
en>Jackmcbarn
0
Middleclass is way overkill here
9121
Scribunto
text/plain
-- This module generates documentation for [[Module:Protection banner]].
--------------------------------------------------------------------------------
-- Documentation class
--------------------------------------------------------------------------------
local Documentation = {}
Documentation.__index = Documentation
function Documentation:new(mainCfg, docCfg)
return setmetatable({
_mainCfg = mainCfg,
_docCfg = docCfg
}, self)
end
function Documentation:makeReasonTable()
-- Get the data from the cfg.banners table.
local rowData = {}
for action, reasonTables in pairs(self._mainCfg.banners) do
for reason, t in pairs(reasonTables) do
rowData[#rowData + 1] = {
reason = reason,
action = action,
description = t.description
}
end
end
-- Sort the table into alphabetical order, first by action and then by
-- reason.
table.sort(rowData, function (t1, t2)
if t1.action == t2.action then
return t1.reason < t2.reason
else
return t1.action < t2.action
end
end)
-- Assemble a wikitable of the data.
local ret = {}
ret[#ret + 1] = '{| class="wikitable"'
if #rowData < 1 then
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'| colspan="3" | %s',
self._docCfg['documentation-blurb-noreasons']
)
else
-- Header
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'! %s\n! %s\n! %s',
self._docCfg['documentation-heading-reason'],
self._docCfg['documentation-heading-action'],
self._docCfg['documentation-heading-description']
)
-- Rows
for _, t in ipairs(rowData) do
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'| %s\n| %s\n| %s',
t.reason,
t.action,
t.description or ''
)
end
end
ret[#ret + 1] = '|}'
return table.concat(ret, '\n')
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p.reasonTable()
local mainCfg = require('Module:Protection banner/config')
local docCfg = require('Module:Protection banner/documentation/config')
local documentationObj = Documentation:new(mainCfg, docCfg)
return documentationObj:makeReasonTable()
end
return p
imbe3ltwmegb6fcpqrsgth07bd9uybu
9122
9121
2026-08-22T14:37:10Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Protection_banner/documentation]]
9121
Scribunto
text/plain
-- This module generates documentation for [[Module:Protection banner]].
--------------------------------------------------------------------------------
-- Documentation class
--------------------------------------------------------------------------------
local Documentation = {}
Documentation.__index = Documentation
function Documentation:new(mainCfg, docCfg)
return setmetatable({
_mainCfg = mainCfg,
_docCfg = docCfg
}, self)
end
function Documentation:makeReasonTable()
-- Get the data from the cfg.banners table.
local rowData = {}
for action, reasonTables in pairs(self._mainCfg.banners) do
for reason, t in pairs(reasonTables) do
rowData[#rowData + 1] = {
reason = reason,
action = action,
description = t.description
}
end
end
-- Sort the table into alphabetical order, first by action and then by
-- reason.
table.sort(rowData, function (t1, t2)
if t1.action == t2.action then
return t1.reason < t2.reason
else
return t1.action < t2.action
end
end)
-- Assemble a wikitable of the data.
local ret = {}
ret[#ret + 1] = '{| class="wikitable"'
if #rowData < 1 then
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'| colspan="3" | %s',
self._docCfg['documentation-blurb-noreasons']
)
else
-- Header
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'! %s\n! %s\n! %s',
self._docCfg['documentation-heading-reason'],
self._docCfg['documentation-heading-action'],
self._docCfg['documentation-heading-description']
)
-- Rows
for _, t in ipairs(rowData) do
ret[#ret + 1] = '|-'
ret[#ret + 1] = string.format(
'| %s\n| %s\n| %s',
t.reason,
t.action,
t.description or ''
)
end
end
ret[#ret + 1] = '|}'
return table.concat(ret, '\n')
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p.reasonTable()
local mainCfg = require('Module:Protection banner/config')
local docCfg = require('Module:Protection banner/documentation/config')
local documentationObj = Documentation:new(mainCfg, docCfg)
return documentationObj:makeReasonTable()
end
return p
imbe3ltwmegb6fcpqrsgth07bd9uybu
Module:Protection banner/documentation/config
828
1079
9123
2026-04-27T21:33:56Z
en>Vipz
0
Undid revision [[Special:Diff/1351425922|1351425922]] by [[Special:Contributions/Vipz|Vipz]] ([[User talk:Vipz|talk]])
9123
Scribunto
text/plain
-- This module contains messages used to generate the documentation for
-- [[Module:Protection banner]].
return {
-- Reason table headings.
['documentation-heading-reason'] = 'Reason',
['documentation-heading-action'] = 'Action',
['documentation-heading-description'] = 'Description',
-- Blurb to display if no reasons were found in the module config.
['documentation-blurb-noreasons'] = 'No reason values were found in the module'
.. ' configuration.',
}
1hgoczciij55c2768j2k1ubzxkco9p9
9124
9123
2026-08-22T14:37:10Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Protection_banner/documentation/config]]
9123
Scribunto
text/plain
-- This module contains messages used to generate the documentation for
-- [[Module:Protection banner]].
return {
-- Reason table headings.
['documentation-heading-reason'] = 'Reason',
['documentation-heading-action'] = 'Action',
['documentation-heading-description'] = 'Description',
-- Blurb to display if no reasons were found in the module config.
['documentation-blurb-noreasons'] = 'No reason values were found in the module'
.. ' configuration.',
}
1hgoczciij55c2768j2k1ubzxkco9p9
Tempilet:Requested move notice
10
1080
9125
2024-09-27T21:54:51Z
en>RMCD bot
0
Removing notice of move discussion
9125
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:Unsubst||$B=
{{mbox
| subst= <includeonly>{{subst:</includeonly><includeonly>substcheck}}</includeonly>
| type = move
| small = {{{small|}}}
| text = <b>A request that this {{main other|article|page}} title be changed{{#ifeq:{{{1|?}}}|?|| to ''{{no redirect|{{{1}}}}}''}} is {{#if:{{{2|}}}|[[{{{2}}}|under discussion]]|[[:{{NAMESPACE}} talk:{{PAGENAME}}#{{{section|}}}|under discussion]]}}</b>. Please <em>do not move</em> this {{main other|article|page}} until the discussion is closed.
}}
}}<noinclude>
{{documentation}}
</noinclude>
m8leh6fx3cm47b963h68rgop67tgyof
9126
9125
2026-08-22T14:37:11Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Requested_move_notice]]
9125
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#invoke:Unsubst||$B=
{{mbox
| subst= <includeonly>{{subst:</includeonly><includeonly>substcheck}}</includeonly>
| type = move
| small = {{{small|}}}
| text = <b>A request that this {{main other|article|page}} title be changed{{#ifeq:{{{1|?}}}|?|| to ''{{no redirect|{{{1}}}}}''}} is {{#if:{{{2|}}}|[[{{{2}}}|under discussion]]|[[:{{NAMESPACE}} talk:{{PAGENAME}}#{{{section|}}}|under discussion]]}}</b>. Please <em>do not move</em> this {{main other|article|page}} until the discussion is closed.
}}
}}<noinclude>
{{documentation}}
</noinclude>
m8leh6fx3cm47b963h68rgop67tgyof
Tempilet:Protection padlock/doc
10
1081
9127
2026-05-05T14:19:14Z
en>Paine Ellsworth
0
fmt
9127
wikitext
text/x-wiki
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])-->
{{High-use}}
{{Twinkle standard installation}}
{{User:MusikBot II/Config notice}}
{{tsh|pp}}
{{lua|Module:Protection banner}}
This is a general template for producing '''p'''rotection banners and '''p'''adlock icons. It can be used with any protection reason, any protection action, and any protection level.
== Usage ==
{{pp
| 1 = ''reason''
| small = ''yes''
| action = ''action''
| date = ''protection date''
| user = ''username''
| section = ''talk page section name''
| category = ''no''
}}
== Parameters ==
All parameters are optional:
* {{para|1}} – The reason that the page was protected. If set, this must be one of the values listed in the [[#Reasons|reasons table]].
* {{para|small}} – If set to {{pval|yes}}, {{pval|y}}, {{pval|1}}, or {{pval|true}}, a padlock icon is generated instead of a full protection banner.
* {{para|action}} – The protection action. Must be one of {{pval|edit}} (for normal protection), {{pval|move}} (for move-protection) or {{pval|autoreview}} (for pending changes). The default value is {{pval|edit}}.
* {{para|date}} – The protection date. This must be valid input to the second parameter of the [[mw:Help:Extension:ParserFunctions##time|#time parser function]]. This argument only has an effect for the {{pval|office}} and {{pval|reset}} reasons.
* {{para|user}} – The username of the user to generate links for. As of July 2014, this only has an effect when the {{pval|usertalk}} reason is specified.
* {{para|section}} – The section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of ''reason''.
* {{para|category}} – Categories are suppressed if this is set to {{pval|no}}, {{pval|n}}, {{pval|0}}, or {{pval|false}}.
== Reasons ==
The following table contains the available reasons, plus the actions for which they are available. Reasons are used to customize the banner text, to place articles in more specific hidden categories such as [[:Category:Wikipedia pages semi-protected against vandalism]], and sometimes to change the icon of the banner (e.g. office actions).
{{#invoke:Protection banner/documentation|reasonTable}}
== Syntax examples ==
'''Padlock icons'''
Padlock icon for a page protected due to vandalism:
{{pp|vandalism|small=yes}}
Padlock icon for a page temporarily protected due to editing disputes:
{{pp|dispute|small=yes}}
'''Banners'''
Banner for a page protected due to sockpuppetry, with a link to a talk page discussion:
{{pp|sock|section=Sockpuppetry concerns}}
Banner for a page temporarily move-protected due to page-move vandalism:
{{pp|vandalism|action=move}}
== Visibility ==
This template will hide itself (not display a padlock icon) if it is used on a page that is not currently protected. [[User:MusikBot II]] may also automatically remove the template wikicode from pages that are not currently protected.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "Produces banners to describe why a page is protected and padlock icons",
"params": {
"1": {
"label": "Reason",
"description": "Reason for protection, may be one of: blp, dispute, dmca, mainpage, office, reset, sock, template, usertalk, vandalism",
"type": "string",
"suggestedvalues": [
"vandalism",
"template",
"usertalk",
"blp",
"dispute",
"dmca",
"ecp",
"mainpage",
"reset",
"sock",
"office"
],
"suggested": true
},
"small": {
"description": "Specifies whether only a padlock is generated. If set to \"yes\", \"y\", \"1\", or \"true\", a padlock icon is generated instead of a full protection banner.",
"example": "1",
"type": "boolean",
"default": "0",
"suggested": true,
"label": "Small?"
},
"action": {
"description": "Action which is restricted. Must be one of \"edit\" (for normal protection), \"move\" (for move-protection) or \"autoreview\" (for pending changes).",
"example": "move",
"type": "string",
"default": "edit",
"label": "Restricted action",
"suggestedvalues": [
"edit",
"move",
"autoreview"
],
"suggested": true
},
"date": {
"description": "Protection date. This must be valid input to the second parameter of the #time parser function. This argument only has an effect for the \"office\" and \"reset\" reasons.",
"type": "date",
"label": "Date protected",
"example": "yyyy-mm-dd"
},
"user": {
"description": "Username of the user to generate links for. This only has an effect when the \"usertalk\" reason is specified.",
"type": "wiki-user-name",
"label": "Username"
},
"section": {
"description": "Section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of reason.",
"type": "string",
"label": "Section name of talk"
},
"category": {
"description": "Categories are suppressed if this is set to \"no\", \"n\", \"0\", or \"false\".",
"type": "boolean",
"label": "Categorize?",
"example": "0",
"default": "1"
}
},
"paramOrder": [
"1",
"small",
"action",
"date",
"user",
"section",
"category"
]
}
</templatedata>
== See also ==
{{Protection templates}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Protection templates]]
[[Category:Templates that add a tracking category]]
}}</includeonly>
c31e1lqqk2as2wfi0fhksuj8cqx91y3
9128
9127
2026-08-22T14:37:11Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Protection_padlock/doc]]
9127
wikitext
text/x-wiki
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])-->
{{High-use}}
{{Twinkle standard installation}}
{{User:MusikBot II/Config notice}}
{{tsh|pp}}
{{lua|Module:Protection banner}}
This is a general template for producing '''p'''rotection banners and '''p'''adlock icons. It can be used with any protection reason, any protection action, and any protection level.
== Usage ==
{{pp
| 1 = ''reason''
| small = ''yes''
| action = ''action''
| date = ''protection date''
| user = ''username''
| section = ''talk page section name''
| category = ''no''
}}
== Parameters ==
All parameters are optional:
* {{para|1}} – The reason that the page was protected. If set, this must be one of the values listed in the [[#Reasons|reasons table]].
* {{para|small}} – If set to {{pval|yes}}, {{pval|y}}, {{pval|1}}, or {{pval|true}}, a padlock icon is generated instead of a full protection banner.
* {{para|action}} – The protection action. Must be one of {{pval|edit}} (for normal protection), {{pval|move}} (for move-protection) or {{pval|autoreview}} (for pending changes). The default value is {{pval|edit}}.
* {{para|date}} – The protection date. This must be valid input to the second parameter of the [[mw:Help:Extension:ParserFunctions##time|#time parser function]]. This argument only has an effect for the {{pval|office}} and {{pval|reset}} reasons.
* {{para|user}} – The username of the user to generate links for. As of July 2014, this only has an effect when the {{pval|usertalk}} reason is specified.
* {{para|section}} – The section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of ''reason''.
* {{para|category}} – Categories are suppressed if this is set to {{pval|no}}, {{pval|n}}, {{pval|0}}, or {{pval|false}}.
== Reasons ==
The following table contains the available reasons, plus the actions for which they are available. Reasons are used to customize the banner text, to place articles in more specific hidden categories such as [[:Category:Wikipedia pages semi-protected against vandalism]], and sometimes to change the icon of the banner (e.g. office actions).
{{#invoke:Protection banner/documentation|reasonTable}}
== Syntax examples ==
'''Padlock icons'''
Padlock icon for a page protected due to vandalism:
{{pp|vandalism|small=yes}}
Padlock icon for a page temporarily protected due to editing disputes:
{{pp|dispute|small=yes}}
'''Banners'''
Banner for a page protected due to sockpuppetry, with a link to a talk page discussion:
{{pp|sock|section=Sockpuppetry concerns}}
Banner for a page temporarily move-protected due to page-move vandalism:
{{pp|vandalism|action=move}}
== Visibility ==
This template will hide itself (not display a padlock icon) if it is used on a page that is not currently protected. [[User:MusikBot II]] may also automatically remove the template wikicode from pages that are not currently protected.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "Produces banners to describe why a page is protected and padlock icons",
"params": {
"1": {
"label": "Reason",
"description": "Reason for protection, may be one of: blp, dispute, dmca, mainpage, office, reset, sock, template, usertalk, vandalism",
"type": "string",
"suggestedvalues": [
"vandalism",
"template",
"usertalk",
"blp",
"dispute",
"dmca",
"ecp",
"mainpage",
"reset",
"sock",
"office"
],
"suggested": true
},
"small": {
"description": "Specifies whether only a padlock is generated. If set to \"yes\", \"y\", \"1\", or \"true\", a padlock icon is generated instead of a full protection banner.",
"example": "1",
"type": "boolean",
"default": "0",
"suggested": true,
"label": "Small?"
},
"action": {
"description": "Action which is restricted. Must be one of \"edit\" (for normal protection), \"move\" (for move-protection) or \"autoreview\" (for pending changes).",
"example": "move",
"type": "string",
"default": "edit",
"label": "Restricted action",
"suggestedvalues": [
"edit",
"move",
"autoreview"
],
"suggested": true
},
"date": {
"description": "Protection date. This must be valid input to the second parameter of the #time parser function. This argument only has an effect for the \"office\" and \"reset\" reasons.",
"type": "date",
"label": "Date protected",
"example": "yyyy-mm-dd"
},
"user": {
"description": "Username of the user to generate links for. This only has an effect when the \"usertalk\" reason is specified.",
"type": "wiki-user-name",
"label": "Username"
},
"section": {
"description": "Section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of reason.",
"type": "string",
"label": "Section name of talk"
},
"category": {
"description": "Categories are suppressed if this is set to \"no\", \"n\", \"0\", or \"false\".",
"type": "boolean",
"label": "Categorize?",
"example": "0",
"default": "1"
}
},
"paramOrder": [
"1",
"small",
"action",
"date",
"user",
"section",
"category"
]
}
</templatedata>
== See also ==
{{Protection templates}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Protection templates]]
[[Category:Templates that add a tracking category]]
}}</includeonly>
c31e1lqqk2as2wfi0fhksuj8cqx91y3
9211
9128
2026-08-23T03:30:29Z
RAPTOR7762
18
/* */
9211
wikitext
text/x-wiki
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])-->
{{High-use}}
{{User:MusikBot II/Config notice}}
{{tsh|pp}}
{{lua|Module:Protection banner}}
This is a general template for producing '''p'''rotection banners and '''p'''adlock icons. It can be used with any protection reason, any protection action, and any protection level.
== Usage ==
{{pp
| 1 = ''reason''
| small = ''yes''
| action = ''action''
| date = ''protection date''
| user = ''username''
| section = ''talk page section name''
| category = ''no''
}}
== Parameters ==
All parameters are optional:
* {{para|1}} – The reason that the page was protected. If set, this must be one of the values listed in the [[#Reasons|reasons table]].
* {{para|small}} – If set to {{pval|yes}}, {{pval|y}}, {{pval|1}}, or {{pval|true}}, a padlock icon is generated instead of a full protection banner.
* {{para|action}} – The protection action. Must be one of {{pval|edit}} (for normal protection), {{pval|move}} (for move-protection) or {{pval|autoreview}} (for pending changes). The default value is {{pval|edit}}.
* {{para|date}} – The protection date. This must be valid input to the second parameter of the [[mw:Help:Extension:ParserFunctions##time|#time parser function]]. This argument only has an effect for the {{pval|office}} and {{pval|reset}} reasons.
* {{para|user}} – The username of the user to generate links for. As of July 2014, this only has an effect when the {{pval|usertalk}} reason is specified.
* {{para|section}} – The section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of ''reason''.
* {{para|category}} – Categories are suppressed if this is set to {{pval|no}}, {{pval|n}}, {{pval|0}}, or {{pval|false}}.
== Reasons ==
The following table contains the available reasons, plus the actions for which they are available. Reasons are used to customize the banner text, to place articles in more specific hidden categories such as [[:Category:Wikipedia pages semi-protected against vandalism]], and sometimes to change the icon of the banner (e.g. office actions).
{{#invoke:Protection banner/documentation|reasonTable}}
== Syntax examples ==
'''Padlock icons'''
Padlock icon for a page protected due to vandalism:
{{pp|vandalism|small=yes}}
Padlock icon for a page temporarily protected due to editing disputes:
{{pp|dispute|small=yes}}
'''Banners'''
Banner for a page protected due to sockpuppetry, with a link to a talk page discussion:
{{pp|sock|section=Sockpuppetry concerns}}
Banner for a page temporarily move-protected due to page-move vandalism:
{{pp|vandalism|action=move}}
== Visibility ==
This template will hide itself (not display a padlock icon) if it is used on a page that is not currently protected. [[User:MusikBot II]] may also automatically remove the template wikicode from pages that are not currently protected.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "Produces banners to describe why a page is protected and padlock icons",
"params": {
"1": {
"label": "Reason",
"description": "Reason for protection, may be one of: blp, dispute, dmca, mainpage, office, reset, sock, template, usertalk, vandalism",
"type": "string",
"suggestedvalues": [
"vandalism",
"template",
"usertalk",
"blp",
"dispute",
"dmca",
"ecp",
"mainpage",
"reset",
"sock",
"office"
],
"suggested": true
},
"small": {
"description": "Specifies whether only a padlock is generated. If set to \"yes\", \"y\", \"1\", or \"true\", a padlock icon is generated instead of a full protection banner.",
"example": "1",
"type": "boolean",
"default": "0",
"suggested": true,
"label": "Small?"
},
"action": {
"description": "Action which is restricted. Must be one of \"edit\" (for normal protection), \"move\" (for move-protection) or \"autoreview\" (for pending changes).",
"example": "move",
"type": "string",
"default": "edit",
"label": "Restricted action",
"suggestedvalues": [
"edit",
"move",
"autoreview"
],
"suggested": true
},
"date": {
"description": "Protection date. This must be valid input to the second parameter of the #time parser function. This argument only has an effect for the \"office\" and \"reset\" reasons.",
"type": "date",
"label": "Date protected",
"example": "yyyy-mm-dd"
},
"user": {
"description": "Username of the user to generate links for. This only has an effect when the \"usertalk\" reason is specified.",
"type": "wiki-user-name",
"label": "Username"
},
"section": {
"description": "Section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of reason.",
"type": "string",
"label": "Section name of talk"
},
"category": {
"description": "Categories are suppressed if this is set to \"no\", \"n\", \"0\", or \"false\".",
"type": "boolean",
"label": "Categorize?",
"example": "0",
"default": "1"
}
},
"paramOrder": [
"1",
"small",
"action",
"date",
"user",
"section",
"category"
]
}
</templatedata>
== See also ==
{{Protection templates}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Protection templates]]
[[Category:Templates that add a tracking category]]
}}</includeonly>
9d5jrfo3t8rozr4pxocj05e578g7wxa
9214
9211
2026-08-23T03:32:31Z
RAPTOR7762
18
9214
wikitext
text/x-wiki
{{Documentation subpage}}
<!--Categories where indicated at the bottom of this page, please; interwikis at Wikidata (see [[Wikipedia:Wikidata]])-->
<includeonly>{{pp-protected|small=yes}}</includeonly>
{{High-use}}
{{User:MusikBot II/Config notice}}
{{tsh|pp}}
{{lua|Module:Protection banner}}
This is a general template for producing '''p'''rotection banners and '''p'''adlock icons. It can be used with any protection reason, any protection action, and any protection level.
== Usage ==
{{pp
| 1 = ''reason''
| small = ''yes''
| action = ''action''
| date = ''protection date''
| user = ''username''
| section = ''talk page section name''
| category = ''no''
}}
== Parameters ==
All parameters are optional:
* {{para|1}} – The reason that the page was protected. If set, this must be one of the values listed in the [[#Reasons|reasons table]].
* {{para|small}} – If set to {{pval|yes}}, {{pval|y}}, {{pval|1}}, or {{pval|true}}, a padlock icon is generated instead of a full protection banner.
* {{para|action}} – The protection action. Must be one of {{pval|edit}} (for normal protection), {{pval|move}} (for move-protection) or {{pval|autoreview}} (for pending changes). The default value is {{pval|edit}}.
* {{para|date}} – The protection date. This must be valid input to the second parameter of the [[mw:Help:Extension:ParserFunctions##time|#time parser function]]. This argument only has an effect for the {{pval|office}} and {{pval|reset}} reasons.
* {{para|user}} – The username of the user to generate links for. As of July 2014, this only has an effect when the {{pval|usertalk}} reason is specified.
* {{para|section}} – The section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of ''reason''.
* {{para|category}} – Categories are suppressed if this is set to {{pval|no}}, {{pval|n}}, {{pval|0}}, or {{pval|false}}.
== Reasons ==
The following table contains the available reasons, plus the actions for which they are available. Reasons are used to customize the banner text, to place articles in more specific hidden categories such as [[:Category:Wikipedia pages semi-protected against vandalism]], and sometimes to change the icon of the banner (e.g. office actions).
{{#invoke:Protection banner/documentation|reasonTable}}
== Syntax examples ==
'''Padlock icons'''
Padlock icon for a page protected due to vandalism:
{{pp|vandalism|small=yes}}
Padlock icon for a page temporarily protected due to editing disputes:
{{pp|dispute|small=yes}}
'''Banners'''
Banner for a page protected due to sockpuppetry, with a link to a talk page discussion:
{{pp|sock|section=Sockpuppetry concerns}}
Banner for a page temporarily move-protected due to page-move vandalism:
{{pp|vandalism|action=move}}
== Visibility ==
This template will hide itself (not display a padlock icon) if it is used on a page that is not currently protected. [[User:MusikBot II]] may also automatically remove the template wikicode from pages that are not currently protected.
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "Produces banners to describe why a page is protected and padlock icons",
"params": {
"1": {
"label": "Reason",
"description": "Reason for protection, may be one of: blp, dispute, dmca, mainpage, office, reset, sock, template, usertalk, vandalism",
"type": "string",
"suggestedvalues": [
"vandalism",
"template",
"usertalk",
"blp",
"dispute",
"dmca",
"ecp",
"mainpage",
"reset",
"sock",
"office"
],
"suggested": true
},
"small": {
"description": "Specifies whether only a padlock is generated. If set to \"yes\", \"y\", \"1\", or \"true\", a padlock icon is generated instead of a full protection banner.",
"example": "1",
"type": "boolean",
"default": "0",
"suggested": true,
"label": "Small?"
},
"action": {
"description": "Action which is restricted. Must be one of \"edit\" (for normal protection), \"move\" (for move-protection) or \"autoreview\" (for pending changes).",
"example": "move",
"type": "string",
"default": "edit",
"label": "Restricted action",
"suggestedvalues": [
"edit",
"move",
"autoreview"
],
"suggested": true
},
"date": {
"description": "Protection date. This must be valid input to the second parameter of the #time parser function. This argument only has an effect for the \"office\" and \"reset\" reasons.",
"type": "date",
"label": "Date protected",
"example": "yyyy-mm-dd"
},
"user": {
"description": "Username of the user to generate links for. This only has an effect when the \"usertalk\" reason is specified.",
"type": "wiki-user-name",
"label": "Username"
},
"section": {
"description": "Section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of reason.",
"type": "string",
"label": "Section name of talk"
},
"category": {
"description": "Categories are suppressed if this is set to \"no\", \"n\", \"0\", or \"false\".",
"type": "boolean",
"label": "Categorize?",
"example": "0",
"default": "1"
}
},
"paramOrder": [
"1",
"small",
"action",
"date",
"user",
"section",
"category"
]
}
</templatedata>
== See also ==
{{Protection templates}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Protection templates]]
[[Category:Templates that add a tracking category]]
}}</includeonly>
cxzd9o35ih5wz1wty02izr6gssju159
Ruta:MusikBot II/Config notice
2
1082
9129
2025-12-08T07:47:33Z
en>Pppery
0
Protected "[[User:MusikBot II/Config notice]]" ([Edit=Require autoconfirmed or confirmed access] (indefinite) [Move=Require autoconfirmed or confirmed access] (indefinite))
9129
wikitext
text/x-wiki
{{Mbox
| image = [[File:Crystal Clear action run.svg|50px|alt=Bot logo]]
| text = If this template is '''moved''', '''redirected''' or '''deleted''', please ask an administrator to update [[User:MusikBot II/{{{task|FixPP}}}/config]] accordingly. Thank you.{{#if:{{{1|}}}|<br>
{{{1}}}}}}}<noinclude>
{{Documentation}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
cy3nd15sgyw9rbc2ftnofyw3b1crlce
9130
9129
2026-08-22T14:37:11Z
RAPTOR7762
18
1 revision imported from [[:en:User:MusikBot_II/Config_notice]]
9129
wikitext
text/x-wiki
{{Mbox
| image = [[File:Crystal Clear action run.svg|50px|alt=Bot logo]]
| text = If this template is '''moved''', '''redirected''' or '''deleted''', please ask an administrator to update [[User:MusikBot II/{{{task|FixPP}}}/config]] accordingly. Thank you.{{#if:{{{1|}}}|<br>
{{{1}}}}}}}<noinclude>
{{Documentation}}<!-- Add categories and interwikis to the /doc subpage, not here! --></noinclude>
cy3nd15sgyw9rbc2ftnofyw3b1crlce
Tempilet:Param value/styles.css
10
1083
9131
2025-12-11T19:07:18Z
en>Pppery
0
/* {{pp-template}} */
9131
sanitized-css
text/css
/* {{pp-template}} */
.tpl-pval__code {
border: thin solid var(--border-color-base, #a2a9b1);
background-color: var(--color-inverted, #fff);
color: inherit;
white-space: nowrap;
}
fqg9qh88nnemm62ynyo3np3cozsa2f2
9132
9131
2026-08-22T14:37:11Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Param_value/styles.css]]
9131
sanitized-css
text/css
/* {{pp-template}} */
.tpl-pval__code {
border: thin solid var(--border-color-base, #a2a9b1);
background-color: var(--color-inverted, #fff);
color: inherit;
white-space: nowrap;
}
fqg9qh88nnemm62ynyo3np3cozsa2f2
Module:Submit an edit request
828
1084
9160
2024-12-16T15:29:26Z
en>HouseBlaster
0
bypass redirect
9160
Scribunto
text/plain
-- This module implements {{Submit an edit request}}.
local CONFIG_MODULE = 'Module:Submit an edit request/config'
-- Load necessary modules
local mRedirect = require('Module:Redirect')
local cfg = mw.loadData(CONFIG_MODULE)
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local escape = require("Module:String")._escapePattern
local lang = mw.language.getContentLanguage()
local p = {}
local validLevels = {
semi = 'semi',
extended = 'extended',
template = 'template',
full = 'full',
interface = 'interface',
manual = 'manual'
}
local function message(key, ...)
local params = {...}
local msg = cfg[key]
if #params < 1 then
return msg
else
return mw.message.newRawMessage(msg):params(params):plain()
end
end
local function validateLevel(level)
return level and validLevels[level] or 'full'
end
local function getLevelInfo(level, field)
return cfg.protectionLevels[level][field]
end
local function resolveRedirect(page)
return mRedirect.luaMain(page)
end
local function isProtected(page)
local action = mw.title.new(page).exists and 'edit' or 'create'
return effectiveProtectionLevel(action, page) ~= '*'
end
function p.makeRequestUrl(level, titleObj)
titleObj = titleObj or mw.title.getCurrentTitle()
local basePage = titleObj.basePageTitle.fullText
if cfg['main-page-content'][basePage] then
return tostring(mw.uri.fullUrl(message('main-page-request-page')))
end
local talkPageName = titleObj.talkPageTitle
if talkPageName == nil then
return tostring(mw.uri.fullUrl(message('protected-talk-page-request-page')))
end
talkPageName = resolveRedirect(talkPageName.prefixedText)
if isProtected(talkPageName) then
return tostring(mw.uri.fullUrl(message('protected-talk-page-request-page')))
end
level = validateLevel(level)
if level == 'manual' then
return tostring(mw.uri.fullUrl(talkPageName, {
action = 'edit',
section = 'new'
}))
end
local sectionname = message(
'preload-title-text',
getLevelInfo(level, 'levelText'),
lang:formatDate(message('preload-title-date-format'))
)
local content = mw.title.new(talkPageName):getContent()
if content and content:find("== *" .. escape(sectionname) .. " *==") then
local dedup = 2
while true do
local newname = message("preload-title-dedup-suffix", sectionname, dedup)
if not content:find("== *" .. escape(newname) .. " *==") then
sectionname = newname
break
end
dedup = dedup + 1
end
end
local url = mw.uri.fullUrl(talkPageName, {
action = 'edit',
editintro = getLevelInfo(level, 'editintro'),
preload = message('preload-template'),
preloadtitle = sectionname,
section = 'new'
})
url = tostring(url)
-- Add the preload parameters. @TODO: merge this into the mw.uri.fullUrl
-- query table once [[phab:T93059]] is fixed.
local function encodeParam(key, val)
return string.format('&%s=%s', mw.uri.encode(key), mw.uri.encode(val))
end
url = url .. encodeParam('preloadparams[]', getLevelInfo(level, 'requestTemplate'))
url = url .. encodeParam('preloadparams[]', titleObj.prefixedText)
return url
end
function p._link(args)
return string.format(
'<span class="plainlinks">[%s %s]</span>',
p.makeRequestUrl(args.type),
args.display or message('default-display-value')
)
end
function p._button(args)
return require('Module:Clickable button').main{
[1] = args.display or message('default-display-value'),
url = p.makeRequestUrl(args.type),
class = 'mw-ui-progressive'
}
end
local function makeInvokeFunc(func, wrapper)
return function (frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = {wrapper}
})
return func(args)
end
end
p.link = makeInvokeFunc(p._link, message('link-wrapper-template'))
p.button = makeInvokeFunc(p._button, message('button-wrapper-template'))
return p
nk1nb7zr3yxhcpwmhyp0oewkuy26v66
9161
9160
2026-08-23T01:43:24Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Submit_an_edit_request]]
9160
Scribunto
text/plain
-- This module implements {{Submit an edit request}}.
local CONFIG_MODULE = 'Module:Submit an edit request/config'
-- Load necessary modules
local mRedirect = require('Module:Redirect')
local cfg = mw.loadData(CONFIG_MODULE)
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local escape = require("Module:String")._escapePattern
local lang = mw.language.getContentLanguage()
local p = {}
local validLevels = {
semi = 'semi',
extended = 'extended',
template = 'template',
full = 'full',
interface = 'interface',
manual = 'manual'
}
local function message(key, ...)
local params = {...}
local msg = cfg[key]
if #params < 1 then
return msg
else
return mw.message.newRawMessage(msg):params(params):plain()
end
end
local function validateLevel(level)
return level and validLevels[level] or 'full'
end
local function getLevelInfo(level, field)
return cfg.protectionLevels[level][field]
end
local function resolveRedirect(page)
return mRedirect.luaMain(page)
end
local function isProtected(page)
local action = mw.title.new(page).exists and 'edit' or 'create'
return effectiveProtectionLevel(action, page) ~= '*'
end
function p.makeRequestUrl(level, titleObj)
titleObj = titleObj or mw.title.getCurrentTitle()
local basePage = titleObj.basePageTitle.fullText
if cfg['main-page-content'][basePage] then
return tostring(mw.uri.fullUrl(message('main-page-request-page')))
end
local talkPageName = titleObj.talkPageTitle
if talkPageName == nil then
return tostring(mw.uri.fullUrl(message('protected-talk-page-request-page')))
end
talkPageName = resolveRedirect(talkPageName.prefixedText)
if isProtected(talkPageName) then
return tostring(mw.uri.fullUrl(message('protected-talk-page-request-page')))
end
level = validateLevel(level)
if level == 'manual' then
return tostring(mw.uri.fullUrl(talkPageName, {
action = 'edit',
section = 'new'
}))
end
local sectionname = message(
'preload-title-text',
getLevelInfo(level, 'levelText'),
lang:formatDate(message('preload-title-date-format'))
)
local content = mw.title.new(talkPageName):getContent()
if content and content:find("== *" .. escape(sectionname) .. " *==") then
local dedup = 2
while true do
local newname = message("preload-title-dedup-suffix", sectionname, dedup)
if not content:find("== *" .. escape(newname) .. " *==") then
sectionname = newname
break
end
dedup = dedup + 1
end
end
local url = mw.uri.fullUrl(talkPageName, {
action = 'edit',
editintro = getLevelInfo(level, 'editintro'),
preload = message('preload-template'),
preloadtitle = sectionname,
section = 'new'
})
url = tostring(url)
-- Add the preload parameters. @TODO: merge this into the mw.uri.fullUrl
-- query table once [[phab:T93059]] is fixed.
local function encodeParam(key, val)
return string.format('&%s=%s', mw.uri.encode(key), mw.uri.encode(val))
end
url = url .. encodeParam('preloadparams[]', getLevelInfo(level, 'requestTemplate'))
url = url .. encodeParam('preloadparams[]', titleObj.prefixedText)
return url
end
function p._link(args)
return string.format(
'<span class="plainlinks">[%s %s]</span>',
p.makeRequestUrl(args.type),
args.display or message('default-display-value')
)
end
function p._button(args)
return require('Module:Clickable button').main{
[1] = args.display or message('default-display-value'),
url = p.makeRequestUrl(args.type),
class = 'mw-ui-progressive'
}
end
local function makeInvokeFunc(func, wrapper)
return function (frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = {wrapper}
})
return func(args)
end
end
p.link = makeInvokeFunc(p._link, message('link-wrapper-template'))
p.button = makeInvokeFunc(p._button, message('button-wrapper-template'))
return p
nk1nb7zr3yxhcpwmhyp0oewkuy26v66
Module:Submit an edit request/config
828
1085
9162
2026-01-11T00:43:40Z
en>Pppery
0
Bypass rdr
9162
Scribunto
text/plain
-- This module contains configuration data for [[Module:Submit an edit request]].
return {
--------------------------------------------------------------------------------
-- Messages
--------------------------------------------------------------------------------
-- The default display value for edit requests.
['default-display-value'] = 'Submit an edit request',
-- The template that stores the edit request preload text
['preload-template'] = 'Template:Submit an edit request/preload',
-- The section heading that is generated when a user clicks on an edit request
-- link. $1 is the protection level text, e.g. "Semi-protected" or
-- "Template-protected". $2 is the current date, in the format specified by the
-- "preload-title-date-format" message.
['preload-title-text'] = '$1 edit request on $2',
-- The date format for the automatically-generated section heading. The format
-- must be valid input for the #time parser function.
['preload-title-date-format'] = 'j F Y',
-- What do do with the generated section header if another header with the same section already exists
-- $1 is the original section header. $2 is an automatically generated number, starting at 2 and increasing
-- by one until a unique header is found.
['preload-title-dedup-suffix'] = '$1 ($2)',
-- The names of pages (and their subpages) that make up the content of the main page for this wiki
['main-page-content'] = {
['Wikipedia:Today\'s featured article'] = true,
['Template:In the news'] = true,
['Template:Did you know'] = true,
['Wikipedia:Selected anniversaries'] = true,
['Template:POTD protected'] = true,
['Wikipedia:Today\'s featured list'] = true
},
-- The page used to request changes to things on the Main Page.
['main-page-request-page'] = 'Wikipedia:Main Page/Errors',
-- The page used to request edits to protected talk pages.
['protected-talk-page-request-page'] = 'Wikipedia:Requests for page protection/Edit',
-- The names of the templates to be used as wrappers for the "link" and "button"
-- functions. These are passed as arguments to the "wrappers" option of
-- [[Module:Arguments]].
['link-wrapper-template'] = 'Template:Submit an edit request/link',
['button-wrapper-template'] = 'Template:Submit an edit request',
--------------------------------------------------------------------------------
-- Protection level config
--------------------------------------------------------------------------------
protectionLevels = {
--[[
-- These settings are for the different protection levels which the module can
-- output edit request links for.
--
-- editintro:
-- The template to use as the edit intro users see when they click on an edit
-- request link.
--
-- request-template:
-- The name of the edit request template for that protection level. Do not
-- include the "Template:" text.
--
-- protectionlevel:
-- The name of the protection level, used for formatting the automatically-
-- generated section headings.
--]]
-- Semi-protection
semi = {
editintro = 'Template:Edit semi-protected/editintro',
requestTemplate = 'edit semi-protected',
levelText = 'Semi-protected',
},
-- Extended-confirmed-protection
extended = {
editintro = 'Template:Edit extended-protected/editintro',
requestTemplate = 'edit extended-protected',
levelText = 'Extended-confirmed-protected',
},
-- Template-protection
template = {
editintro = 'Template:Edit template-protected/editintro',
requestTemplate = 'edit template-protected',
levelText = 'Template-protected',
},
-- Full protection
full = {
editintro = 'Template:Edit fully-protected/editintro',
requestTemplate = 'edit fully-protected',
levelText = 'Protected',
},
-- Interface-protection
interface = {
editintro = 'Template:Edit interface-protected/editintro',
requestTemplate = 'edit interface-protected',
levelText = 'Interface-protected',
},
}
}
pt4ho7slt5fo4w5xg1pn6u5vzde87r1
9163
9162
2026-08-23T01:43:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Submit_an_edit_request/config]]
9162
Scribunto
text/plain
-- This module contains configuration data for [[Module:Submit an edit request]].
return {
--------------------------------------------------------------------------------
-- Messages
--------------------------------------------------------------------------------
-- The default display value for edit requests.
['default-display-value'] = 'Submit an edit request',
-- The template that stores the edit request preload text
['preload-template'] = 'Template:Submit an edit request/preload',
-- The section heading that is generated when a user clicks on an edit request
-- link. $1 is the protection level text, e.g. "Semi-protected" or
-- "Template-protected". $2 is the current date, in the format specified by the
-- "preload-title-date-format" message.
['preload-title-text'] = '$1 edit request on $2',
-- The date format for the automatically-generated section heading. The format
-- must be valid input for the #time parser function.
['preload-title-date-format'] = 'j F Y',
-- What do do with the generated section header if another header with the same section already exists
-- $1 is the original section header. $2 is an automatically generated number, starting at 2 and increasing
-- by one until a unique header is found.
['preload-title-dedup-suffix'] = '$1 ($2)',
-- The names of pages (and their subpages) that make up the content of the main page for this wiki
['main-page-content'] = {
['Wikipedia:Today\'s featured article'] = true,
['Template:In the news'] = true,
['Template:Did you know'] = true,
['Wikipedia:Selected anniversaries'] = true,
['Template:POTD protected'] = true,
['Wikipedia:Today\'s featured list'] = true
},
-- The page used to request changes to things on the Main Page.
['main-page-request-page'] = 'Wikipedia:Main Page/Errors',
-- The page used to request edits to protected talk pages.
['protected-talk-page-request-page'] = 'Wikipedia:Requests for page protection/Edit',
-- The names of the templates to be used as wrappers for the "link" and "button"
-- functions. These are passed as arguments to the "wrappers" option of
-- [[Module:Arguments]].
['link-wrapper-template'] = 'Template:Submit an edit request/link',
['button-wrapper-template'] = 'Template:Submit an edit request',
--------------------------------------------------------------------------------
-- Protection level config
--------------------------------------------------------------------------------
protectionLevels = {
--[[
-- These settings are for the different protection levels which the module can
-- output edit request links for.
--
-- editintro:
-- The template to use as the edit intro users see when they click on an edit
-- request link.
--
-- request-template:
-- The name of the edit request template for that protection level. Do not
-- include the "Template:" text.
--
-- protectionlevel:
-- The name of the protection level, used for formatting the automatically-
-- generated section headings.
--]]
-- Semi-protection
semi = {
editintro = 'Template:Edit semi-protected/editintro',
requestTemplate = 'edit semi-protected',
levelText = 'Semi-protected',
},
-- Extended-confirmed-protection
extended = {
editintro = 'Template:Edit extended-protected/editintro',
requestTemplate = 'edit extended-protected',
levelText = 'Extended-confirmed-protected',
},
-- Template-protection
template = {
editintro = 'Template:Edit template-protected/editintro',
requestTemplate = 'edit template-protected',
levelText = 'Template-protected',
},
-- Full protection
full = {
editintro = 'Template:Edit fully-protected/editintro',
requestTemplate = 'edit fully-protected',
levelText = 'Protected',
},
-- Interface-protection
interface = {
editintro = 'Template:Edit interface-protected/editintro',
requestTemplate = 'edit interface-protected',
levelText = 'Interface-protected',
},
}
}
pt4ho7slt5fo4w5xg1pn6u5vzde87r1
Module:Transclusion count/data/S
828
1086
9164
2026-08-16T05:09:50Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9164
Scribunto
text/plain
return {
["S"] = 4300,
["S-aca"] = 6700,
["S-ach"] = 17000,
["S-aft"] = 230000,
["S-aft/check"] = 230000,
["S-aft/filter"] = 230000,
["S-bef"] = 235000,
["S-bef/check"] = 235000,
["S-bef/filter"] = 235000,
["S-break"] = 6500,
["S-bus"] = 2100,
["S-civ"] = 2900,
["S-dip"] = 6000,
["S-end"] = 262000,
["S-gov"] = 8600,
["S-hon"] = 4000,
["S-hou"] = 9800,
["S-inc"] = 13000,
["S-legal"] = 9900,
["S-line_label"] = 2000,
["S-mil"] = 13000,
["S-new"] = 17000,
["S-non"] = 11000,
["S-npo"] = 4200,
["S-off"] = 43000,
["S-par"] = 52000,
["S-par/en"] = 3300,
["S-par/gb"] = 3300,
["S-par/uk"] = 12000,
["S-par/us-hs"] = 12000,
["S-par/us-sen"] = 2100,
["S-ppo"] = 15000,
["S-prec"] = 3200,
["S-reg"] = 22000,
["S-rel"] = 19000,
["S-roy"] = 2800,
["S-sports"] = 12000,
["S-start"] = 253000,
["S-ttl"] = 242000,
["S-ttl/check"] = 242000,
["S-vac"] = 7800,
["SAU"] = 2100,
["SCO"] = 3800,
["SDcat"] = 6800000,
["SECOND"] = 2300,
["SGP"] = 2900,
["SIA"] = 2500,
["SLL"] = 2000,
["SLO"] = 4900,
["SMS"] = 6800,
["SMU"] = 2500,
["SPI_archive_notice"] = 85000,
["SPIarchive_notice"] = 82000,
["SPIcat"] = 3800,
["SPIclose"] = 3300,
["SPIpriorcases"] = 78000,
["SR/Olympics_profile"] = 2200,
["SRB"] = 4300,
["SS"] = 22000,
["SSPa"] = 2600,
["STN"] = 11000,
["SUBJECTSPACE_formatted"] = 44000,
["SUI"] = 9600,
["SVG"] = 2700,
["SVG-Logo"] = 26000,
["SVG-Res"] = 24000,
["SVG-logo"] = 14000,
["SVK"] = 8700,
["SVN"] = 5800,
["SWE"] = 13000,
["Salts_by_element"] = 2200,
["Sandbox_other"] = 467000,
["Saturday"] = 2800,
["Saved_book"] = 52000,
["Sc"] = 2900,
["Scholia"] = 3700,
["School_block"] = 13000,
["School_disambiguation"] = 3500,
["Schoolblock"] = 6900,
["Schooldis"] = 2700,
["Schoolip"] = 12000,
["Scientist_icon"] = 16000,
["Scientist_icon2"] = 16000,
["Sclass"] = 34000,
["Sclass2"] = 11000,
["Screen_reader-only"] = 108000,
["Screen_reader-only/styles.css"] = 148000,
["Script"] = 7600,
["Script/Arabic"] = 4000,
["Script/Hebrew"] = 4900,
["Script/Nastaliq"] = 15000,
["Script/doc/id-unk"] = 3200,
["Script/doc/id-unk/core"] = 3200,
["Script/doc/id-unk/is-iso-alpha4"] = 3200,
["Script/doc/id-unk/name-to-alpha4"] = 3200,
["Script/styles.css"] = 3400,
["Script/styles_arabic.css"] = 4000,
["Script/styles_hebrew.css"] = 4900,
["Sdash"] = 4000,
["Search_box"] = 73000,
["Search_link"] = 26000,
["Section_link"] = 165000,
["Section_sizes"] = 4300,
["See"] = 8900,
["See_also"] = 217000,
["Seealso"] = 7900,
["Seiner_Majestät_Schiff"] = 6800,
["Seiner_Majestät_Unterseeboot"] = 2500,
["Select_skin"] = 5500,
["Selected"] = 2000,
["Selected_article"] = 2500,
["Selected_picture"] = 2400,
["Self"] = 45000,
["Self-published_inline"] = 4700,
["Self-published_source"] = 6100,
["Self-reference"] = 2200,
["Self-reference_tool"] = 8200,
["Sent_off"] = 17000,
["Sentoff"] = 6200,
["Sequence"] = 4100,
["Series_overview"] = 9900,
["Serif"] = 5000,
["Set_category"] = 38000,
["Set_index_article"] = 6300,
["Sets_taxobox_colour"] = 3400,
["Sfn"] = 209000,
["SfnRef"] = 164000,
["Sfn_whitelist"] = 2600,
["Sfnm"] = 5900,
["Sfnp"] = 24000,
["Sfnref"] = 18000,
["Sfrac"] = 5100,
["Sfrac/styles.css"] = 5200,
["SharedIPEDU"] = 3300,
["Shared_IP"] = 10000,
["Shared_IP_corp"] = 4100,
["Shared_IP_edu"] = 186000,
["Shared_IP_gov"] = 2300,
["Sharedip"] = 3000,
["Sharedipedu"] = 3800,
["Sherdog"] = 2700,
["Ship"] = 42000,
["Ship_index"] = 7600,
["Shipboxflag"] = 21000,
["Shipboxflag/core"] = 21000,
["Shipwrecks_navbox_footer"] = 11000,
["Shipwrecks_navbox_footer/link"] = 11000,
["Short_description"] = 6940000,
["Short_description/lowercasecheck"] = 6940000,
["Short_pages_monitor"] = 16000,
["Short_pages_monitor/maximum_length"] = 16000,
["Shortcut"] = 22000,
["Should_be_SVG"] = 8200,
["Shy"] = 2200,
["Sic"] = 39000,
["Side_box"] = 1250000,
["Sidebar"] = 320000,
["Sidebar_games_events"] = 42000,
["Sidebar_person"] = 4900,
["Sidebar_person/styles.css"] = 6300,
["Sidebar_with_collapsible_lists"] = 84000,
["Sigfig"] = 4100,
["Significant_figures"] = 5600,
["Significant_figures/rnd"] = 5300,
["Signpost-subscription"] = 2100,
["Signpost-subscription/styles.css"] = 2100,
["Signpost/item"] = 49000,
["Signpost/item/core"] = 49000,
["Signpost/snippet-nopic"] = 3400,
["Signpost/snippet/styles.css"] = 3700,
["Sildb_prim"] = 2200,
["Silver02"] = 18000,
["Silver2"] = 46000,
["Silver_medal"] = 6700,
["Silver_medal_icon"] = 59000,
["Similar_names"] = 3400,
["Single+double"] = 11000,
["Single+space"] = 17000,
["Single-innings_cricket_match"] = 4000,
["Single_chart"] = 43000,
["Single_namespace"] = 337000,
["Single_source"] = 3000,
["Singlechart"] = 12000,
["Singles"] = 49000,
["Sister-inline"] = 223000,
["Sister-inline/styles.css"] = 223000,
["Sister_project"] = 1120000,
["Sister_project/styles.css"] = 1120000,
["Sister_project_links"] = 14000,
["Skip_to_talk"] = 12000,
["Skip_to_talk/styles.css"] = 12000,
["Sky"] = 3300,
["Sky/styles.css"] = 3300,
["Slink"] = 66000,
["Slovak_municipality"] = 3000,
["Slovak_municipality/geo"] = 2800,
["Small"] = 650000,
["Small_Solar_System_bodies"] = 3600,
["Smallcaps"] = 21000,
["Smallcaps/styles.css"] = 22000,
["Smalldiv"] = 43000,
["Smaller"] = 79000,
["Smiley"] = 53000,
["Snd"] = 612000,
["Snds"] = 6500,
["Soccer_icon"] = 124000,
["Soccer_icon2"] = 124000,
["Soccer_icon4"] = 3500,
["Soccerbase"] = 13000,
["Soccerbase_season"] = 8000,
["Soccerway"] = 83000,
["Sock"] = 55000,
["Sock_list"] = 11000,
["Sockcat"] = 2000,
["Sockmaster"] = 10000,
["Sockpuppet"] = 285000,
["Sockpuppet/altmaster"] = 3700,
["Sockpuppet/categorise"] = 285000,
["SockpuppetCheckuser"] = 5500,
["Sockpuppet_category"] = 52000,
["Sockpuppet_category/confirmed"] = 28000,
["Sockpuppet_category/suspected"] = 24000,
["Sockpuppetcheckuser"] = 3600,
["Sockpuppeteer"] = 29000,
["Soft_hyphen"] = 2300,
["Soft_redirect"] = 6500,
["Soft_redirect_protection"] = 10000,
["Softredirect"] = 3300,
["Solar_luminosity"] = 5200,
["Solar_mass"] = 6400,
["Solar_radius"] = 5200,
["Soldier_icon"] = 3900,
["Soldier_icon2"] = 3900,
["Songs_category"] = 9600,
["Songs_category/core"] = 9600,
["Sort"] = 122000,
["Sort_under"] = 2200,
["Sort_under/styles.css"] = 2200,
["Sortname"] = 64000,
["Source-attribution"] = 9100,
["Source_assess"] = 2700,
["Source_assess_table"] = 2700,
["Source_attribution"] = 39000,
["Source_check"] = 927000,
["Sourcecheck"] = 927000,
["Sources"] = 3600,
["Sources_exist"] = 4200,
["South_America_topic"] = 2700,
["Sp"] = 164000,
["Space"] = 130000,
["Space+apostrophe+s"] = 26000,
["Space+double"] = 7200,
["Space+single"] = 15000,
["Spaced_en_dash"] = 645000,
["Spaced_en_dash_space"] = 6600,
["Spaced_ndash"] = 22000,
["Spaces"] = 734000,
["Spain_metadata_Wikidata"] = 7400,
["Spamlink"] = 14000,
["Species_Latin_name_abbreviation_disambiguation"] = 2400,
["Species_list"] = 25000,
["Speciesbox"] = 393000,
["Speciesbox/checkgenus"] = 391000,
["Speciesbox/getGenus"] = 394000,
["Speciesbox/getSpecies"] = 393000,
["Speciesbox/name"] = 393000,
["Speciesbox/parameterCheck"] = 393000,
["Speciesbox/trim"] = 393000,
["Specieslist"] = 9300,
["Split_article"] = 4200,
["Spnd"] = 4700,
["Spoken_Wikipedia"] = 2200,
["Sport_icon"] = 16000,
["Sport_icon2"] = 17000,
["SportsYearCatUSstate"] = 6700,
["Sports_club_or_team_people_category_header"] = 14000,
["Sports_club_or_team_people_category_header/category1"] = 14000,
["Sports_links"] = 81000,
["Sports_reference"] = 5100,
["Squad_maintenance"] = 3800,
["Sronly"] = 49000,
["Srt"] = 7200,
["Stack"] = 30000,
["Stack/styles.css"] = 41000,
["Stack_begin"] = 11000,
["Stack_end"] = 11000,
["StaleIP"] = 3600,
["StandardEbooks"] = 2400,
["Standings_table_end"] = 64000,
["Standings_table_entry"] = 25000,
["Standings_table_entry/record"] = 64000,
["Standings_table_start"] = 64000,
["Standings_table_start/colheader"] = 64000,
["Standings_table_start/colspan"] = 64000,
["Standings_table_start/styles.css"] = 64000,
["Starbox_astrometry"] = 5700,
["Starbox_begin"] = 5800,
["Starbox_catalog"] = 5700,
["Starbox_character"] = 5700,
["Starbox_detail"] = 5600,
["Starbox_end"] = 5800,
["Starbox_image"] = 4000,
["Starbox_observe"] = 5800,
["Starbox_reference"] = 5700,
["Start-Class"] = 18000,
["Start-date"] = 2300,
["Start_and_end_dates"] = 3700,
["Start_box"] = 5600,
["Start_date"] = 547000,
["Start_date_and_age"] = 187000,
["Start_date_and_years_ago"] = 4000,
["Start_date_text"] = 3900,
["Start_of_course_timeline"] = 5800,
["Start_of_course_week"] = 6000,
["Start_tab"] = 6700,
["Startflatlist"] = 162000,
["Startplainlist"] = 2200,
["Static_IP"] = 5000,
["Static_row_numbers"] = 2900,
["Static_row_numbers/styles.css"] = 2900,
["Station"] = 22000,
["Station_link"] = 19000,
["Stdinchicite"] = 10000,
["Steady"] = 19000,
["Sticky_header"] = 9500,
["Sticky_header/styles.css"] = 26000,
["Stl"] = 17000,
["Stn"] = 11000,
["Stn_art_lnk"] = 2200,
["Stnlnk"] = 35000,
["Stop"] = 2000,
["Store_norske_leksikon"] = 2400,
["Storm_colour"] = 5800,
["Storm_name"] = 2400,
["Storm_path"] = 2200,
["Stortingetbio"] = 2100,
["StoryTeleplay"] = 3400,
["Str_count"] = 166000,
["Str_endswith"] = 236000,
["Str_find"] = 283000,
["Str_index"] = 15000,
["Str_left"] = 348000,
["Str_len"] = 167000,
["Str_letter"] = 184000,
["Str_letter/trim"] = 21000,
["Str_number"] = 7200,
["Str_number/trim"] = 225000,
["Str_rep"] = 298000,
["Str_right"] = 7100,
["Str_startswith"] = 2800,
["Str_trim"] = 4200,
["Str_≠_len"] = 48000,
["Str_≤_len"] = 2900,
["Str_≥_len"] = 104000,
["Strfind_short"] = 5300,
["Strike"] = 2300,
["Strikethrough"] = 20000,
["String_split"] = 5300,
["Strip_tags"] = 41000,
["Strong"] = 212000,
["Structurae"] = 2100,
["Stub-Class"] = 18000,
["Stub_Category"] = 14000,
["Stub_category"] = 21000,
["Stub_documentation"] = 42000,
["Student_editor"] = 27000,
["Student_sandbox"] = 4400,
["Student_table_row"] = 7000,
["Students_table"] = 7000,
["Su"] = 4800,
["Su-census1989"] = 4600,
["Sub"] = 4500,
["Subinfobox_bodystyle"] = 75000,
["Subject_bar"] = 20000,
["Suboff"] = 7400,
["Subon"] = 7600,
["Subpage_other"] = 408000,
["Subscription_required"] = 36000,
["Subsidebar_bodystyle"] = 6200,
["Subst_only"] = 5500,
["Substituted_comment"] = 19000,
["Succession_box"] = 119000,
["Succession_box/check"] = 119000,
["Succession_links"] = 217000,
["Summer_Olympics_by_year_category_navigation"] = 2500,
["Summer_Olympics_by_year_category_navigation/core"] = 2500,
["Sunday"] = 2800,
["Sup"] = 95000,
["Suppress_categories"] = 6600,
["Surname"] = 80000,
["Swiss_metadata_Wikidata"] = 2900,
["Swiss_populations"] = 2400,
["Swiss_populations_NC"] = 3000,
["Swiss_populations_YM"] = 2300,
["Swiss_populations_ref"] = 2400,
["Switcher"] = 8400,
["Sz"] = 2500,
["Module:SDcat"] = 6800000,
["Module:SPI_archive_notice"] = 39000,
["Module:SST"] = 13000,
["Module:SST/hosts"] = 13000,
["Module:SST/registry"] = 274000,
["Module:SST/shards/sets/COLLEDGE_SHIPS_RN"] = 3000,
["Module:SST/shards/sets/TALBERT_BARRINGTON_ATLAS"] = 2100,
["Module:Science_redirect"] = 322000,
["Module:Science_redirect/conf"] = 322000,
["Module:Section_link"] = 165000,
["Module:Section_sizes"] = 5900,
["Module:See_also_if_exists"] = 95000,
["Module:Self"] = 45000,
["Module:Self/license_migration_data.json"] = 23000,
["Module:Self/styles.css"] = 45000,
["Module:Separated_entries"] = 2760000,
["Module:Series_overview"] = 9900,
["Module:Settlement_Wikidata"] = 52000,
["Module:Settlement_short_description"] = 729000,
["Module:Shortcut"] = 29000,
["Module:Shortcut/config"] = 29000,
["Module:Shortcut/styles.css"] = 29000,
["Module:Side_box"] = 1280000,
["Module:Side_box/styles.css"] = 1280000,
["Module:Sidebar"] = 435000,
["Module:Sidebar/configuration"] = 435000,
["Module:Sidebar/styles.css"] = 441000,
["Module:Sidebar_games_events"] = 42000,
["Module:Sidebar_games_events/styles.css"] = 42000,
["Module:Singles"] = 49000,
["Module:Sister_project_links"] = 21000,
["Module:Sister_project_links/bar/styles.css"] = 7200,
["Module:Sister_project_links/config"] = 21000,
["Module:Sister_project_links/styles.css"] = 14000,
["Module:Sister_project_logo"] = 1360000,
["Module:Sister_project_logo/data"] = 1360000,
["Module:Slovak_municipality"] = 3000,
["Module:Sock_list"] = 11000,
["Module:Sort"] = 155000,
["Module:Sort_title"] = 40000,
["Module:Sortkey"] = 105000,
["Module:Split_article"] = 4200,
["Module:Spoken_Wikipedia"] = 2200,
["Module:Spoken_Wikipedia/configuration"] = 2200,
["Module:Spoken_Wikipedia/styles.css"] = 2200,
["Module:Sports_career"] = 21000,
["Module:Sports_color"] = 79000,
["Module:Sports_color/baseball"] = 36000,
["Module:Sports_color/basketball"] = 19000,
["Module:Sports_color/ice_hockey"] = 3400,
["Module:Sports_color/international_football"] = 42000,
["Module:Sports_rbr_table"] = 15000,
["Module:Sports_rbr_table/styles.css"] = 15000,
["Module:Sports_reference"] = 5100,
["Module:Sports_results"] = 19000,
["Module:Sports_results/styles.css"] = 11000,
["Module:Sports_table"] = 73000,
["Module:Sports_table/Volleyball"] = 2400,
["Module:Sports_table/WDL"] = 64000,
["Module:Sports_table/WDL_OT"] = 4000,
["Module:Sports_table/WL"] = 5500,
["Module:Sports_table/WL_OT"] = 3100,
["Module:Sports_table/argcheck"] = 73000,
["Module:Sports_table/styles.css"] = 73000,
["Module:Sports_table/sub"] = 74000,
["Module:Sports_table/totalscheck"] = 52000,
["Module:Stock_tickers/NYSE"] = 2000,
["Module:Storm_categories"] = 5900,
["Module:Storm_categories/categories"] = 5900,
["Module:Storm_categories/colors"] = 5900,
["Module:Storm_categories/icons"] = 5900,
["Module:String"] = 14300000,
["Module:String2"] = 2080000,
["Module:Su"] = 14000,
["Module:Subject_bar"] = 20000,
["Module:Suppress_categories"] = 6600,
["Module:Switcher"] = 8400,
}
f842dgbm7eeq0olk3qobc8g94x72oao
9165
9164
2026-08-23T01:43:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/S]]
9164
Scribunto
text/plain
return {
["S"] = 4300,
["S-aca"] = 6700,
["S-ach"] = 17000,
["S-aft"] = 230000,
["S-aft/check"] = 230000,
["S-aft/filter"] = 230000,
["S-bef"] = 235000,
["S-bef/check"] = 235000,
["S-bef/filter"] = 235000,
["S-break"] = 6500,
["S-bus"] = 2100,
["S-civ"] = 2900,
["S-dip"] = 6000,
["S-end"] = 262000,
["S-gov"] = 8600,
["S-hon"] = 4000,
["S-hou"] = 9800,
["S-inc"] = 13000,
["S-legal"] = 9900,
["S-line_label"] = 2000,
["S-mil"] = 13000,
["S-new"] = 17000,
["S-non"] = 11000,
["S-npo"] = 4200,
["S-off"] = 43000,
["S-par"] = 52000,
["S-par/en"] = 3300,
["S-par/gb"] = 3300,
["S-par/uk"] = 12000,
["S-par/us-hs"] = 12000,
["S-par/us-sen"] = 2100,
["S-ppo"] = 15000,
["S-prec"] = 3200,
["S-reg"] = 22000,
["S-rel"] = 19000,
["S-roy"] = 2800,
["S-sports"] = 12000,
["S-start"] = 253000,
["S-ttl"] = 242000,
["S-ttl/check"] = 242000,
["S-vac"] = 7800,
["SAU"] = 2100,
["SCO"] = 3800,
["SDcat"] = 6800000,
["SECOND"] = 2300,
["SGP"] = 2900,
["SIA"] = 2500,
["SLL"] = 2000,
["SLO"] = 4900,
["SMS"] = 6800,
["SMU"] = 2500,
["SPI_archive_notice"] = 85000,
["SPIarchive_notice"] = 82000,
["SPIcat"] = 3800,
["SPIclose"] = 3300,
["SPIpriorcases"] = 78000,
["SR/Olympics_profile"] = 2200,
["SRB"] = 4300,
["SS"] = 22000,
["SSPa"] = 2600,
["STN"] = 11000,
["SUBJECTSPACE_formatted"] = 44000,
["SUI"] = 9600,
["SVG"] = 2700,
["SVG-Logo"] = 26000,
["SVG-Res"] = 24000,
["SVG-logo"] = 14000,
["SVK"] = 8700,
["SVN"] = 5800,
["SWE"] = 13000,
["Salts_by_element"] = 2200,
["Sandbox_other"] = 467000,
["Saturday"] = 2800,
["Saved_book"] = 52000,
["Sc"] = 2900,
["Scholia"] = 3700,
["School_block"] = 13000,
["School_disambiguation"] = 3500,
["Schoolblock"] = 6900,
["Schooldis"] = 2700,
["Schoolip"] = 12000,
["Scientist_icon"] = 16000,
["Scientist_icon2"] = 16000,
["Sclass"] = 34000,
["Sclass2"] = 11000,
["Screen_reader-only"] = 108000,
["Screen_reader-only/styles.css"] = 148000,
["Script"] = 7600,
["Script/Arabic"] = 4000,
["Script/Hebrew"] = 4900,
["Script/Nastaliq"] = 15000,
["Script/doc/id-unk"] = 3200,
["Script/doc/id-unk/core"] = 3200,
["Script/doc/id-unk/is-iso-alpha4"] = 3200,
["Script/doc/id-unk/name-to-alpha4"] = 3200,
["Script/styles.css"] = 3400,
["Script/styles_arabic.css"] = 4000,
["Script/styles_hebrew.css"] = 4900,
["Sdash"] = 4000,
["Search_box"] = 73000,
["Search_link"] = 26000,
["Section_link"] = 165000,
["Section_sizes"] = 4300,
["See"] = 8900,
["See_also"] = 217000,
["Seealso"] = 7900,
["Seiner_Majestät_Schiff"] = 6800,
["Seiner_Majestät_Unterseeboot"] = 2500,
["Select_skin"] = 5500,
["Selected"] = 2000,
["Selected_article"] = 2500,
["Selected_picture"] = 2400,
["Self"] = 45000,
["Self-published_inline"] = 4700,
["Self-published_source"] = 6100,
["Self-reference"] = 2200,
["Self-reference_tool"] = 8200,
["Sent_off"] = 17000,
["Sentoff"] = 6200,
["Sequence"] = 4100,
["Series_overview"] = 9900,
["Serif"] = 5000,
["Set_category"] = 38000,
["Set_index_article"] = 6300,
["Sets_taxobox_colour"] = 3400,
["Sfn"] = 209000,
["SfnRef"] = 164000,
["Sfn_whitelist"] = 2600,
["Sfnm"] = 5900,
["Sfnp"] = 24000,
["Sfnref"] = 18000,
["Sfrac"] = 5100,
["Sfrac/styles.css"] = 5200,
["SharedIPEDU"] = 3300,
["Shared_IP"] = 10000,
["Shared_IP_corp"] = 4100,
["Shared_IP_edu"] = 186000,
["Shared_IP_gov"] = 2300,
["Sharedip"] = 3000,
["Sharedipedu"] = 3800,
["Sherdog"] = 2700,
["Ship"] = 42000,
["Ship_index"] = 7600,
["Shipboxflag"] = 21000,
["Shipboxflag/core"] = 21000,
["Shipwrecks_navbox_footer"] = 11000,
["Shipwrecks_navbox_footer/link"] = 11000,
["Short_description"] = 6940000,
["Short_description/lowercasecheck"] = 6940000,
["Short_pages_monitor"] = 16000,
["Short_pages_monitor/maximum_length"] = 16000,
["Shortcut"] = 22000,
["Should_be_SVG"] = 8200,
["Shy"] = 2200,
["Sic"] = 39000,
["Side_box"] = 1250000,
["Sidebar"] = 320000,
["Sidebar_games_events"] = 42000,
["Sidebar_person"] = 4900,
["Sidebar_person/styles.css"] = 6300,
["Sidebar_with_collapsible_lists"] = 84000,
["Sigfig"] = 4100,
["Significant_figures"] = 5600,
["Significant_figures/rnd"] = 5300,
["Signpost-subscription"] = 2100,
["Signpost-subscription/styles.css"] = 2100,
["Signpost/item"] = 49000,
["Signpost/item/core"] = 49000,
["Signpost/snippet-nopic"] = 3400,
["Signpost/snippet/styles.css"] = 3700,
["Sildb_prim"] = 2200,
["Silver02"] = 18000,
["Silver2"] = 46000,
["Silver_medal"] = 6700,
["Silver_medal_icon"] = 59000,
["Similar_names"] = 3400,
["Single+double"] = 11000,
["Single+space"] = 17000,
["Single-innings_cricket_match"] = 4000,
["Single_chart"] = 43000,
["Single_namespace"] = 337000,
["Single_source"] = 3000,
["Singlechart"] = 12000,
["Singles"] = 49000,
["Sister-inline"] = 223000,
["Sister-inline/styles.css"] = 223000,
["Sister_project"] = 1120000,
["Sister_project/styles.css"] = 1120000,
["Sister_project_links"] = 14000,
["Skip_to_talk"] = 12000,
["Skip_to_talk/styles.css"] = 12000,
["Sky"] = 3300,
["Sky/styles.css"] = 3300,
["Slink"] = 66000,
["Slovak_municipality"] = 3000,
["Slovak_municipality/geo"] = 2800,
["Small"] = 650000,
["Small_Solar_System_bodies"] = 3600,
["Smallcaps"] = 21000,
["Smallcaps/styles.css"] = 22000,
["Smalldiv"] = 43000,
["Smaller"] = 79000,
["Smiley"] = 53000,
["Snd"] = 612000,
["Snds"] = 6500,
["Soccer_icon"] = 124000,
["Soccer_icon2"] = 124000,
["Soccer_icon4"] = 3500,
["Soccerbase"] = 13000,
["Soccerbase_season"] = 8000,
["Soccerway"] = 83000,
["Sock"] = 55000,
["Sock_list"] = 11000,
["Sockcat"] = 2000,
["Sockmaster"] = 10000,
["Sockpuppet"] = 285000,
["Sockpuppet/altmaster"] = 3700,
["Sockpuppet/categorise"] = 285000,
["SockpuppetCheckuser"] = 5500,
["Sockpuppet_category"] = 52000,
["Sockpuppet_category/confirmed"] = 28000,
["Sockpuppet_category/suspected"] = 24000,
["Sockpuppetcheckuser"] = 3600,
["Sockpuppeteer"] = 29000,
["Soft_hyphen"] = 2300,
["Soft_redirect"] = 6500,
["Soft_redirect_protection"] = 10000,
["Softredirect"] = 3300,
["Solar_luminosity"] = 5200,
["Solar_mass"] = 6400,
["Solar_radius"] = 5200,
["Soldier_icon"] = 3900,
["Soldier_icon2"] = 3900,
["Songs_category"] = 9600,
["Songs_category/core"] = 9600,
["Sort"] = 122000,
["Sort_under"] = 2200,
["Sort_under/styles.css"] = 2200,
["Sortname"] = 64000,
["Source-attribution"] = 9100,
["Source_assess"] = 2700,
["Source_assess_table"] = 2700,
["Source_attribution"] = 39000,
["Source_check"] = 927000,
["Sourcecheck"] = 927000,
["Sources"] = 3600,
["Sources_exist"] = 4200,
["South_America_topic"] = 2700,
["Sp"] = 164000,
["Space"] = 130000,
["Space+apostrophe+s"] = 26000,
["Space+double"] = 7200,
["Space+single"] = 15000,
["Spaced_en_dash"] = 645000,
["Spaced_en_dash_space"] = 6600,
["Spaced_ndash"] = 22000,
["Spaces"] = 734000,
["Spain_metadata_Wikidata"] = 7400,
["Spamlink"] = 14000,
["Species_Latin_name_abbreviation_disambiguation"] = 2400,
["Species_list"] = 25000,
["Speciesbox"] = 393000,
["Speciesbox/checkgenus"] = 391000,
["Speciesbox/getGenus"] = 394000,
["Speciesbox/getSpecies"] = 393000,
["Speciesbox/name"] = 393000,
["Speciesbox/parameterCheck"] = 393000,
["Speciesbox/trim"] = 393000,
["Specieslist"] = 9300,
["Split_article"] = 4200,
["Spnd"] = 4700,
["Spoken_Wikipedia"] = 2200,
["Sport_icon"] = 16000,
["Sport_icon2"] = 17000,
["SportsYearCatUSstate"] = 6700,
["Sports_club_or_team_people_category_header"] = 14000,
["Sports_club_or_team_people_category_header/category1"] = 14000,
["Sports_links"] = 81000,
["Sports_reference"] = 5100,
["Squad_maintenance"] = 3800,
["Sronly"] = 49000,
["Srt"] = 7200,
["Stack"] = 30000,
["Stack/styles.css"] = 41000,
["Stack_begin"] = 11000,
["Stack_end"] = 11000,
["StaleIP"] = 3600,
["StandardEbooks"] = 2400,
["Standings_table_end"] = 64000,
["Standings_table_entry"] = 25000,
["Standings_table_entry/record"] = 64000,
["Standings_table_start"] = 64000,
["Standings_table_start/colheader"] = 64000,
["Standings_table_start/colspan"] = 64000,
["Standings_table_start/styles.css"] = 64000,
["Starbox_astrometry"] = 5700,
["Starbox_begin"] = 5800,
["Starbox_catalog"] = 5700,
["Starbox_character"] = 5700,
["Starbox_detail"] = 5600,
["Starbox_end"] = 5800,
["Starbox_image"] = 4000,
["Starbox_observe"] = 5800,
["Starbox_reference"] = 5700,
["Start-Class"] = 18000,
["Start-date"] = 2300,
["Start_and_end_dates"] = 3700,
["Start_box"] = 5600,
["Start_date"] = 547000,
["Start_date_and_age"] = 187000,
["Start_date_and_years_ago"] = 4000,
["Start_date_text"] = 3900,
["Start_of_course_timeline"] = 5800,
["Start_of_course_week"] = 6000,
["Start_tab"] = 6700,
["Startflatlist"] = 162000,
["Startplainlist"] = 2200,
["Static_IP"] = 5000,
["Static_row_numbers"] = 2900,
["Static_row_numbers/styles.css"] = 2900,
["Station"] = 22000,
["Station_link"] = 19000,
["Stdinchicite"] = 10000,
["Steady"] = 19000,
["Sticky_header"] = 9500,
["Sticky_header/styles.css"] = 26000,
["Stl"] = 17000,
["Stn"] = 11000,
["Stn_art_lnk"] = 2200,
["Stnlnk"] = 35000,
["Stop"] = 2000,
["Store_norske_leksikon"] = 2400,
["Storm_colour"] = 5800,
["Storm_name"] = 2400,
["Storm_path"] = 2200,
["Stortingetbio"] = 2100,
["StoryTeleplay"] = 3400,
["Str_count"] = 166000,
["Str_endswith"] = 236000,
["Str_find"] = 283000,
["Str_index"] = 15000,
["Str_left"] = 348000,
["Str_len"] = 167000,
["Str_letter"] = 184000,
["Str_letter/trim"] = 21000,
["Str_number"] = 7200,
["Str_number/trim"] = 225000,
["Str_rep"] = 298000,
["Str_right"] = 7100,
["Str_startswith"] = 2800,
["Str_trim"] = 4200,
["Str_≠_len"] = 48000,
["Str_≤_len"] = 2900,
["Str_≥_len"] = 104000,
["Strfind_short"] = 5300,
["Strike"] = 2300,
["Strikethrough"] = 20000,
["String_split"] = 5300,
["Strip_tags"] = 41000,
["Strong"] = 212000,
["Structurae"] = 2100,
["Stub-Class"] = 18000,
["Stub_Category"] = 14000,
["Stub_category"] = 21000,
["Stub_documentation"] = 42000,
["Student_editor"] = 27000,
["Student_sandbox"] = 4400,
["Student_table_row"] = 7000,
["Students_table"] = 7000,
["Su"] = 4800,
["Su-census1989"] = 4600,
["Sub"] = 4500,
["Subinfobox_bodystyle"] = 75000,
["Subject_bar"] = 20000,
["Suboff"] = 7400,
["Subon"] = 7600,
["Subpage_other"] = 408000,
["Subscription_required"] = 36000,
["Subsidebar_bodystyle"] = 6200,
["Subst_only"] = 5500,
["Substituted_comment"] = 19000,
["Succession_box"] = 119000,
["Succession_box/check"] = 119000,
["Succession_links"] = 217000,
["Summer_Olympics_by_year_category_navigation"] = 2500,
["Summer_Olympics_by_year_category_navigation/core"] = 2500,
["Sunday"] = 2800,
["Sup"] = 95000,
["Suppress_categories"] = 6600,
["Surname"] = 80000,
["Swiss_metadata_Wikidata"] = 2900,
["Swiss_populations"] = 2400,
["Swiss_populations_NC"] = 3000,
["Swiss_populations_YM"] = 2300,
["Swiss_populations_ref"] = 2400,
["Switcher"] = 8400,
["Sz"] = 2500,
["Module:SDcat"] = 6800000,
["Module:SPI_archive_notice"] = 39000,
["Module:SST"] = 13000,
["Module:SST/hosts"] = 13000,
["Module:SST/registry"] = 274000,
["Module:SST/shards/sets/COLLEDGE_SHIPS_RN"] = 3000,
["Module:SST/shards/sets/TALBERT_BARRINGTON_ATLAS"] = 2100,
["Module:Science_redirect"] = 322000,
["Module:Science_redirect/conf"] = 322000,
["Module:Section_link"] = 165000,
["Module:Section_sizes"] = 5900,
["Module:See_also_if_exists"] = 95000,
["Module:Self"] = 45000,
["Module:Self/license_migration_data.json"] = 23000,
["Module:Self/styles.css"] = 45000,
["Module:Separated_entries"] = 2760000,
["Module:Series_overview"] = 9900,
["Module:Settlement_Wikidata"] = 52000,
["Module:Settlement_short_description"] = 729000,
["Module:Shortcut"] = 29000,
["Module:Shortcut/config"] = 29000,
["Module:Shortcut/styles.css"] = 29000,
["Module:Side_box"] = 1280000,
["Module:Side_box/styles.css"] = 1280000,
["Module:Sidebar"] = 435000,
["Module:Sidebar/configuration"] = 435000,
["Module:Sidebar/styles.css"] = 441000,
["Module:Sidebar_games_events"] = 42000,
["Module:Sidebar_games_events/styles.css"] = 42000,
["Module:Singles"] = 49000,
["Module:Sister_project_links"] = 21000,
["Module:Sister_project_links/bar/styles.css"] = 7200,
["Module:Sister_project_links/config"] = 21000,
["Module:Sister_project_links/styles.css"] = 14000,
["Module:Sister_project_logo"] = 1360000,
["Module:Sister_project_logo/data"] = 1360000,
["Module:Slovak_municipality"] = 3000,
["Module:Sock_list"] = 11000,
["Module:Sort"] = 155000,
["Module:Sort_title"] = 40000,
["Module:Sortkey"] = 105000,
["Module:Split_article"] = 4200,
["Module:Spoken_Wikipedia"] = 2200,
["Module:Spoken_Wikipedia/configuration"] = 2200,
["Module:Spoken_Wikipedia/styles.css"] = 2200,
["Module:Sports_career"] = 21000,
["Module:Sports_color"] = 79000,
["Module:Sports_color/baseball"] = 36000,
["Module:Sports_color/basketball"] = 19000,
["Module:Sports_color/ice_hockey"] = 3400,
["Module:Sports_color/international_football"] = 42000,
["Module:Sports_rbr_table"] = 15000,
["Module:Sports_rbr_table/styles.css"] = 15000,
["Module:Sports_reference"] = 5100,
["Module:Sports_results"] = 19000,
["Module:Sports_results/styles.css"] = 11000,
["Module:Sports_table"] = 73000,
["Module:Sports_table/Volleyball"] = 2400,
["Module:Sports_table/WDL"] = 64000,
["Module:Sports_table/WDL_OT"] = 4000,
["Module:Sports_table/WL"] = 5500,
["Module:Sports_table/WL_OT"] = 3100,
["Module:Sports_table/argcheck"] = 73000,
["Module:Sports_table/styles.css"] = 73000,
["Module:Sports_table/sub"] = 74000,
["Module:Sports_table/totalscheck"] = 52000,
["Module:Stock_tickers/NYSE"] = 2000,
["Module:Storm_categories"] = 5900,
["Module:Storm_categories/categories"] = 5900,
["Module:Storm_categories/colors"] = 5900,
["Module:Storm_categories/icons"] = 5900,
["Module:String"] = 14300000,
["Module:String2"] = 2080000,
["Module:Su"] = 14000,
["Module:Subject_bar"] = 20000,
["Module:Suppress_categories"] = 6600,
["Module:Switcher"] = 8400,
}
f842dgbm7eeq0olk3qobc8g94x72oao
Module:Submit an edit request/doc
828
1087
9166
2024-12-16T15:34:00Z
en>HouseBlaster
0
bypass redirect
9166
wikitext
text/x-wiki
{{used in system}}
{{Lua|Module:Submit an edit request/config|Module:Redirect|Module:Effective protection level|Module:String|Module:Arguments|Module:Clickable button}}
This module implements the {{tl|submit an edit request}} and {{tl|submit an edit request/link}} templates.
== Usage from wikitext ==
To use this module from wikitext, you should normally use the {{Template link|Submit an edit request}} and {{Template link|Submit an edit request/link}} templates. However, the module can also be used directly from #invoke. For the edit request button, use <code><nowiki>{{#invoke:Submit an edit request|button|</nowiki>''args''<nowiki>}}</nowiki></code>, and for the edit request link only, use <code><nowiki>{{#invoke:Submit an edit request|link|</nowiki>''args''<nowiki>}}</nowiki></code>. Please see the respective template pages for a list of available parameters.
== Usage from Lua modules ==
To use this module from other Lua modules, first load the module.
<syntaxhighlight lang="lua">
local mEditRequest = require('Module:Submit an edit request')
</syntaxhighlight>
You can then use the _button function to generate an edit request button, and the _link function to generate an edit request link.
<syntaxhighlight lang="lua">
mEditRequest._button(args)
mEditRequest._link(args)
</syntaxhighlight>
The <var>args</var> variable should be a table containing the arguments to pass to the module. To see the different arguments that can be specified and how they affect the module output, please refer to the documentation of {{tl|Submit an edit request}} and {{tl|Submit an edit request/link}}.
== Configuration ==
This module can be translated and configured for other wikis by editing [[Module:Submit an edit request/config]].
<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
<!-- Categories go here and interwikis go in Wikidata. -->
}}</includeonly>
juy3xo0ch8zsc73mypbinkl1sw1f0mc
9167
9166
2026-08-23T01:43:25Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Submit_an_edit_request/doc]]
9166
wikitext
text/x-wiki
{{used in system}}
{{Lua|Module:Submit an edit request/config|Module:Redirect|Module:Effective protection level|Module:String|Module:Arguments|Module:Clickable button}}
This module implements the {{tl|submit an edit request}} and {{tl|submit an edit request/link}} templates.
== Usage from wikitext ==
To use this module from wikitext, you should normally use the {{Template link|Submit an edit request}} and {{Template link|Submit an edit request/link}} templates. However, the module can also be used directly from #invoke. For the edit request button, use <code><nowiki>{{#invoke:Submit an edit request|button|</nowiki>''args''<nowiki>}}</nowiki></code>, and for the edit request link only, use <code><nowiki>{{#invoke:Submit an edit request|link|</nowiki>''args''<nowiki>}}</nowiki></code>. Please see the respective template pages for a list of available parameters.
== Usage from Lua modules ==
To use this module from other Lua modules, first load the module.
<syntaxhighlight lang="lua">
local mEditRequest = require('Module:Submit an edit request')
</syntaxhighlight>
You can then use the _button function to generate an edit request button, and the _link function to generate an edit request link.
<syntaxhighlight lang="lua">
mEditRequest._button(args)
mEditRequest._link(args)
</syntaxhighlight>
The <var>args</var> variable should be a table containing the arguments to pass to the module. To see the different arguments that can be specified and how they affect the module output, please refer to the documentation of {{tl|Submit an edit request}} and {{tl|Submit an edit request/link}}.
== Configuration ==
This module can be translated and configured for other wikis by editing [[Module:Submit an edit request/config]].
<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
<!-- Categories go here and interwikis go in Wikidata. -->
}}</includeonly>
juy3xo0ch8zsc73mypbinkl1sw1f0mc
Tempilet:Pp-protected
10
1088
9169
2024-10-31T22:49:43Z
en>Primefac
0
/* top */ avoid double redir
9169
wikitext
text/x-wiki
#REDIRECT [[Template:Protection padlock]]
{{Rcat shell|
{{R from move}}
{{R from long name}}
{{R with history}}
}}
[[Category:Top icon protection templates]]
fggdzzf86ur8bq36yd27gkfxl333uwg
9170
9169
2026-08-23T01:48:12Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pp-protected]]
9169
wikitext
text/x-wiki
#REDIRECT [[Template:Protection padlock]]
{{Rcat shell|
{{R from move}}
{{R from long name}}
{{R with history}}
}}
[[Category:Top icon protection templates]]
fggdzzf86ur8bq36yd27gkfxl333uwg
Tempilet:Redirect category shell
10
1089
9171
2026-08-20T17:28:15Z
en>Jonesey95
0
magic word has been implemented as of today
9171
wikitext
text/x-wiki
__NONEWSECTIONLINK__{{Mbox
| name = Redirect category shell
| type = move
| image = none
| style = margin-top: 1.1em; border: solid 1px darkblue; border-left-width: 0.5em;
| textstyle = padding-top: 0.9em; padding-bottom: 0.9em;
| text = '''This {{Talk other|talk page|page}} is a [[Wikipedia:Redirect|redirect]]. <small>The following [[Wikipedia:Categorizing redirects|categories]] are used to track and monitor this redirect:</small>'''{{#if:{{{h|}}}
|{{block indent|1= ''{{{h}}}''}}
}}
<!--
Automatically detect protected redirects:
--><includeonly>{{#switch: {{PROTECTIONLEVEL:move}}
|sysop|templateeditor|extendedconfirmed={{pp-move|small=yes|catonly=no}}
}}{{#switch: {{PROTECTIONLEVEL:edit}}
|sysop
|templateeditor
|extendedconfirmed
|autoconfirmed={{pp-protected|small=yes}}{{R protected}}
| <!--Not protected, or only semi-move-protected-->
}}</includeonly>{{#if: {{{1|}}}||<includeonly>
* {{red|'''Important – Please Read! {{maroon|This template should {{em|not}} be applied without parameters by bot nor by any automated or semi-automated process. It should {{em|not}} be used without parameters {{em|unless you want to learn how to categorize redirects}}. For editors who want to learn how to categorize redirects, this template is a {{em|learning tool}}. {{em|Only}} those editors who intend to return to the redirect to learn which rcats to use should apply this template without parameters, or with an empty first parameter!}}'''}}</includeonly>
* '''Manifold sort''': If help is needed to determine appropriate categories, then this redirect populates '''{{Cat|Miscellaneous redirects}}'''. Monitors of that category will check this redirect and add or remove [[Wikipedia:Categorizing redirects|rcats]] as needed.{{#ifeq: {{lc:{{{nocat|false}}}}} | false |{{{category|<includeonly>[[Category:Miscellaneous redirects]]</includeonly>}}}}}
}}
{{#if: {{{2|}}}|{{{2}}}|{{{1|}}}}}{{#if: {{{1|}}}{{{2|}}}||{{#ifeq: {{ROOTPAGENAME}}|Redirect category shell||[[Category:Redirect category shell without parameters]]}}}}
''<small>When appropriate, [[Wikipedia:Protection policy|protection levels]] are automatically sensed, described and categorized.</small>''
}}<includeonly>__EXPECTSHORTPAGE__<!--To prevent pages from appearing on Special:ShortPages. See Tech News 2026-34. --></includeonly><noinclude>
{{Documentation}}
</noinclude>
dt89h4apbs7l1rhl2q3letiqcxmyceg
9172
9171
2026-08-23T01:48:12Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Redirect_category_shell]]
9171
wikitext
text/x-wiki
__NONEWSECTIONLINK__{{Mbox
| name = Redirect category shell
| type = move
| image = none
| style = margin-top: 1.1em; border: solid 1px darkblue; border-left-width: 0.5em;
| textstyle = padding-top: 0.9em; padding-bottom: 0.9em;
| text = '''This {{Talk other|talk page|page}} is a [[Wikipedia:Redirect|redirect]]. <small>The following [[Wikipedia:Categorizing redirects|categories]] are used to track and monitor this redirect:</small>'''{{#if:{{{h|}}}
|{{block indent|1= ''{{{h}}}''}}
}}
<!--
Automatically detect protected redirects:
--><includeonly>{{#switch: {{PROTECTIONLEVEL:move}}
|sysop|templateeditor|extendedconfirmed={{pp-move|small=yes|catonly=no}}
}}{{#switch: {{PROTECTIONLEVEL:edit}}
|sysop
|templateeditor
|extendedconfirmed
|autoconfirmed={{pp-protected|small=yes}}{{R protected}}
| <!--Not protected, or only semi-move-protected-->
}}</includeonly>{{#if: {{{1|}}}||<includeonly>
* {{red|'''Important – Please Read! {{maroon|This template should {{em|not}} be applied without parameters by bot nor by any automated or semi-automated process. It should {{em|not}} be used without parameters {{em|unless you want to learn how to categorize redirects}}. For editors who want to learn how to categorize redirects, this template is a {{em|learning tool}}. {{em|Only}} those editors who intend to return to the redirect to learn which rcats to use should apply this template without parameters, or with an empty first parameter!}}'''}}</includeonly>
* '''Manifold sort''': If help is needed to determine appropriate categories, then this redirect populates '''{{Cat|Miscellaneous redirects}}'''. Monitors of that category will check this redirect and add or remove [[Wikipedia:Categorizing redirects|rcats]] as needed.{{#ifeq: {{lc:{{{nocat|false}}}}} | false |{{{category|<includeonly>[[Category:Miscellaneous redirects]]</includeonly>}}}}}
}}
{{#if: {{{2|}}}|{{{2}}}|{{{1|}}}}}{{#if: {{{1|}}}{{{2|}}}||{{#ifeq: {{ROOTPAGENAME}}|Redirect category shell||[[Category:Redirect category shell without parameters]]}}}}
''<small>When appropriate, [[Wikipedia:Protection policy|protection levels]] are automatically sensed, described and categorized.</small>''
}}<includeonly>__EXPECTSHORTPAGE__<!--To prevent pages from appearing on Special:ShortPages. See Tech News 2026-34. --></includeonly><noinclude>
{{Documentation}}
</noinclude>
dt89h4apbs7l1rhl2q3letiqcxmyceg
Tempilet:Talk other
10
1090
9173
2022-02-04T21:51:58Z
en>MSGJ
0
remove comment
9173
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{lc: {{{demospace}}} }} <!--Use lower case "demospace"-->
| {{#ifeq:{{NAMESPACE}}|{{TALKSPACE}}
| talk
| other
}}
}}
| talk = {{{1|}}}
| other
| #default = {{{2|}}}
}}<!--End switch--><noinclude>
{{documentation}}
</noinclude>
jp99kuih528b90wq2so1nbhkt480jzw
9174
9173
2026-08-23T01:48:12Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Talk_other]]
9173
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{lc: {{{demospace}}} }} <!--Use lower case "demospace"-->
| {{#ifeq:{{NAMESPACE}}|{{TALKSPACE}}
| talk
| other
}}
}}
| talk = {{{1|}}}
| other
| #default = {{{2|}}}
}}<!--End switch--><noinclude>
{{documentation}}
</noinclude>
jp99kuih528b90wq2so1nbhkt480jzw
Tempilet:Redirect template
10
1091
9175
2025-08-11T23:33:23Z
en>Pppery
0
Changed protection settings for "[[Template:Redirect template]]": [[WP:High-risk templates|High-risk template or module]] ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9175
wikitext
text/x-wiki
{{#invoke:Redirect template|main}}<noinclude>
{{Documentation}}</noinclude>
1cl28dcwjsrtge5hedu653jwub1cll3
9176
9175
2026-08-23T01:48:12Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Redirect_template]]
9175
wikitext
text/x-wiki
{{#invoke:Redirect template|main}}<noinclude>
{{Documentation}}</noinclude>
1cl28dcwjsrtge5hedu653jwub1cll3
Tempilet:R from move
10
1092
9177
2022-07-21T18:41:22Z
en>Steel1943
0
Undid revision 996791156 by [[Special:Contributions/Paine Ellsworth|Paine Ellsworth]] ([[User talk:Paine Ellsworth|talk]]) this wording addition needs discussion since it wasn't discussed and I don't agree with it (and how I didn't notice it for over a year ... not sure)
9177
wikitext
text/x-wiki
<noinclude>{{hatnote|This rcat template is automatically added to all new redirects that result from page moves; it must be added manually to older redirects when appropriate.}}{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R from move
|name=From a page move
|from=a page that has been moved (renamed)
|info=This page was kept as a redirect to avoid breaking links, both internal and external, that may have been made to the old page name.
|all category=Redirects from moves
}}<includeonly>{{R from move/except}}</includeonly><noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
jb1j0dw49p25rsnw8nldcu4oogum41x
9178
9177
2026-08-23T01:48:12Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_from_move]]
9177
wikitext
text/x-wiki
<noinclude>{{hatnote|This rcat template is automatically added to all new redirects that result from page moves; it must be added manually to older redirects when appropriate.}}{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R from move
|name=From a page move
|from=a page that has been moved (renamed)
|info=This page was kept as a redirect to avoid breaking links, both internal and external, that may have been made to the old page name.
|all category=Redirects from moves
}}<includeonly>{{R from move/except}}</includeonly><noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
jb1j0dw49p25rsnw8nldcu4oogum41x
Tempilet:R from move/except
10
1093
9179
2024-05-08T00:57:29Z
en>SilverLocust
0
Have that R2 tracking category also show a message
9179
wikitext
text/x-wiki
<noinclude>This is the exception page for {{tl|R from move}}. This page makes exceptions that include certain pages that should not inhabit either {{cat|Unsynchronized talk page redirects}} or {{cat|Redirects from moves}}. If necessary, new exceptions may be added with no need to edit the main template, {{tl|R from move}}.
</noinclude>{{#switch: {{FULLPAGENAME}}
|MediaWiki:Move-redirect-text=
|Template:R from move/except=
|#default=[[Category:Redirects from moves]]
}}{{#switch: {{NAMESPACENUMBER}}
|1={{#ifeq: {{#invoke:redirect|isRedirect|{{FULLPAGENAME}}}}|yes|
{{#ifeq: {{#invoke:redirect|isRedirect|{{SUBJECTPAGENAME}}}}|yes|
{{#ifeq: {{PAGENAME:{{#invoke:redirect|main|{{TALKPAGENAME}}}}}}|{{PAGENAME:{{#invoke:redirect|main|{{SUBJECTPAGENAME}}}}}}||
{{#ifeq: {{FULLPAGENAME}}|{{SUBJECTPAGENAME}}||
{{#ifeq: {{Str left|{{PAGENAME}}|16}}|List of ships of||[[Category:Unsynchronized talk page redirects]]
}}
}}
}}
|{{#ifexist:{{SUBJECTPAGENAME}}|
{{#ifeq: {{SUBJECTPAGENAME}}|{{Target of|{{SUBJECTPAGENAME:{{Target of|{{FULLPAGENAME}}}}}}}}|[[Category:Articles with unsynchronized talk page redirects]]|
{{#ifexpr: {{#invoke:string|find|{{#invoke:page|getContent|{{SUBJECTPAGENAME}}|as=raw}}|:Rfd}}|[[Category:Redirects for discussion with talk page redirects]]|[[Category:Articles with talk page redirects]]}}}}
}}
}}
|{{error|Page is not a redirect, misplaced [[Template:R from move]]}}
}}
|0={{#switch:{{NAMESPACENUMBER:{{#invoke:redirect|main|{{FULLPAGENAME}}}}}}|0|4|10|12|14|100=|#default={{R from move/Cross-namespace}}}}
}}<noinclude>
{{Documentation|Template:R from move/doc}}
</noinclude>
2a82jzb8kp50itnyti0qkq1qte99dnn
9180
9179
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_from_move/except]]
9179
wikitext
text/x-wiki
<noinclude>This is the exception page for {{tl|R from move}}. This page makes exceptions that include certain pages that should not inhabit either {{cat|Unsynchronized talk page redirects}} or {{cat|Redirects from moves}}. If necessary, new exceptions may be added with no need to edit the main template, {{tl|R from move}}.
</noinclude>{{#switch: {{FULLPAGENAME}}
|MediaWiki:Move-redirect-text=
|Template:R from move/except=
|#default=[[Category:Redirects from moves]]
}}{{#switch: {{NAMESPACENUMBER}}
|1={{#ifeq: {{#invoke:redirect|isRedirect|{{FULLPAGENAME}}}}|yes|
{{#ifeq: {{#invoke:redirect|isRedirect|{{SUBJECTPAGENAME}}}}|yes|
{{#ifeq: {{PAGENAME:{{#invoke:redirect|main|{{TALKPAGENAME}}}}}}|{{PAGENAME:{{#invoke:redirect|main|{{SUBJECTPAGENAME}}}}}}||
{{#ifeq: {{FULLPAGENAME}}|{{SUBJECTPAGENAME}}||
{{#ifeq: {{Str left|{{PAGENAME}}|16}}|List of ships of||[[Category:Unsynchronized talk page redirects]]
}}
}}
}}
|{{#ifexist:{{SUBJECTPAGENAME}}|
{{#ifeq: {{SUBJECTPAGENAME}}|{{Target of|{{SUBJECTPAGENAME:{{Target of|{{FULLPAGENAME}}}}}}}}|[[Category:Articles with unsynchronized talk page redirects]]|
{{#ifexpr: {{#invoke:string|find|{{#invoke:page|getContent|{{SUBJECTPAGENAME}}|as=raw}}|:Rfd}}|[[Category:Redirects for discussion with talk page redirects]]|[[Category:Articles with talk page redirects]]}}}}
}}
}}
|{{error|Page is not a redirect, misplaced [[Template:R from move]]}}
}}
|0={{#switch:{{NAMESPACENUMBER:{{#invoke:redirect|main|{{FULLPAGENAME}}}}}}|0|4|10|12|14|100=|#default={{R from move/Cross-namespace}}}}
}}<noinclude>
{{Documentation|Template:R from move/doc}}
</noinclude>
2a82jzb8kp50itnyti0qkq1qte99dnn
Module:Redirect template
828
1094
9181
2025-08-11T23:33:36Z
en>Pppery
0
Changed protection settings for "[[Module:Redirect template]]" ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9181
Scribunto
text/plain
require('strict')
local p = {}
-- key is beginning of arg name. value is table with namespace number and link
-- alternatively, a function taking the namespace number and returning a validity
-- can be used
local namespaceCategories = {
all = { function() return true end },
main = { 0, '[[WP:Mainspace|main]]' },
help = { 12, '[[WP:Help namespace|help]]' },
portal = { 100, '[[WP:Portal|portal]]' },
mos = { 126, '[[WP:MOS namespace|MOS]]' },
talk = { function(n) return n > 0 and n%2 == 1 end, '[[Help:Talk pages|talk]]' },
template = { 10, '[[WP:Template namespace|template]]' },
wikipedia = { 4, '[[WP:Project namespace|Wikipedia project]]' },
category = { 14, '[[WP:Categorization|category]]' },
user = { 2, '[[WP:User pages|user]]' },
draft = { 118, '[[WP:Drafts|draft]]' },
}
-- remove whitespaces from beginning and end of args
local function valueFunc(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
end
end
return val
end
local function getPrettyName(args)
for k in pairs(namespaceCategories) do
if args[k .. ' category'] then
return string.format("'''[[:Category:%s|%s]]''': ", args[k .. ' category'], args.name)
end
end
return string.format("'''%s''': ", args.name)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:Redirect template', valueFunc = valueFunc})
local namespace = mw.title.getCurrentTitle().namespace
--- XXX: this is a HORRIBLE HACK. kill it with fire as soon as https://phabricator.wikimedia.org/T14974 is fixed
--- [[phab:T14974]] was previously known as [[bugzilla:12974]] https://bugzilla.wikimedia.org/show_bug.cgi?id=12974
local beCompatibleWithBug14974 = args.info and (args.info:find('^[:;#*]', 1) == 1 or args.info:find('{|', 1, true) == 1) and '\n' or ' '
local content = string.format('\n<div class="rcat %s">\n*%sThis is a redirect%s%s.%s%s\n</div>',
args.id and ('rcat-' .. string.gsub(args.id, ' ', '_')) or '',
args.name and getPrettyName(args) or '',
args.from and (' from ' .. args.from) or '',
args.to and (' to ' .. args.to) or '',
args.info and beCompatibleWithBug14974 or '',
args.info or ''
)
for k,v in pairs(namespaceCategories) do
if args[k .. ' category'] then
if type(v[1]) == 'function' and v[1](namespace) or v[1] == namespace then
if args.sortkey then
content = content .. string.format('[[Category:%s|%s]]', args[k .. ' category'], args.sortkey)
else
content = content .. string.format('[[Category:%s]]', args[k .. ' category'])
end
elseif args['other category'] then
if args.sortkey then
content = content .. string.format('[[Category:%s|%s]]', args['other category'], args.sortkey)
else
content = content .. string.format('[[Category:%s]]', args['other category'])
end
else
content = content .. frame:expandTemplate{title = 'Incorrect redirect template', args = {v[2]}}
end
end
end
if namespace == 0 then
local yesno = require('Module:Yesno')
if yesno(args.printworthy) == true then
return content .. '[[Category:Printworthy redirects]]'
elseif yesno(args.printworthy) == false then
return content .. '[[Category:Unprintworthy redirects]]'
end
end
return content
end
return p
7vajdchxsgtfzfo0bbnl18pwnlasddx
9182
9181
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Redirect_template]]
9181
Scribunto
text/plain
require('strict')
local p = {}
-- key is beginning of arg name. value is table with namespace number and link
-- alternatively, a function taking the namespace number and returning a validity
-- can be used
local namespaceCategories = {
all = { function() return true end },
main = { 0, '[[WP:Mainspace|main]]' },
help = { 12, '[[WP:Help namespace|help]]' },
portal = { 100, '[[WP:Portal|portal]]' },
mos = { 126, '[[WP:MOS namespace|MOS]]' },
talk = { function(n) return n > 0 and n%2 == 1 end, '[[Help:Talk pages|talk]]' },
template = { 10, '[[WP:Template namespace|template]]' },
wikipedia = { 4, '[[WP:Project namespace|Wikipedia project]]' },
category = { 14, '[[WP:Categorization|category]]' },
user = { 2, '[[WP:User pages|user]]' },
draft = { 118, '[[WP:Drafts|draft]]' },
}
-- remove whitespaces from beginning and end of args
local function valueFunc(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
end
end
return val
end
local function getPrettyName(args)
for k in pairs(namespaceCategories) do
if args[k .. ' category'] then
return string.format("'''[[:Category:%s|%s]]''': ", args[k .. ' category'], args.name)
end
end
return string.format("'''%s''': ", args.name)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:Redirect template', valueFunc = valueFunc})
local namespace = mw.title.getCurrentTitle().namespace
--- XXX: this is a HORRIBLE HACK. kill it with fire as soon as https://phabricator.wikimedia.org/T14974 is fixed
--- [[phab:T14974]] was previously known as [[bugzilla:12974]] https://bugzilla.wikimedia.org/show_bug.cgi?id=12974
local beCompatibleWithBug14974 = args.info and (args.info:find('^[:;#*]', 1) == 1 or args.info:find('{|', 1, true) == 1) and '\n' or ' '
local content = string.format('\n<div class="rcat %s">\n*%sThis is a redirect%s%s.%s%s\n</div>',
args.id and ('rcat-' .. string.gsub(args.id, ' ', '_')) or '',
args.name and getPrettyName(args) or '',
args.from and (' from ' .. args.from) or '',
args.to and (' to ' .. args.to) or '',
args.info and beCompatibleWithBug14974 or '',
args.info or ''
)
for k,v in pairs(namespaceCategories) do
if args[k .. ' category'] then
if type(v[1]) == 'function' and v[1](namespace) or v[1] == namespace then
if args.sortkey then
content = content .. string.format('[[Category:%s|%s]]', args[k .. ' category'], args.sortkey)
else
content = content .. string.format('[[Category:%s]]', args[k .. ' category'])
end
elseif args['other category'] then
if args.sortkey then
content = content .. string.format('[[Category:%s|%s]]', args['other category'], args.sortkey)
else
content = content .. string.format('[[Category:%s]]', args['other category'])
end
else
content = content .. frame:expandTemplate{title = 'Incorrect redirect template', args = {v[2]}}
end
end
end
if namespace == 0 then
local yesno = require('Module:Yesno')
if yesno(args.printworthy) == true then
return content .. '[[Category:Printworthy redirects]]'
elseif yesno(args.printworthy) == false then
return content .. '[[Category:Unprintworthy redirects]]'
end
end
return content
end
return p
7vajdchxsgtfzfo0bbnl18pwnlasddx
Tempilet:Rcat shell
10
1095
9183
2021-01-24T13:30:52Z
en>Elli
0
add {{R from high-use template}}
9183
wikitext
text/x-wiki
#REDIRECT [[Template:Redirect category shell]]
{{Redirect category shell|
{{R from high-use template}}
{{R to redirect template}}
{{R from template shortcut}}
}}
p2aqcolqolaorvl3bv21oc68tkj2wxw
9184
9183
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Rcat_shell]]
9183
wikitext
text/x-wiki
#REDIRECT [[Template:Redirect category shell]]
{{Redirect category shell|
{{R from high-use template}}
{{R to redirect template}}
{{R from template shortcut}}
}}
p2aqcolqolaorvl3bv21oc68tkj2wxw
Tempilet:Pp-move
10
1096
9185
2026-08-16T14:03:11Z
en>RMCD bot
0
Notifying subject page of move discussion on [[Template talk:Protection padlock#Requested move 16 August 2026|Template talk:Protection padlock]]
9185
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Move-protected|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
9d4y4f3ih6lpwzr9mu2reqmn8htizmo
9186
9185
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pp-move]]
9185
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Move-protected|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
9d4y4f3ih6lpwzr9mu2reqmn8htizmo
Tempilet:R with history
10
1097
9187
2024-12-23T00:44:42Z
en>HouseBlaster
0
semantic markup
9187
wikitext
text/x-wiki
<noinclude>
{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R with history
|name=With history
|from=a page containing <span class="editlink plainlinks">[{{fullurl:{{FULLPAGENAMEE}}|action=history}} '''substantive page history''']</span>
|info=This page is kept as a redirect to preserve its former content and attributions. Please <em>do not</em> remove the tag that generates this text (unless the need to recreate content on this page has been demonstrated), nor delete this page.
** This template should <em>not</em> be used for redirects having some edit history but no meaningful content in their previous versions, nor for redirects created as a result of a [[Wikipedia:Merging|page merge]] (use {{tl|R from merge}} instead), nor for redirects from a title that forms a historic part of Wikipedia (use {{tl|R with old history}} instead).
|all category=Redirects with history
}}<noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{documentation}}
</noinclude>
f93vdvyyipmtbr38ntr4lyajrlxl5yu
9188
9187
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_with_history]]
9187
wikitext
text/x-wiki
<noinclude>
{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R with history
|name=With history
|from=a page containing <span class="editlink plainlinks">[{{fullurl:{{FULLPAGENAMEE}}|action=history}} '''substantive page history''']</span>
|info=This page is kept as a redirect to preserve its former content and attributions. Please <em>do not</em> remove the tag that generates this text (unless the need to recreate content on this page has been demonstrated), nor delete this page.
** This template should <em>not</em> be used for redirects having some edit history but no meaningful content in their previous versions, nor for redirects created as a result of a [[Wikipedia:Merging|page merge]] (use {{tl|R from merge}} instead), nor for redirects from a title that forms a historic part of Wikipedia (use {{tl|R with old history}} instead).
|all category=Redirects with history
}}<noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{documentation}}
</noinclude>
f93vdvyyipmtbr38ntr4lyajrlxl5yu
Tempilet:R from long name
10
1098
9189
2025-11-25T04:58:29Z
en>Paine Ellsworth
0
per edit request on talk page - include unnamed parameter
9189
wikitext
text/x-wiki
<noinclude>{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R from long name
|name=From a longer title
|from=a title that is a complete, more complete or longer version of the topic's name{{#if:{{{of|{{{for|{{{1|}}}}}}}}}|<nowiki />; the short version is: "{{{of|{{{for|{{{1}}}}}}}}}"}}
|info=It leads to the title in accordance with the naming conventions for [[WP:COMMONNAME|common names]] and can help writing and searches. However, do not replace these redirected links with a [[WP:piped link|piped link]] unless the page is updated for another reason.
|all category=Redirects from long names
}}<noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
iqxzjdw6emc8ldpn9bcjcsrhchzjd8b
9190
9189
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_from_long_name]]
9189
wikitext
text/x-wiki
<noinclude>{{This is a redirect/rcat}}
</noinclude>{{Redirect template
|id=R from long name
|name=From a longer title
|from=a title that is a complete, more complete or longer version of the topic's name{{#if:{{{of|{{{for|{{{1|}}}}}}}}}|<nowiki />; the short version is: "{{{of|{{{for|{{{1}}}}}}}}}"}}
|info=It leads to the title in accordance with the naming conventions for [[WP:COMMONNAME|common names]] and can help writing and searches. However, do not replace these redirected links with a [[WP:piped link|piped link]] unless the page is updated for another reason.
|all category=Redirects from long names
}}<noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
iqxzjdw6emc8ldpn9bcjcsrhchzjd8b
Tempilet:R protected
10
1099
9191
2026-04-10T21:42:21Z
en>Toadspike
0
Adding {{pp-template}}
9191
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#switch:{{{protlevel|{{#invoke:effective protection level|edit|1={{{title|{{FULLPAGENAME}}}}}}}}}}
|sysop={{R protected/full|nocat={{{nocat|}}}}}{{pp-protected|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|templateeditor={{R protected/template|nocat={{{nocat|}}}}}{{pp-template|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|extendedconfirmed={{R protected/excon|nocat={{{nocat|}}}}}{{pp-extended|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|autoconfirmed={{R protected/semi|nocat={{{nocat|}}}}}{{pp-semi|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|#default=<!-- Show nothing -->{{#ifeq:{{{nocat|}}}|true||[[Category:Wikipedia pages with incorrect protection templates]]}}
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
e03wg7rf043et6g51gjxh8u9x8ia1li
9192
9191
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_protected]]
9191
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#switch:{{{protlevel|{{#invoke:effective protection level|edit|1={{{title|{{FULLPAGENAME}}}}}}}}}}
|sysop={{R protected/full|nocat={{{nocat|}}}}}{{pp-protected|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|templateeditor={{R protected/template|nocat={{{nocat|}}}}}{{pp-template|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|extendedconfirmed={{R protected/excon|nocat={{{nocat|}}}}}{{pp-extended|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|autoconfirmed={{R protected/semi|nocat={{{nocat|}}}}}{{pp-semi|small=yes|category={{#ifeq:{{{nocat|}}}|true|no|yes}}}}
|#default=<!-- Show nothing -->{{#ifeq:{{{nocat|}}}|true||[[Category:Wikipedia pages with incorrect protection templates]]}}
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
e03wg7rf043et6g51gjxh8u9x8ia1li
Tempilet:Pp-template
10
1100
9193
2026-08-16T14:03:24Z
en>RMCD bot
0
Notifying subject page of move discussion on [[Template talk:Protection padlock#Requested move 16 August 2026|Template talk:Protection padlock]]
9193
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Template-protected|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
3k9596rbxyf00i52qw8xg2itbyhe89l
9194
9193
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pp-template]]
9193
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Template-protected|2=Template talk:Protection padlock#Requested move 16 August 2026}}
</noinclude><includeonly>{{#invoke:Protection banner|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
3k9596rbxyf00i52qw8xg2itbyhe89l
Tempilet:R protected/template
10
1101
9195
2026-01-10T23:38:19Z
en>Andrybak
0
wrap categorization in <includeonly></includeonly> to remove this page from [[:Category:Wikipedia pages with incorrect protection templates]]
9195
wikitext
text/x-wiki
{{Redirect template
|id=R template-protected
|name=[[:Category:Wikipedia template-protected redirects|Template-protected]]
|from=a page that is template-protected from editing for any of several possible reasons. Only administrators and template editors may edit this page
|info=** '''Please do not replace these redirected links''' with links directly to the target page unless expressly advised to do so below or elsewhere on this page, or if the change is supported by a policy or guideline.
|template category=<!--for automatic namespace detection-->
}}<includeonly>{{#ifeq:{{{nocat|}}}|true||{{#ifeq:{{FULLPAGENAME}}|Template:R template-protected||{{#ifeq: {{SUBPAGENAME}}|sandbox||{{#switch: {{PROTECTIONLEVEL:move}}
|templateeditor=[[Category:Wikipedia template-protected redirects]]
|sysop=[[Category:Wikipedia move-protected pages]]
}}{{#switch: {{PROTECTIONLEVEL:edit}}
|templateeditor=[[Category:Wikipedia template-protected redirects]]
|sysop|autoconfirmed|extendedconfirmed|#default=[[Category:Wikipedia pages with incorrect protection templates]]
}}}}}}}}</includeonly><noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{documentation}}
</noinclude>
jn1kvzk5qpnk0dh8vbq74u19oomhxvv
9196
9195
2026-08-23T01:48:13Z
RAPTOR7762
18
1 revision imported from [[:en:Template:R_protected/template]]
9195
wikitext
text/x-wiki
{{Redirect template
|id=R template-protected
|name=[[:Category:Wikipedia template-protected redirects|Template-protected]]
|from=a page that is template-protected from editing for any of several possible reasons. Only administrators and template editors may edit this page
|info=** '''Please do not replace these redirected links''' with links directly to the target page unless expressly advised to do so below or elsewhere on this page, or if the change is supported by a policy or guideline.
|template category=<!--for automatic namespace detection-->
}}<includeonly>{{#ifeq:{{{nocat|}}}|true||{{#ifeq:{{FULLPAGENAME}}|Template:R template-protected||{{#ifeq: {{SUBPAGENAME}}|sandbox||{{#switch: {{PROTECTIONLEVEL:move}}
|templateeditor=[[Category:Wikipedia template-protected redirects]]
|sysop=[[Category:Wikipedia move-protected pages]]
}}{{#switch: {{PROTECTIONLEVEL:edit}}
|templateeditor=[[Category:Wikipedia template-protected redirects]]
|sysop|autoconfirmed|extendedconfirmed|#default=[[Category:Wikipedia pages with incorrect protection templates]]
}}}}}}}}</includeonly><noinclude>
<!-- Place categories on /doc subpage; interwikis go to Wikidata. -->
{{documentation}}
</noinclude>
jn1kvzk5qpnk0dh8vbq74u19oomhxvv
Tempilet:Template link/doc
10
1102
9197
2026-08-20T06:30:25Z
en>GhostInTheMachine
0
prune stuff about macros, ce
9197
wikitext
text/x-wiki
{{Documentation subpage}}
{{Template shortcut|t|tl|TL}}
{{#ifeq:{{FULLPAGENAME}} | Template:Template link | {{used in system}} {{cascade-protected template}} }}
{{Always substitute|yesnomaybe=never|actualtemplate={{tl}}}}
'''Template link''' displays a template name as a link surrounded by braces, thus showing the template name as code rather than actually invoking it.
Note that this template has aliases {{TLX|tl}} ("T el") and {{TLX|t1}} ("T one"). They should not be confused with {{TLX|ti}} ("T eye"), which is an alias for {{TLX|Template information}}.
{{Tlx|Tla}} works exactly like {{tlx|tl}} but allows displaying alternative label text (link label).
{{Tlx|Tlg}} can display parameters for the template.
==Examples==
A short example of its use:
:: {{tlx|tl|Example}}
: which generates
:: {{tl|Example}}
Other longer examples:
{| class="wikitable"
! Code
! Result
! Notes
|-
| {{tlx|tl|Void}}
| {{tl|Void}}
| Standard usage
|-
| {{tlx|tls|Example}}
| {{tls|Example}}
| For templates that should be [[Wikipedia:Substitution|substituted]]
|-
| {{tlx|tl2|X1}}
| {{tl2|X1}}
| This formats the link to show how it would look in code (i.e., monospace font)
|-
| {{tlx|tl2|sister{{=}}M:|3x}}
| {{tl2|sister=M:|3x}}
| Same as above, for templates on another Wikimedia project (in this example, Meta, using '''<code>m:</code>'''). See [[Help:Interwiki_linking#Prefix_codes_for_linking_to_Wikimedia_sister_projects|Interwiki codes]].
|-
| {{tlx|tl2|sister{{=}}wikibooks|lang{{=}}de:|WP}}
| {{tl2|sister=wikibooks|lang=de|WP}}
| For templates on another language project
|-
| {{tlx|tl|1{{=}}{{=}})}}
| {{tl|1==)}}
| Use the format <code><nowiki>{{tl|1=templatename}}</nowiki></code> if the template contains template coding characters such as {{tl|1==)}} or {{tl|1=!}}
|}
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "This template displays a template name as a link surrounded by braces, thus showing how the template name would be used in code. Its primary use is in instruction and documentation.",
"params": {
"1": {
"label": "Template name",
"description": "Positional parameter: the template name without the namespace prefix “Template:”, which is added automatically",
"type": "wiki-template-name",
"required": true
}
},
"format": "inline"
}</templatedata>
== See also ==
* {{tiw|tl2}}
* {{tiw|tl}}
* {{tiw|tlp}} to produce a [t]emplate [l]ink with a single [p]arameter
* {{tiw|tlx}} to produce a [t]emplate [l]ink with an e[x]panded number of parameters
* {{tiw|tlsp}} to produce a [t]emplate [l]ink that's [[Wikipedia:Substitution|[s]ubst:]]ituted, with a single [p]arameter
* {{tiw|lts}}
* {{tiw|tlu}}, tl or tlp in any [[Wikipedia:Namespaces|namespace]]
* {{lcs|Internal template-link templates}}
* {{tiw|tl-r}} to produce a [t]emplate [l]ink to a template [r]edirect
{{Template-linking templates}}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:Internal template-link templates]]
[[Category:Variadic templates]]
}}</includeonly>
ryuw79sy4y8qptvt55fh3kt1x95pv4s
9198
9197
2026-08-23T02:44:37Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_link/doc]]
9197
wikitext
text/x-wiki
{{Documentation subpage}}
{{Template shortcut|t|tl|TL}}
{{#ifeq:{{FULLPAGENAME}} | Template:Template link | {{used in system}} {{cascade-protected template}} }}
{{Always substitute|yesnomaybe=never|actualtemplate={{tl}}}}
'''Template link''' displays a template name as a link surrounded by braces, thus showing the template name as code rather than actually invoking it.
Note that this template has aliases {{TLX|tl}} ("T el") and {{TLX|t1}} ("T one"). They should not be confused with {{TLX|ti}} ("T eye"), which is an alias for {{TLX|Template information}}.
{{Tlx|Tla}} works exactly like {{tlx|tl}} but allows displaying alternative label text (link label).
{{Tlx|Tlg}} can display parameters for the template.
==Examples==
A short example of its use:
:: {{tlx|tl|Example}}
: which generates
:: {{tl|Example}}
Other longer examples:
{| class="wikitable"
! Code
! Result
! Notes
|-
| {{tlx|tl|Void}}
| {{tl|Void}}
| Standard usage
|-
| {{tlx|tls|Example}}
| {{tls|Example}}
| For templates that should be [[Wikipedia:Substitution|substituted]]
|-
| {{tlx|tl2|X1}}
| {{tl2|X1}}
| This formats the link to show how it would look in code (i.e., monospace font)
|-
| {{tlx|tl2|sister{{=}}M:|3x}}
| {{tl2|sister=M:|3x}}
| Same as above, for templates on another Wikimedia project (in this example, Meta, using '''<code>m:</code>'''). See [[Help:Interwiki_linking#Prefix_codes_for_linking_to_Wikimedia_sister_projects|Interwiki codes]].
|-
| {{tlx|tl2|sister{{=}}wikibooks|lang{{=}}de:|WP}}
| {{tl2|sister=wikibooks|lang=de|WP}}
| For templates on another language project
|-
| {{tlx|tl|1{{=}}{{=}})}}
| {{tl|1==)}}
| Use the format <code><nowiki>{{tl|1=templatename}}</nowiki></code> if the template contains template coding characters such as {{tl|1==)}} or {{tl|1=!}}
|}
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "This template displays a template name as a link surrounded by braces, thus showing how the template name would be used in code. Its primary use is in instruction and documentation.",
"params": {
"1": {
"label": "Template name",
"description": "Positional parameter: the template name without the namespace prefix “Template:”, which is added automatically",
"type": "wiki-template-name",
"required": true
}
},
"format": "inline"
}</templatedata>
== See also ==
* {{tiw|tl2}}
* {{tiw|tl}}
* {{tiw|tlp}} to produce a [t]emplate [l]ink with a single [p]arameter
* {{tiw|tlx}} to produce a [t]emplate [l]ink with an e[x]panded number of parameters
* {{tiw|tlsp}} to produce a [t]emplate [l]ink that's [[Wikipedia:Substitution|[s]ubst:]]ituted, with a single [p]arameter
* {{tiw|lts}}
* {{tiw|tlu}}, tl or tlp in any [[Wikipedia:Namespaces|namespace]]
* {{lcs|Internal template-link templates}}
* {{tiw|tl-r}} to produce a [t]emplate [l]ink to a template [r]edirect
{{Template-linking templates}}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:Internal template-link templates]]
[[Category:Variadic templates]]
}}</includeonly>
ryuw79sy4y8qptvt55fh3kt1x95pv4s
9199
9198
2026-08-23T02:54:07Z
RAPTOR7762
18
9199
wikitext
text/x-wiki
{{Documentation subpage}}
{{Template shortcut|t|tl|TL}}
{{pp-protected|small=yes}}
{{Always substitute|yesnomaybe=never|actualtemplate={{tl}}}}
'''Template link''' displays a template name as a link surrounded by braces, thus showing the template name as code rather than actually invoking it.
Note that this template has aliases {{TLX|tl}} ("T el") and {{TLX|t1}} ("T one"). They should not be confused with {{TLX|ti}} ("T eye"), which is an alias for {{TLX|Template information}}.
{{Tlx|Tla}} works exactly like {{tlx|tl}} but allows displaying alternative label text (link label).
{{Tlx|Tlg}} can display parameters for the template.
==Examples==
A short example of its use:
:: {{tlx|tl|Example}}
: which generates
:: {{tl|Example}}
Other longer examples:
{| class="wikitable"
! Code
! Result
! Notes
|-
| {{tlx|tl|Void}}
| {{tl|Void}}
| Standard usage
|-
| {{tlx|tls|Example}}
| {{tls|Example}}
| For templates that should be [[Wikipedia:Substitution|substituted]]
|-
| {{tlx|tl2|X1}}
| {{tl2|X1}}
| This formats the link to show how it would look in code (i.e., monospace font)
|-
| {{tlx|tl2|sister{{=}}M:|3x}}
| {{tl2|sister=M:|3x}}
| Same as above, for templates on another Wikimedia project (in this example, Meta, using '''<code>m:</code>'''). See [[Help:Interwiki_linking#Prefix_codes_for_linking_to_Wikimedia_sister_projects|Interwiki codes]].
|-
| {{tlx|tl2|sister{{=}}wikibooks|lang{{=}}de:|WP}}
| {{tl2|sister=wikibooks|lang=de|WP}}
| For templates on another language project
|-
| {{tlx|tl|1{{=}}{{=}})}}
| {{tl|1==)}}
| Use the format <code><nowiki>{{tl|1=templatename}}</nowiki></code> if the template contains template coding characters such as {{tl|1==)}} or {{tl|1=!}}
|}
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "This template displays a template name as a link surrounded by braces, thus showing how the template name would be used in code. Its primary use is in instruction and documentation.",
"params": {
"1": {
"label": "Template name",
"description": "Positional parameter: the template name without the namespace prefix “Template:”, which is added automatically",
"type": "wiki-template-name",
"required": true
}
},
"format": "inline"
}</templatedata>
== See also ==
* {{tiw|tl2}}
* {{tiw|tl}}
* {{tiw|tlp}} to produce a [t]emplate [l]ink with a single [p]arameter
* {{tiw|tlx}} to produce a [t]emplate [l]ink with an e[x]panded number of parameters
* {{tiw|tlsp}} to produce a [t]emplate [l]ink that's [[Wikipedia:Substitution|[s]ubst:]]ituted, with a single [p]arameter
* {{tiw|lts}}
* {{tiw|tlu}}, tl or tlp in any [[Wikipedia:Namespaces|namespace]]
* {{lcs|Internal template-link templates}}
* {{tiw|tl-r}} to produce a [t]emplate [l]ink to a template [r]edirect
{{Template-linking templates}}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:Internal template-link templates]]
[[Category:Variadic templates]]
}}</includeonly>
isxlljevqadkeru2d60cwtlnn1svat9
9200
9199
2026-08-23T02:54:38Z
RAPTOR7762
18
/* */
9200
wikitext
text/x-wiki
{{Documentation subpage}}
{{Template shortcut|t|tl|TL}}
<includeonly>{{pp-protected|small=yes}}</includeonly>
{{Always substitute|yesnomaybe=never|actualtemplate={{tl}}}}
'''Template link''' displays a template name as a link surrounded by braces, thus showing the template name as code rather than actually invoking it.
Note that this template has aliases {{TLX|tl}} ("T el") and {{TLX|t1}} ("T one"). They should not be confused with {{TLX|ti}} ("T eye"), which is an alias for {{TLX|Template information}}.
{{Tlx|Tla}} works exactly like {{tlx|tl}} but allows displaying alternative label text (link label).
{{Tlx|Tlg}} can display parameters for the template.
==Examples==
A short example of its use:
:: {{tlx|tl|Example}}
: which generates
:: {{tl|Example}}
Other longer examples:
{| class="wikitable"
! Code
! Result
! Notes
|-
| {{tlx|tl|Void}}
| {{tl|Void}}
| Standard usage
|-
| {{tlx|tls|Example}}
| {{tls|Example}}
| For templates that should be [[Wikipedia:Substitution|substituted]]
|-
| {{tlx|tl2|X1}}
| {{tl2|X1}}
| This formats the link to show how it would look in code (i.e., monospace font)
|-
| {{tlx|tl2|sister{{=}}M:|3x}}
| {{tl2|sister=M:|3x}}
| Same as above, for templates on another Wikimedia project (in this example, Meta, using '''<code>m:</code>'''). See [[Help:Interwiki_linking#Prefix_codes_for_linking_to_Wikimedia_sister_projects|Interwiki codes]].
|-
| {{tlx|tl2|sister{{=}}wikibooks|lang{{=}}de:|WP}}
| {{tl2|sister=wikibooks|lang=de|WP}}
| For templates on another language project
|-
| {{tlx|tl|1{{=}}{{=}})}}
| {{tl|1==)}}
| Use the format <code><nowiki>{{tl|1=templatename}}</nowiki></code> if the template contains template coding characters such as {{tl|1==)}} or {{tl|1=!}}
|}
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "This template displays a template name as a link surrounded by braces, thus showing how the template name would be used in code. Its primary use is in instruction and documentation.",
"params": {
"1": {
"label": "Template name",
"description": "Positional parameter: the template name without the namespace prefix “Template:”, which is added automatically",
"type": "wiki-template-name",
"required": true
}
},
"format": "inline"
}</templatedata>
== See also ==
* {{tiw|tl2}}
* {{tiw|tl}}
* {{tiw|tlp}} to produce a [t]emplate [l]ink with a single [p]arameter
* {{tiw|tlx}} to produce a [t]emplate [l]ink with an e[x]panded number of parameters
* {{tiw|tlsp}} to produce a [t]emplate [l]ink that's [[Wikipedia:Substitution|[s]ubst:]]ituted, with a single [p]arameter
* {{tiw|lts}}
* {{tiw|tlu}}, tl or tlp in any [[Wikipedia:Namespaces|namespace]]
* {{lcs|Internal template-link templates}}
* {{tiw|tl-r}} to produce a [t]emplate [l]ink to a template [r]edirect
{{Template-linking templates}}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:Internal template-link templates]]
[[Category:Variadic templates]]
}}</includeonly>
oigos131sqtcmwvmeypmcacw5i510km
Module:Arguments/doc
828
1103
9206
2026-07-30T06:00:15Z
en>John of Reading
0
Reverted 1 edit by [[Special:Contributions/~2026-42282-05|~2026-42282-05]] ([[User talk:~2026-42282-05|talk]]): Unexplained blanking
9206
wikitext
text/x-wiki
{{Used in system}}
{{Module rating|p}}
{{cascade-protected template|page=module}}
This module provides easy processing of arguments passed from <code>#invoke</code>. It is a meta-module, meant for use by other modules, and should not be called from <code>#invoke</code> directly. Its features include:
* Easy [[Trimming (computer programming)|trimming]] of arguments and removal of blank arguments.
* Arguments can be passed by both the current frame and by the parent frame at the same time. (More details below.)
* Arguments can be passed in directly from another Lua module or from the debug console.
* Most features can be customized.
== Basic use ==
First, you need to load the module. It contains one function, named <code>getArgs</code>.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
</syntaxhighlight>
In the most basic scenario, you can use getArgs inside your main function. The variable <code>args</code> is a table containing the arguments from #invoke. (See below for details.)
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
-- Main module code goes here.
end
return p
</syntaxhighlight>
=== Recommended practice ===
However, the recommended practice is to use a separate function as the entry point from <code>#invoke</code> just for processing the arguments. This allows other Lua modules to call your core logic directly, improving performance by avoiding the overhead of interacting with the <code>frame</code> object.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
-- Main module code goes here.
end
return p
</syntaxhighlight>
The way this is called from a template is <code><nowiki>{{#invoke:Example|main}}</nowiki></code> (optionally with some parameters like <code><nowiki>{{#invoke:Example|main|arg1=value1|arg2=value2}}</nowiki></code>), and the way this is called from a module is <syntaxhighlight lang=lua inline>require('Module:Example')._main({arg1 = 'value1', arg2 = value2, 'spaced arg3' = 'value3'})</syntaxhighlight>. What this second one does is construct a table with the arguments in it, then gives that table to the p._main(args) function, which uses it natively.
=== Multiple functions ===
If you want multiple functions to use the arguments, and you also want them to be accessible from #invoke, you can use a wrapper function.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
p.func1 = makeInvokeFunc('_func1')
function p._func1(args)
-- Code for the first function goes here.
end
p.func2 = makeInvokeFunc('_func2')
function p._func2(args)
-- Code for the second function goes here.
end
return p
</syntaxhighlight>
== Options ==
The following options are available. They are explained in the sections below.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false,
removeBlanks = false,
valueFunc = function (key, value)
-- Code for processing one argument
end,
frameOnly = true,
parentOnly = true,
parentFirst = true,
wrappers = {
'Template:A wrapper template',
'Template:Another wrapper template'
},
readOnly = true,
noOverwrite = true
})
</syntaxhighlight>
=== Trimming whitespace ===
MediaWiki trims whitespace for named arguments coming from #invoke or a template call, but preserves whitespace for positional arguments. By default, this module helps trim whitespace also for position arguments. To preserve whitespace for positional arguments, set the <code>trim</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false
})
</syntaxhighlight>
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for trimming whitespace, and the <code>trim</code> option will have no effect.
=== Removing blank arguments ===
"Blank arguments" are arguments from #invoke or template that are blank strings or consist of only whitespace. By default, this module removes all blank arguments. To preserve the blank arguments, set the <code>removeBlanks</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
removeBlanks = false
})
</syntaxhighlight>
This might be necessary for some templates' operation.
Note: When converting MediaWiki templates to Lua, keep in mind that in Lua, blank strings and strings consisting only of whitespace are considered true. If you don't pay attention to such blank arguments when you write your Lua modules, you might treat something as true that should actually be treated as false.
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for handling blank arguments, and the <code>removeBlanks</code> option will have no effect.
=== Custom formatting of arguments ===
Sometimes you want to remove some blank arguments but not others, or perhaps you might want to put all of the positional arguments in lower case. To do things like this you can use the <code>valueFunc</code> option. The input to this option must be a function that takes two parameters, <code>key</code> and <code>value</code>, and returns a single value. This value is what you will get when you access the field <code>key</code> in the <code>args</code> table.
Example 1: this function preserves whitespace for the first positional argument's value, but trims all other arguments' value and removes all other blank arguments.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif value then
value = mw.text.trim(value)
if value ~= '' then
return value
end
end
return nil
end
})
</syntaxhighlight>
Example 2: this function removes blank arguments and converts all argument values to lower case, but doesn't trim whitespace from positional parameters.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if not value then
return nil
end
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
end
return nil
end
})
</syntaxhighlight>
Note: the above functions will fail if passed input that is not of type <code>string</code> or <code>nil</code>. This might be the case if you use the <code>getArgs</code> function in the main function of your module, and that function is called by another Lua module. In this case, you will need to check the type of your input. This is not a problem if you are using a function specially for arguments from #invoke (i.e. you have <code>p.main</code> and <code>p._main</code> functions, or something similar).
{{cot|Examples 1 and 2 with type checking}}
Example 1:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif type(value) == 'string' then
value = mw.text.trim(value)
if value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
Example 2:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
{{cob}}
Also, please note that the <code>valueFunc</code> function is called more or less every time an argument is requested from the <code>args</code> table, so if you care about performance you should make sure you aren't doing anything inefficient with your code.
=== Frames and parent frames ===
Arguments in the <code>args</code> table can be passed from the current frame or from its parent frame at the same time. To understand what this means, it is easiest to give an example. Let's say that we have a module called <code>Module:ExampleArgs</code>. This module prints the first two positional arguments that it is passed.
{{cot|Module:ExampleArgs code}}
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
local first = args[1] or ''
local second = args[2] or ''
return first .. ' ' .. second
end
return p
</syntaxhighlight>
{{cob}}
<code>Template:ExampleArgs</code> contains the code <code><nowiki>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}</nowiki></code>.
Now if we were to call <code>Template:ExampleArgs</code>, the following would happen:
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <pre>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}
(call #invoke directly without template)</pre>
| ''firstInvokeArg''
(call #invoke directly without template)
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
There are three options you can set to change this behaviour: <code>frameOnly</code>, <code>parentOnly</code> and <code>parentFirst</code>. If you set <code>frameOnly</code> then only arguments passed from the current frame will be accepted; if you set <code>parentOnly</code> then only arguments passed from the parent frame will be accepted; and if you set <code>parentFirst</code> then arguments will be passed from both the current and parent frames, but the parent frame will have priority over the current frame. Here are the results in terms of <code>Template:ExampleArgs</code>:
; frameOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; parentOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; parentFirst
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
Notes:
# If you set both the <code>frameOnly</code> and <code>parentOnly</code> options, the module won't fetch any arguments at all from #invoke. This is probably not what you want.
# In some situations a parent frame may not be available, e.g. if getArgs is passed the parent frame rather than the current frame. In this case, only the frame arguments will be used (unless parentOnly is set, in which case no arguments will be used) and the <code>parentFirst</code> and <code>frameOnly</code> options will have no effect.
=== Wrappers ===
The ''wrappers'' option is used to specify a limited number of templates as ''wrapper templates'', that is, templates whose only purpose is to call a module. If the module detects that it is being called from a wrapper template, it will only check for arguments in the parent frame; otherwise it will only check for arguments in the frame passed to getArgs. This allows modules to be called by either #invoke or through a wrapper template without the loss of performance associated with having to check both the frame and the parent frame for each argument lookup.
For example, the only content of [[Template:Side box]] (excluding content in {{tag|noinclude}} tags) is <code><nowiki>{{#invoke:Side box|main}}</nowiki></code>. There is no point in checking the arguments passed directly to the #invoke statement for this template, as no arguments will ever be specified there. We can avoid checking arguments passed to #invoke by using the ''parentOnly'' option, but if we do this then #invoke will not work from other pages either. If this were the case, the {{para|text|Some text}} in the code <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> would be ignored completely, no matter what page it was used from. By using the <code>wrappers</code> option to specify 'Template:Side box' as a wrapper, we can make <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> work from most pages, while still not requiring that the module check for arguments on the [[Template:Side box]] page itself.
Wrappers can be specified either as a string, or as an array of strings.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = 'Template:Wrapper template'
})
</syntaxhighlight>
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = {
'Template:Wrapper 1',
'Template:Wrapper 2',
-- Any number of wrapper templates can be added here.
}
})
</syntaxhighlight>
The <code>wrappers</code> option changes the default behaviors of the <code>frameOnly</code> and <code>parentOnly</code> options.
{{collapse top|title=Behaviors of ''frameOnly'' and ''parentOnly'' in relations with wrapper templates}}
; If <code>Template:ExampleArgs</code> is specified as a wrapper template:
; <code>parentOnly</code> is true or not set
The frame arguments will not be used at all.
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; If <code>wrappers</code> is set but <code>Template:ExampleArgs</code> is not in the <code>wrappers</code> list:
; <code>frameOnly</code> is true or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
{{collapse bottom}}
Notes:
# The module will automatically detect if it is being called from a wrapper template's /sandbox subpage, so there is no need to specify sandbox pages explicitly.
# If the ''wrappers'' option is set and no parent frame is available, the module will always get the arguments from the frame passed to <code>getArgs</code>.
=== Writing to the args table ===
Sometimes it can be useful to write new values to the args table. This is possible with the default settings of this module. (However, bear in mind that it is usually better coding style to create a new table with your new values and copy arguments from the args table as needed.)
<syntaxhighlight lang="lua">
args.foo = 'some value'
</syntaxhighlight>
It is possible to alter this behaviour with the <code>readOnly</code> and <code>noOverwrite</code> options. If <code>readOnly</code> is set then it is not possible to write any values to the args table at all. If <code>noOverwrite</code> is set, then it is possible to add new values to the table, but it is not possible to add a value if it would overwrite any arguments that are passed from #invoke.
== Notes ==
=== Ref tags ===
This module uses [[mw:Extension:Scribunto/Lua reference manual#Metatables|metatables]] to fetch arguments from #invoke. This allows access to both the frame arguments and the parent frame arguments without using the <code>pairs()</code> function. This can help if your module might be passed {{tag|ref}} tags as input.
As soon as {{tag|ref}} tags are accessed from Lua, they are processed by the MediaWiki software and the reference will appear in the reference list at the bottom of the article. If your module proceeds to omit the reference tag from the output, you will end up with a phantom reference – a reference that appears in the reference list but without any number linking to it. This has been a problem with modules that use <code>pairs()</code> to detect whether to use the arguments from the frame or the parent frame, as those modules automatically process every available argument.
This module solves this problem by allowing access to both frame and parent frame arguments, while still only fetching those arguments when it is necessary. The problem will still occur if you use <code>pairs(args)</code> elsewhere in your module, however.
=== Known limitations ===
The use of metatables also has its downsides. Most of the normal Lua table tools won't work properly on the args table, including the <code>#</code> operator, the <code>next()</code> function, and the functions in the table library. If using these is important for your module, you should use your own argument processing function instead of this module.<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:Lua metamodules]]
}}</includeonly>
== See also ==
* {{tl|Template parameter value}}
<includeonly>{{Sandbox other||
<!-- Categories below this line; interwikis at Wikidata -->
[[Category:Wikipedia utility modules]]
}}</includeonly>
<noinclude>
[[Category:Module documentation pages]]
</noinclude>
8crhbj871v0ij9fwji03najvw3jqeb9
9207
9206
2026-08-23T02:58:40Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Arguments/doc]]
9206
wikitext
text/x-wiki
{{Used in system}}
{{Module rating|p}}
{{cascade-protected template|page=module}}
This module provides easy processing of arguments passed from <code>#invoke</code>. It is a meta-module, meant for use by other modules, and should not be called from <code>#invoke</code> directly. Its features include:
* Easy [[Trimming (computer programming)|trimming]] of arguments and removal of blank arguments.
* Arguments can be passed by both the current frame and by the parent frame at the same time. (More details below.)
* Arguments can be passed in directly from another Lua module or from the debug console.
* Most features can be customized.
== Basic use ==
First, you need to load the module. It contains one function, named <code>getArgs</code>.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
</syntaxhighlight>
In the most basic scenario, you can use getArgs inside your main function. The variable <code>args</code> is a table containing the arguments from #invoke. (See below for details.)
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
-- Main module code goes here.
end
return p
</syntaxhighlight>
=== Recommended practice ===
However, the recommended practice is to use a separate function as the entry point from <code>#invoke</code> just for processing the arguments. This allows other Lua modules to call your core logic directly, improving performance by avoiding the overhead of interacting with the <code>frame</code> object.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
-- Main module code goes here.
end
return p
</syntaxhighlight>
The way this is called from a template is <code><nowiki>{{#invoke:Example|main}}</nowiki></code> (optionally with some parameters like <code><nowiki>{{#invoke:Example|main|arg1=value1|arg2=value2}}</nowiki></code>), and the way this is called from a module is <syntaxhighlight lang=lua inline>require('Module:Example')._main({arg1 = 'value1', arg2 = value2, 'spaced arg3' = 'value3'})</syntaxhighlight>. What this second one does is construct a table with the arguments in it, then gives that table to the p._main(args) function, which uses it natively.
=== Multiple functions ===
If you want multiple functions to use the arguments, and you also want them to be accessible from #invoke, you can use a wrapper function.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
p.func1 = makeInvokeFunc('_func1')
function p._func1(args)
-- Code for the first function goes here.
end
p.func2 = makeInvokeFunc('_func2')
function p._func2(args)
-- Code for the second function goes here.
end
return p
</syntaxhighlight>
== Options ==
The following options are available. They are explained in the sections below.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false,
removeBlanks = false,
valueFunc = function (key, value)
-- Code for processing one argument
end,
frameOnly = true,
parentOnly = true,
parentFirst = true,
wrappers = {
'Template:A wrapper template',
'Template:Another wrapper template'
},
readOnly = true,
noOverwrite = true
})
</syntaxhighlight>
=== Trimming whitespace ===
MediaWiki trims whitespace for named arguments coming from #invoke or a template call, but preserves whitespace for positional arguments. By default, this module helps trim whitespace also for position arguments. To preserve whitespace for positional arguments, set the <code>trim</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false
})
</syntaxhighlight>
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for trimming whitespace, and the <code>trim</code> option will have no effect.
=== Removing blank arguments ===
"Blank arguments" are arguments from #invoke or template that are blank strings or consist of only whitespace. By default, this module removes all blank arguments. To preserve the blank arguments, set the <code>removeBlanks</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
removeBlanks = false
})
</syntaxhighlight>
This might be necessary for some templates' operation.
Note: When converting MediaWiki templates to Lua, keep in mind that in Lua, blank strings and strings consisting only of whitespace are considered true. If you don't pay attention to such blank arguments when you write your Lua modules, you might treat something as true that should actually be treated as false.
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for handling blank arguments, and the <code>removeBlanks</code> option will have no effect.
=== Custom formatting of arguments ===
Sometimes you want to remove some blank arguments but not others, or perhaps you might want to put all of the positional arguments in lower case. To do things like this you can use the <code>valueFunc</code> option. The input to this option must be a function that takes two parameters, <code>key</code> and <code>value</code>, and returns a single value. This value is what you will get when you access the field <code>key</code> in the <code>args</code> table.
Example 1: this function preserves whitespace for the first positional argument's value, but trims all other arguments' value and removes all other blank arguments.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif value then
value = mw.text.trim(value)
if value ~= '' then
return value
end
end
return nil
end
})
</syntaxhighlight>
Example 2: this function removes blank arguments and converts all argument values to lower case, but doesn't trim whitespace from positional parameters.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if not value then
return nil
end
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
end
return nil
end
})
</syntaxhighlight>
Note: the above functions will fail if passed input that is not of type <code>string</code> or <code>nil</code>. This might be the case if you use the <code>getArgs</code> function in the main function of your module, and that function is called by another Lua module. In this case, you will need to check the type of your input. This is not a problem if you are using a function specially for arguments from #invoke (i.e. you have <code>p.main</code> and <code>p._main</code> functions, or something similar).
{{cot|Examples 1 and 2 with type checking}}
Example 1:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif type(value) == 'string' then
value = mw.text.trim(value)
if value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
Example 2:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
{{cob}}
Also, please note that the <code>valueFunc</code> function is called more or less every time an argument is requested from the <code>args</code> table, so if you care about performance you should make sure you aren't doing anything inefficient with your code.
=== Frames and parent frames ===
Arguments in the <code>args</code> table can be passed from the current frame or from its parent frame at the same time. To understand what this means, it is easiest to give an example. Let's say that we have a module called <code>Module:ExampleArgs</code>. This module prints the first two positional arguments that it is passed.
{{cot|Module:ExampleArgs code}}
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
local first = args[1] or ''
local second = args[2] or ''
return first .. ' ' .. second
end
return p
</syntaxhighlight>
{{cob}}
<code>Template:ExampleArgs</code> contains the code <code><nowiki>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}</nowiki></code>.
Now if we were to call <code>Template:ExampleArgs</code>, the following would happen:
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <pre>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}
(call #invoke directly without template)</pre>
| ''firstInvokeArg''
(call #invoke directly without template)
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
There are three options you can set to change this behaviour: <code>frameOnly</code>, <code>parentOnly</code> and <code>parentFirst</code>. If you set <code>frameOnly</code> then only arguments passed from the current frame will be accepted; if you set <code>parentOnly</code> then only arguments passed from the parent frame will be accepted; and if you set <code>parentFirst</code> then arguments will be passed from both the current and parent frames, but the parent frame will have priority over the current frame. Here are the results in terms of <code>Template:ExampleArgs</code>:
; frameOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; parentOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; parentFirst
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
Notes:
# If you set both the <code>frameOnly</code> and <code>parentOnly</code> options, the module won't fetch any arguments at all from #invoke. This is probably not what you want.
# In some situations a parent frame may not be available, e.g. if getArgs is passed the parent frame rather than the current frame. In this case, only the frame arguments will be used (unless parentOnly is set, in which case no arguments will be used) and the <code>parentFirst</code> and <code>frameOnly</code> options will have no effect.
=== Wrappers ===
The ''wrappers'' option is used to specify a limited number of templates as ''wrapper templates'', that is, templates whose only purpose is to call a module. If the module detects that it is being called from a wrapper template, it will only check for arguments in the parent frame; otherwise it will only check for arguments in the frame passed to getArgs. This allows modules to be called by either #invoke or through a wrapper template without the loss of performance associated with having to check both the frame and the parent frame for each argument lookup.
For example, the only content of [[Template:Side box]] (excluding content in {{tag|noinclude}} tags) is <code><nowiki>{{#invoke:Side box|main}}</nowiki></code>. There is no point in checking the arguments passed directly to the #invoke statement for this template, as no arguments will ever be specified there. We can avoid checking arguments passed to #invoke by using the ''parentOnly'' option, but if we do this then #invoke will not work from other pages either. If this were the case, the {{para|text|Some text}} in the code <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> would be ignored completely, no matter what page it was used from. By using the <code>wrappers</code> option to specify 'Template:Side box' as a wrapper, we can make <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> work from most pages, while still not requiring that the module check for arguments on the [[Template:Side box]] page itself.
Wrappers can be specified either as a string, or as an array of strings.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = 'Template:Wrapper template'
})
</syntaxhighlight>
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = {
'Template:Wrapper 1',
'Template:Wrapper 2',
-- Any number of wrapper templates can be added here.
}
})
</syntaxhighlight>
The <code>wrappers</code> option changes the default behaviors of the <code>frameOnly</code> and <code>parentOnly</code> options.
{{collapse top|title=Behaviors of ''frameOnly'' and ''parentOnly'' in relations with wrapper templates}}
; If <code>Template:ExampleArgs</code> is specified as a wrapper template:
; <code>parentOnly</code> is true or not set
The frame arguments will not be used at all.
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; If <code>wrappers</code> is set but <code>Template:ExampleArgs</code> is not in the <code>wrappers</code> list:
; <code>frameOnly</code> is true or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
{{collapse bottom}}
Notes:
# The module will automatically detect if it is being called from a wrapper template's /sandbox subpage, so there is no need to specify sandbox pages explicitly.
# If the ''wrappers'' option is set and no parent frame is available, the module will always get the arguments from the frame passed to <code>getArgs</code>.
=== Writing to the args table ===
Sometimes it can be useful to write new values to the args table. This is possible with the default settings of this module. (However, bear in mind that it is usually better coding style to create a new table with your new values and copy arguments from the args table as needed.)
<syntaxhighlight lang="lua">
args.foo = 'some value'
</syntaxhighlight>
It is possible to alter this behaviour with the <code>readOnly</code> and <code>noOverwrite</code> options. If <code>readOnly</code> is set then it is not possible to write any values to the args table at all. If <code>noOverwrite</code> is set, then it is possible to add new values to the table, but it is not possible to add a value if it would overwrite any arguments that are passed from #invoke.
== Notes ==
=== Ref tags ===
This module uses [[mw:Extension:Scribunto/Lua reference manual#Metatables|metatables]] to fetch arguments from #invoke. This allows access to both the frame arguments and the parent frame arguments without using the <code>pairs()</code> function. This can help if your module might be passed {{tag|ref}} tags as input.
As soon as {{tag|ref}} tags are accessed from Lua, they are processed by the MediaWiki software and the reference will appear in the reference list at the bottom of the article. If your module proceeds to omit the reference tag from the output, you will end up with a phantom reference – a reference that appears in the reference list but without any number linking to it. This has been a problem with modules that use <code>pairs()</code> to detect whether to use the arguments from the frame or the parent frame, as those modules automatically process every available argument.
This module solves this problem by allowing access to both frame and parent frame arguments, while still only fetching those arguments when it is necessary. The problem will still occur if you use <code>pairs(args)</code> elsewhere in your module, however.
=== Known limitations ===
The use of metatables also has its downsides. Most of the normal Lua table tools won't work properly on the args table, including the <code>#</code> operator, the <code>next()</code> function, and the functions in the table library. If using these is important for your module, you should use your own argument processing function instead of this module.<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:Lua metamodules]]
}}</includeonly>
== See also ==
* {{tl|Template parameter value}}
<includeonly>{{Sandbox other||
<!-- Categories below this line; interwikis at Wikidata -->
[[Category:Wikipedia utility modules]]
}}</includeonly>
<noinclude>
[[Category:Module documentation pages]]
</noinclude>
8crhbj871v0ij9fwji03najvw3jqeb9
9208
9207
2026-08-23T03:15:18Z
RAPTOR7762
18
9208
wikitext
text/x-wiki
{{Used in system}}
{{Template rating|release}}
<includeonly>{{pp-protected|small=yes}}</includeonly>
This module provides easy processing of arguments passed from <code>#invoke</code>. It is a meta-module, meant for use by other modules, and should not be called from <code>#invoke</code> directly. Its features include:
* Easy [[Trimming (computer programming)|trimming]] of arguments and removal of blank arguments.
* Arguments can be passed by both the current frame and by the parent frame at the same time. (More details below.)
* Arguments can be passed in directly from another Lua module or from the debug console.
* Most features can be customized.
== Basic use ==
First, you need to load the module. It contains one function, named <code>getArgs</code>.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
</syntaxhighlight>
In the most basic scenario, you can use getArgs inside your main function. The variable <code>args</code> is a table containing the arguments from #invoke. (See below for details.)
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
-- Main module code goes here.
end
return p
</syntaxhighlight>
=== Recommended practice ===
However, the recommended practice is to use a separate function as the entry point from <code>#invoke</code> just for processing the arguments. This allows other Lua modules to call your core logic directly, improving performance by avoiding the overhead of interacting with the <code>frame</code> object.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
-- Main module code goes here.
end
return p
</syntaxhighlight>
The way this is called from a template is <code><nowiki>{{#invoke:Example|main}}</nowiki></code> (optionally with some parameters like <code><nowiki>{{#invoke:Example|main|arg1=value1|arg2=value2}}</nowiki></code>), and the way this is called from a module is <syntaxhighlight lang=lua inline>require('Module:Example')._main({arg1 = 'value1', arg2 = value2, 'spaced arg3' = 'value3'})</syntaxhighlight>. What this second one does is construct a table with the arguments in it, then gives that table to the p._main(args) function, which uses it natively.
=== Multiple functions ===
If you want multiple functions to use the arguments, and you also want them to be accessible from #invoke, you can use a wrapper function.
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
p.func1 = makeInvokeFunc('_func1')
function p._func1(args)
-- Code for the first function goes here.
end
p.func2 = makeInvokeFunc('_func2')
function p._func2(args)
-- Code for the second function goes here.
end
return p
</syntaxhighlight>
== Options ==
The following options are available. They are explained in the sections below.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false,
removeBlanks = false,
valueFunc = function (key, value)
-- Code for processing one argument
end,
frameOnly = true,
parentOnly = true,
parentFirst = true,
wrappers = {
'Template:A wrapper template',
'Template:Another wrapper template'
},
readOnly = true,
noOverwrite = true
})
</syntaxhighlight>
=== Trimming whitespace ===
MediaWiki trims whitespace for named arguments coming from #invoke or a template call, but preserves whitespace for positional arguments. By default, this module helps trim whitespace also for position arguments. To preserve whitespace for positional arguments, set the <code>trim</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
trim = false
})
</syntaxhighlight>
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for trimming whitespace, and the <code>trim</code> option will have no effect.
=== Removing blank arguments ===
"Blank arguments" are arguments from #invoke or template that are blank strings or consist of only whitespace. By default, this module removes all blank arguments. To preserve the blank arguments, set the <code>removeBlanks</code> option to <code>false</code>.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
removeBlanks = false
})
</syntaxhighlight>
This might be necessary for some templates' operation.
Note: When converting MediaWiki templates to Lua, keep in mind that in Lua, blank strings and strings consisting only of whitespace are considered true. If you don't pay attention to such blank arguments when you write your Lua modules, you might treat something as true that should actually be treated as false.
When the <code>valueFunc</code> option is given, the <code>valueFunc</code> function will be responsible for handling blank arguments, and the <code>removeBlanks</code> option will have no effect.
=== Custom formatting of arguments ===
Sometimes you want to remove some blank arguments but not others, or perhaps you might want to put all of the positional arguments in lower case. To do things like this you can use the <code>valueFunc</code> option. The input to this option must be a function that takes two parameters, <code>key</code> and <code>value</code>, and returns a single value. This value is what you will get when you access the field <code>key</code> in the <code>args</code> table.
Example 1: this function preserves whitespace for the first positional argument's value, but trims all other arguments' value and removes all other blank arguments.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif value then
value = mw.text.trim(value)
if value ~= '' then
return value
end
end
return nil
end
})
</syntaxhighlight>
Example 2: this function removes blank arguments and converts all argument values to lower case, but doesn't trim whitespace from positional parameters.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if not value then
return nil
end
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
end
return nil
end
})
</syntaxhighlight>
Note: the above functions will fail if passed input that is not of type <code>string</code> or <code>nil</code>. This might be the case if you use the <code>getArgs</code> function in the main function of your module, and that function is called by another Lua module. In this case, you will need to check the type of your input. This is not a problem if you are using a function specially for arguments from #invoke (i.e. you have <code>p.main</code> and <code>p._main</code> functions, or something similar).
{{cot|Examples 1 and 2 with type checking}}
Example 1:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif type(value) == 'string' then
value = mw.text.trim(value)
if value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
Example 2:
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
else
return nil
end
else
return value
end
end
})
</syntaxhighlight>
{{cob}}
Also, please note that the <code>valueFunc</code> function is called more or less every time an argument is requested from the <code>args</code> table, so if you care about performance you should make sure you aren't doing anything inefficient with your code.
=== Frames and parent frames ===
Arguments in the <code>args</code> table can be passed from the current frame or from its parent frame at the same time. To understand what this means, it is easiest to give an example. Let's say that we have a module called <code>Module:ExampleArgs</code>. This module prints the first two positional arguments that it is passed.
{{cot|Module:ExampleArgs code}}
<syntaxhighlight lang="lua">
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
local first = args[1] or ''
local second = args[2] or ''
return first .. ' ' .. second
end
return p
</syntaxhighlight>
{{cob}}
<code>Template:ExampleArgs</code> contains the code <code><nowiki>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}</nowiki></code>.
Now if we were to call <code>Template:ExampleArgs</code>, the following would happen:
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <pre>{{#invoke:ExampleArgs|main|''firstInvokeArg''}}
(call #invoke directly without template)</pre>
| ''firstInvokeArg''
(call #invoke directly without template)
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
There are three options you can set to change this behaviour: <code>frameOnly</code>, <code>parentOnly</code> and <code>parentFirst</code>. If you set <code>frameOnly</code> then only arguments passed from the current frame will be accepted; if you set <code>parentOnly</code> then only arguments passed from the parent frame will be accepted; and if you set <code>parentFirst</code> then arguments will be passed from both the current and parent frames, but the parent frame will have priority over the current frame. Here are the results in terms of <code>Template:ExampleArgs</code>:
; frameOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; parentOnly
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; parentFirst
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
Notes:
# If you set both the <code>frameOnly</code> and <code>parentOnly</code> options, the module won't fetch any arguments at all from #invoke. This is probably not what you want.
# In some situations a parent frame may not be available, e.g. if getArgs is passed the parent frame rather than the current frame. In this case, only the frame arguments will be used (unless parentOnly is set, in which case no arguments will be used) and the <code>parentFirst</code> and <code>frameOnly</code> options will have no effect.
=== Wrappers ===
The ''wrappers'' option is used to specify a limited number of templates as ''wrapper templates'', that is, templates whose only purpose is to call a module. If the module detects that it is being called from a wrapper template, it will only check for arguments in the parent frame; otherwise it will only check for arguments in the frame passed to getArgs. This allows modules to be called by either #invoke or through a wrapper template without the loss of performance associated with having to check both the frame and the parent frame for each argument lookup.
For example, the only content of [[Template:Side box]] (excluding content in {{tag|noinclude}} tags) is <code><nowiki>{{#invoke:Side box|main}}</nowiki></code>. There is no point in checking the arguments passed directly to the #invoke statement for this template, as no arguments will ever be specified there. We can avoid checking arguments passed to #invoke by using the ''parentOnly'' option, but if we do this then #invoke will not work from other pages either. If this were the case, the {{para|text|Some text}} in the code <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> would be ignored completely, no matter what page it was used from. By using the <code>wrappers</code> option to specify 'Template:Side box' as a wrapper, we can make <code><nowiki>{{#invoke:Side box|main|text=Some text}}</nowiki></code> work from most pages, while still not requiring that the module check for arguments on the [[Template:Side box]] page itself.
Wrappers can be specified either as a string, or as an array of strings.
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = 'Template:Wrapper template'
})
</syntaxhighlight>
<syntaxhighlight lang="lua">
local args = getArgs(frame, {
wrappers = {
'Template:Wrapper 1',
'Template:Wrapper 2',
-- Any number of wrapper templates can be added here.
}
})
</syntaxhighlight>
The <code>wrappers</code> option changes the default behaviors of the <code>frameOnly</code> and <code>parentOnly</code> options.
{{collapse top|title=Behaviors of ''frameOnly'' and ''parentOnly'' in relations with wrapper templates}}
; If <code>Template:ExampleArgs</code> is specified as a wrapper template:
; <code>parentOnly</code> is true or not set
The frame arguments will not be used at all.
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
|
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>parentOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
; If <code>wrappers</code> is set but <code>Template:ExampleArgs</code> is not in the <code>wrappers</code> list:
; <code>frameOnly</code> is true or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is false or not set
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| ''firstInvokeArg'' secondTemplateArg
|}
; <code>frameOnly</code> is false, <code>parentFirst</code> is true
{| class="wikitable" style="width: 50em; max-width: 100%;"
|-
! style="width: 60%;" | Code
! style="width: 40%;" | Result
|-
| <code><nowiki>{{ExampleArgs}}</nowiki></code>
| ''firstInvokeArg''
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg}}</nowiki></code>
| firstTemplateArg
|-
| <code><nowiki>{{ExampleArgs|firstTemplateArg|secondTemplateArg}}</nowiki></code>
| firstTemplateArg secondTemplateArg
|}
{{collapse bottom}}
Notes:
# The module will automatically detect if it is being called from a wrapper template's /sandbox subpage, so there is no need to specify sandbox pages explicitly.
# If the ''wrappers'' option is set and no parent frame is available, the module will always get the arguments from the frame passed to <code>getArgs</code>.
=== Writing to the args table ===
Sometimes it can be useful to write new values to the args table. This is possible with the default settings of this module. (However, bear in mind that it is usually better coding style to create a new table with your new values and copy arguments from the args table as needed.)
<syntaxhighlight lang="lua">
args.foo = 'some value'
</syntaxhighlight>
It is possible to alter this behaviour with the <code>readOnly</code> and <code>noOverwrite</code> options. If <code>readOnly</code> is set then it is not possible to write any values to the args table at all. If <code>noOverwrite</code> is set, then it is possible to add new values to the table, but it is not possible to add a value if it would overwrite any arguments that are passed from #invoke.
== Notes ==
=== Ref tags ===
This module uses [[mw:Extension:Scribunto/Lua reference manual#Metatables|metatables]] to fetch arguments from #invoke. This allows access to both the frame arguments and the parent frame arguments without using the <code>pairs()</code> function. This can help if your module might be passed {{tag|ref}} tags as input.
As soon as {{tag|ref}} tags are accessed from Lua, they are processed by the MediaWiki software and the reference will appear in the reference list at the bottom of the article. If your module proceeds to omit the reference tag from the output, you will end up with a phantom reference – a reference that appears in the reference list but without any number linking to it. This has been a problem with modules that use <code>pairs()</code> to detect whether to use the arguments from the frame or the parent frame, as those modules automatically process every available argument.
This module solves this problem by allowing access to both frame and parent frame arguments, while still only fetching those arguments when it is necessary. The problem will still occur if you use <code>pairs(args)</code> elsewhere in your module, however.
=== Known limitations ===
The use of metatables also has its downsides. Most of the normal Lua table tools won't work properly on the args table, including the <code>#</code> operator, the <code>next()</code> function, and the functions in the table library. If using these is important for your module, you should use your own argument processing function instead of this module.<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:Lua metamodules]]
}}</includeonly>
== See also ==
* {{tl|Template parameter value}}
<includeonly>{{Sandbox other||
<!-- Categories below this line; interwikis at Wikidata -->
[[Category:Wikipedia utility modules]]
}}</includeonly>
<noinclude>
[[Category:Module documentation pages]]
</noinclude>
9moin48mb5pfedoqc2ffm443pxvp3h9
Tempilet:Terminate sentence
10
1104
9215
2021-11-29T17:59:48Z
en>MusikBot II
0
Protected "[[Template:Terminate sentence]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 9267 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9215
wikitext
text/x-wiki
{{{1}}}{{#if:{{#invoke:text|sentenceTerminated|{{{1|}}}}}||{{{2|.}}}}}<noinclude>{{documentation}}</noinclude>
qn47z9jj1gbam5odtqcnrnt6hqvwhtn
9216
9215
2026-08-23T03:33:21Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Terminate_sentence]]
9215
wikitext
text/x-wiki
{{{1}}}{{#if:{{#invoke:text|sentenceTerminated|{{{1|}}}}}||{{{2|.}}}}}<noinclude>{{documentation}}</noinclude>
qn47z9jj1gbam5odtqcnrnt6hqvwhtn
Module:OutputBuffer
828
1105
9217
2015-12-14T09:30:14Z
en>The Earwig
0
Protected "[[Module:OutputBuffer]]": [[WP:High-risk templates|High-risk Lua module]]: over 10,000 mainspace transclusions ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))
9217
Scribunto
text/plain
return function()
local buffer = {}
return function(sep)
local b = buffer
buffer = {}
return table.concat(b, sep)
end,
function(text)
buffer[#buffer + 1] = text
end,
function(...)
buffer[#buffer + 1] = string.format(...)
end
end
q99uj160az0ttaurr5k4mo7r9ep8nyi
9218
9217
2026-08-23T03:33:21Z
RAPTOR7762
18
1 revision imported from [[:en:Module:OutputBuffer]]
9217
Scribunto
text/plain
return function()
local buffer = {}
return function(sep)
local b = buffer
buffer = {}
return table.concat(b, sep)
end,
function(text)
buffer[#buffer + 1] = text
end,
function(...)
buffer[#buffer + 1] = string.format(...)
end
end
q99uj160az0ttaurr5k4mo7r9ep8nyi
Module:Transclusion count/data/T
828
1106
9219
2026-08-16T05:10:00Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9219
Scribunto
text/plain
return {
["T"] = 324000,
["T1"] = 9000,
["T:TDYK"] = 2700,
["TAFI/Picture_box"] = 2800,
["TBA"] = 6500,
["TCH"] = 2300,
["TCMDb_name"] = 2700,
["TCMDb_title"] = 15000,
["TDMCA"] = 23000,
["TERYT"] = 53000,
["TFAFULL"] = 14000,
["TFAIMAGE"] = 3000,
["TFA_footer"] = 9700,
["TFAfooter"] = 9700,
["TFArecentlist"] = 5400,
["THA"] = 4500,
["TOC_bottom"] = 86000,
["TOC_left"] = 3100,
["TOC_left/styles.css"] = 3100,
["TOC_limit"] = 24000,
["TOC_limit/styles.css"] = 26000,
["TOC_right"] = 51000,
["TOC_right/styles.css"] = 51000,
["TOC_top"] = 86000,
["TOC_top/styles.css"] = 86000,
["TOClimit"] = 3100,
["TOCright"] = 7500,
["TPE"] = 2500,
["TUN"] = 2300,
["TUR"] = 8100,
["TWA/Logo/3"] = 74000,
["TWA/Navigation2"] = 5200,
["TWA_nav_inner_black"] = 38000,
["Tab"] = 6700,
["Tab/Number_of_defined_parameters"] = 6700,
["Tab/styles.css"] = 6700,
["TableTBA"] = 3100,
["Table_alignment"] = 19000,
["Table_alignment/styles.css"] = 19000,
["Tag"] = 7300,
["Talk"] = 4300,
["Talk_Header"] = 5800,
["Talk_archive"] = 45000,
["Talk_archive_navigation"] = 20000,
["Talk_header"] = 845000,
["Talk_header/archivebotparse"] = 115000,
["Talk_header/styles.css"] = 845000,
["Talk_other"] = 4520000,
["Talk_page"] = 8100,
["Talk_page_header"] = 4600,
["Talk_page_of_a_redirect"] = 4200,
["Talk_page_of_redirect"] = 36000,
["Talk_page_stalker"] = 13000,
["Talk_page_watcher"] = 3700,
["Talk_quote"] = 2500,
["Talk_quote_block"] = 22000,
["Talk_quote_block/styles.css"] = 22000,
["Talk_quote_inline"] = 176000,
["Talk_quote_inline/styles.css"] = 176000,
["Talk_quote_inline_with_italics"] = 2800,
["Talk_quote_inline_with_quotes"] = 7300,
["Talkarchive"] = 117000,
["Talkarchivenav"] = 31000,
["Talkback"] = 65000,
["Talkheader"] = 119000,
["Talkpage"] = 6100,
["Talkquote"] = 9200,
["Talkref"] = 3500,
["Talkspace_detect"] = 557000,
["Tallyho"] = 2300,
["Tan"] = 5200,
["Task_force_assessment_category"] = 3100,
["Task_force_assessment_category/core"] = 3100,
["Tasks"] = 938000,
["Taxobox"] = 3400,
["Taxobox/Error_colour"] = 506000,
["Taxobox/core"] = 506000,
["Taxobox/core/styles.css"] = 506000,
["Taxobox/species"] = 200000,
["Taxobox_colour"] = 657000,
["Taxon_author"] = 6300,
["Taxon_info"] = 546000,
["Taxon_italics"] = 395000,
["Taxonbar"] = 503000,
["Taxonbar/candidate"] = 501000,
["Taxonomy"] = 400000,
["Taxonomy/Acalyptratae"] = 6700,
["Taxonomy/Acanthomorpha"] = 17000,
["Taxonomy/Acanthopterygii"] = 17000,
["Taxonomy/Acrididea"] = 2100,
["Taxonomy/Actinomycetes"] = 2600,
["Taxonomy/Actinomycetota"] = 2800,
["Taxonomy/Actinopteri"] = 32000,
["Taxonomy/Actinopterygii"] = 33000,
["Taxonomy/Aculeata"] = 10000,
["Taxonomy/Adephaga"] = 14000,
["Taxonomy/Afrophidia"] = 4500,
["Taxonomy/Agaricales"] = 3600,
["Taxonomy/Agaricomycetes"] = 7200,
["Taxonomy/Agaricomycetidae"] = 4600,
["Taxonomy/Agaricomycotina"] = 7500,
["Taxonomy/Alethinophidia"] = 4700,
["Taxonomy/Allotriocarida"] = 266000,
["Taxonomy/Alphaproteobacteria"] = 2100,
["Taxonomy/Amastigomycota"] = 24000,
["Taxonomy/Ambulacraria"] = 3100,
["Taxonomy/Ammonoidea"] = 2400,
["Taxonomy/Amniota"] = 64000,
["Taxonomy/Amorphea"] = 517000,
["Taxonomy/Amphibia"] = 9100,
["Taxonomy/Amphiesmenoptera"] = 117000,
["Taxonomy/Angiosperms"] = 104000,
["Taxonomy/Animalia"] = 492000,
["Taxonomy/Antennoclypeata"] = 3200,
["Taxonomy/Anthophila"] = 4600,
["Taxonomy/Anthozoa"] = 2200,
["Taxonomy/Antliophora"] = 24000,
["Taxonomy/Anura"] = 7800,
["Taxonomy/Aparaglossata"] = 224000,
["Taxonomy/Apiales"] = 2200,
["Taxonomy/Apo-Chiroptera"] = 2000,
["Taxonomy/Apocrita"] = 14000,
["Taxonomy/Apoditrysia"] = 107000,
["Taxonomy/Apoidea"] = 5200,
["Taxonomy/Arachnida"] = 26000,
["Taxonomy/Arachnopulmonata"] = 19000,
["Taxonomy/Araneae"] = 18000,
["Taxonomy/Araneoidea"] = 3000,
["Taxonomy/Araneomorphae"] = 16000,
["Taxonomy/Archaeplastida"] = 113000,
["Taxonomy/Archelosauria"] = 7200,
["Taxonomy/Archosauria"] = 25000,
["Taxonomy/Archosauria/skip"] = 19000,
["Taxonomy/Archosauriformes"] = 5300,
["Taxonomy/Archosauromorpha"] = 5500,
["Taxonomy/Arctiinae"] = 11000,
["Taxonomy/Arctiini"] = 5200,
["Taxonomy/Arthropoda"] = 307000,
["Taxonomy/Artiodactyla"] = 2700,
["Taxonomy/Artiofabula"] = 2400,
["Taxonomy/Artiopoda"] = 2300,
["Taxonomy/Aschiza"] = 2500,
["Taxonomy/Ascomycota"] = 16000,
["Taxonomy/Asilomorpha"] = 3400,
["Taxonomy/Asparagales"] = 12000,
["Taxonomy/Asteraceae"] = 8600,
["Taxonomy/Asterales"] = 9900,
["Taxonomy/Asterids"] = 31000,
["Taxonomy/Asteroideae"] = 6600,
["Taxonomy/Auchenorrhyncha"] = 4000,
["Taxonomy/Australaves"] = 11000,
["Taxonomy/Avemetatarsalia"] = 5100,
["Taxonomy/Avemetatarsalia/skip"] = 19000,
["Taxonomy/Aves"] = 19000,
["Taxonomy/Avicularioidea"] = 2300,
["Taxonomy/BOP_clade"] = 2300,
["Taxonomy/Bacillati"] = 5700,
["Taxonomy/Bacillota"] = 2300,
["Taxonomy/Bacteria"] = 14000,
["Taxonomy/Basidiomycota"] = 8300,
["Taxonomy/Batrachia"] = 8800,
["Taxonomy/Batrachomorpha"] = 9100,
["Taxonomy/Bilateria"] = 486000,
["Taxonomy/Bivalvia"] = 2800,
["Taxonomy/Bombycoidea"] = 3800,
["Taxonomy/Boreoeutheria"] = 16000,
["Taxonomy/Brachycera"] = 20000,
["Taxonomy/Brachyura"] = 2000,
["Taxonomy/Bromeliaceae"] = 2300,
["Taxonomy/Buccinoidea"] = 2500,
["Taxonomy/CAM"] = 113000,
["Taxonomy/Caelifera"] = 2200,
["Taxonomy/Caenogastropoda"] = 25000,
["Taxonomy/Caenophidia"] = 4300,
["Taxonomy/Caesalpinioideae"] = 2200,
["Taxonomy/Calyptratae"] = 5600,
["Taxonomy/Campanulids"] = 13000,
["Taxonomy/Carabidae"] = 11000,
["Taxonomy/Caraboidea"] = 12000,
["Taxonomy/Carnivoramorpha"] = 2000,
["Taxonomy/Caryophyllales"] = 5600,
["Taxonomy/Cassidinae"] = 3900,
["Taxonomy/Cephalopoda"] = 5000,
["Taxonomy/Cerambycidae"] = 29000,
["Taxonomy/Cerambycinae"] = 6200,
["Taxonomy/Cetruminantia"] = 2200,
["Taxonomy/Chelicerata"] = 27000,
["Taxonomy/Chiroptera"] = 2000,
["Taxonomy/Choanozoa"] = 492000,
["Taxonomy/Chondrichthyes"] = 2700,
["Taxonomy/Chordata"] = 113000,
["Taxonomy/Chrysomelidae"] = 7500,
["Taxonomy/Chrysomeloidea"] = 37000,
["Taxonomy/Cicadomorpha"] = 2800,
["Taxonomy/Cimicomorpha"] = 2200,
["Taxonomy/Clupeocephala"] = 30000,
["Taxonomy/Cnidaria"] = 3800,
["Taxonomy/Coccinellidae"] = 2500,
["Taxonomy/Coccinelloidea"] = 2800,
["Taxonomy/Coelolepida"] = 116000,
["Taxonomy/Coleoptera"] = 82000,
["Taxonomy/Coleopterida"] = 82000,
["Taxonomy/Colubridae"] = 2700,
["Taxonomy/Colubroidea"] = 2700,
["Taxonomy/Colubroides"] = 4300,
["Taxonomy/Commelinids"] = 12000,
["Taxonomy/Conchifera"] = 5200,
["Taxonomy/Condylognatha"] = 12000,
["Taxonomy/Conoidea"] = 7300,
["Taxonomy/Core_eudicots"] = 70000,
["Taxonomy/Cosmopterigidae"] = 2100,
["Taxonomy/Cossoidea"] = 2800,
["Taxonomy/Crambidae"] = 12000,
["Taxonomy/Crambinae"] = 2300,
["Taxonomy/Crocopoda"] = 5400,
["Taxonomy/Ctenosquamata"] = 18000,
["Taxonomy/Cucujiformia"] = 49000,
["Taxonomy/Curculionidae"] = 3200,
["Taxonomy/Curculionoidea"] = 3900,
["Taxonomy/Cyclorrhapha"] = 12000,
["Taxonomy/Cyperaceae"] = 2500,
["Taxonomy/Cypriniformes"] = 5100,
["Taxonomy/Cypriniphysi"] = 5100,
["Taxonomy/Cyprinoidei"] = 3900,
["Taxonomy/Decapoda"] = 4300,
["Taxonomy/Dendrobiinae"] = 2100,
["Taxonomy/Depressariidae"] = 3100,
["Taxonomy/Deuteropoda"] = 306000,
["Taxonomy/Deuterostomia"] = 116000,
["Taxonomy/Diaphoretickes"] = 117000,
["Taxonomy/Diaphoretickes/showdomain"] = 5100,
["Taxonomy/Dicondylia"] = 263000,
["Taxonomy/Dictyoptera"] = 2400,
["Taxonomy/Dikarya"] = 24000,
["Taxonomy/Dinosauria"] = 4300,
["Taxonomy/Dinosauria/skip"] = 19000,
["Taxonomy/Dinosauromorpha"] = 4300,
["Taxonomy/Diptera"] = 24000,
["Taxonomy/Ditrysia"] = 113000,
["Taxonomy/Doryloformicia"] = 2900,
["Taxonomy/Dothideomyceta"] = 9700,
["Taxonomy/Dothideomycetes"] = 2700,
["Taxonomy/Ecdysozoa"] = 309000,
["Taxonomy/Echinodermata"] = 2800,
["Taxonomy/Elasmobranchii"] = 2200,
["Taxonomy/Elateriformia"] = 3800,
["Taxonomy/Elementaves"] = 2100,
["Taxonomy/Elpistostegalia"] = 74000,
["Taxonomy/Embryophytes"] = 110000,
["Taxonomy/Embryophytes/Plantae"] = 110000,
["Taxonomy/Ennominae"] = 2700,
["Taxonomy/Ensifera"] = 2200,
["Taxonomy/Entelegynae"] = 8100,
["Taxonomy/Eotetrapodiformes"] = 74000,
["Taxonomy/Epidendroideae"] = 5500,
["Taxonomy/Erebidae"] = 17000,
["Taxonomy/Eremoneura"] = 12000,
["Taxonomy/Ericales"] = 4200,
["Taxonomy/Euarchontoglires"] = 6300,
["Taxonomy/Eucarida"] = 4400,
["Taxonomy/Eucrocopoda"] = 5200,
["Taxonomy/Eudicots"] = 74000,
["Taxonomy/Eufalconimorphae"] = 11000,
["Taxonomy/Euformicia"] = 3200,
["Taxonomy/Eugnathostomata"] = 111000,
["Taxonomy/Eukaryota"] = 635000,
["Taxonomy/Eukaryota/displayed"] = 6400,
["Taxonomy/Eulepidoptera"] = 114000,
["Taxonomy/Eumalacostraca"] = 6900,
["Taxonomy/Eumetabola"] = 250000,
["Taxonomy/Eumetazoa"] = 490000,
["Taxonomy/Eupasseres"] = 9800,
["Taxonomy/Eupercaria"] = 5700,
["Taxonomy/Euphyllophytes"] = 2000,
["Taxonomy/Eupitheciini"] = 2000,
["Taxonomy/Eupulmonata"] = 6300,
["Taxonomy/Eurypterygii"] = 18000,
["Taxonomy/Euselachii"] = 2300,
["Taxonomy/Euteleostei"] = 19000,
["Taxonomy/Eutheria"] = 17000,
["Taxonomy/Euthyneura"] = 13000,
["Taxonomy/Euungulata"] = 4000,
["Taxonomy/Fabaceae"] = 6800,
["Taxonomy/Fabales"] = 7100,
["Taxonomy/Fabids"] = 18000,
["Taxonomy/Faboideae"] = 4000,
["Taxonomy/Ferae"] = 2400,
["Taxonomy/Ferungulata"] = 6400,
["Taxonomy/Filozoa"] = 492000,
["Taxonomy/Formicidae"] = 3300,
["Taxonomy/Formicoidea"] = 3300,
["Taxonomy/Fungi"] = 25000,
["Taxonomy/Gamasina"] = 2300,
["Taxonomy/Gammaproteobacteria"] = 2000,
["Taxonomy/Gastropoda"] = 44000,
["Taxonomy/Gekkonoidea"] = 2200,
["Taxonomy/Gekkonomorpha"] = 2600,
["Taxonomy/Gekkota"] = 2600,
["Taxonomy/Gelechiidae"] = 6100,
["Taxonomy/Gelechiinae"] = 3000,
["Taxonomy/Gelechioidea"] = 19000,
["Taxonomy/Gentianales"] = 5000,
["Taxonomy/Geometridae"] = 11000,
["Taxonomy/Geometroidea"] = 11000,
["Taxonomy/Glires"] = 4600,
["Taxonomy/Gliriformes"] = 4600,
["Taxonomy/Glossata"] = 116000,
["Taxonomy/Gnathostomata"] = 111000,
["Taxonomy/Gracillariidae"] = 2200,
["Taxonomy/Gracillarioidea"] = 2500,
["Taxonomy/Graminid_clade"] = 4100,
["Taxonomy/Halvaria"] = 3000,
["Taxonomy/Helicina_(suborder)"] = 5500,
["Taxonomy/Hemiptera"] = 10000,
["Taxonomy/Hesperiidae"] = 2700,
["Taxonomy/Heterobranchia"] = 13000,
["Taxonomy/Heteroneura"] = 115000,
["Taxonomy/Heteroptera"] = 5100,
["Taxonomy/Hexapoda"] = 265000,
["Taxonomy/Holometabola"] = 238000,
["Taxonomy/Holomycota"] = 25000,
["Taxonomy/Holozoa"] = 492000,
["Taxonomy/Hyloidea"] = 3600,
["Taxonomy/Hymenoptera"] = 14000,
["Taxonomy/Hymenopterida"] = 14000,
["Taxonomy/Iguania"] = 2500,
["Taxonomy/Iguanomorpha"] = 2500,
["Taxonomy/Insecta"] = 263000,
["Taxonomy/Lamiales"] = 6900,
["Taxonomy/Lamiids"] = 14000,
["Taxonomy/Lamiinae"] = 21000,
["Taxonomy/Larentiinae"] = 3700,
["Taxonomy/Laurasiatheria"] = 9200,
["Taxonomy/Lecanoromycetes"] = 4700,
["Taxonomy/Lecanoromycetidae"] = 3200,
["Taxonomy/Leotiomyceta"] = 14000,
["Taxonomy/Lepidoptera"] = 116000,
["Taxonomy/Lepidosauria"] = 15000,
["Taxonomy/Lepidosauromorpha"] = 15000,
["Taxonomy/Life"] = 653000,
["Taxonomy/Linyphiidae"] = 2100,
["Taxonomy/Lissamphibia"] = 9100,
["Taxonomy/Lithosiini"] = 3600,
["Taxonomy/Littorinimorpha"] = 5800,
["Taxonomy/Lophotrochozoa"] = 57000,
["Taxonomy/Lycaenidae"] = 4100,
["Taxonomy/Macroheterocera"] = 43000,
["Taxonomy/Magnoliids"] = 2900,
["Taxonomy/Malacostraca"] = 7100,
["Taxonomy/Malaxideae"] = 2200,
["Taxonomy/Malpighiales"] = 4900,
["Taxonomy/Malvales"] = 2700,
["Taxonomy/Malvids"] = 13000,
["Taxonomy/Mammalia"] = 19000,
["Taxonomy/Mammalia/skip"] = 19000,
["Taxonomy/Mandibulata"] = 277000,
["Taxonomy/Melolonthinae"] = 3000,
["Taxonomy/Meso-Papilionoideae"] = 3800,
["Taxonomy/Mesostigmata"] = 2800,
["Taxonomy/Mollusca"] = 52000,
["Taxonomy/Monocots"] = 27000,
["Taxonomy/Monogynaspida"] = 2500,
["Taxonomy/Multicrustacea"] = 8700,
["Taxonomy/Muricidae"] = 2200,
["Taxonomy/Muricoidea"] = 2200,
["Taxonomy/Muroidea"] = 2600,
["Taxonomy/Muscomorpha"] = 15000,
["Taxonomy/Mygalomorphae"] = 2400,
["Taxonomy/Myoglossata"] = 116000,
["Taxonomy/Myomorpha"] = 2700,
["Taxonomy/Myriapoda"] = 2400,
["Taxonomy/Myrtaceae"] = 3100,
["Taxonomy/Myrtales"] = 4600,
["Taxonomy/Myrtoideae"] = 3100,
["Taxonomy/Nematocera"] = 3300,
["Taxonomy/Neoaves"] = 17000,
["Taxonomy/Neobatrachia"] = 6800,
["Taxonomy/Neocephalopoda"] = 3900,
["Taxonomy/Neodiapsida"] = 24000,
["Taxonomy/Neogastropoda"] = 16000,
["Taxonomy/Neognathae"] = 18000,
["Taxonomy/Neolepidoptera"] = 116000,
["Taxonomy/Neoptera"] = 259000,
["Taxonomy/Neopterygii"] = 32000,
["Taxonomy/Neoreptilia"] = 25000,
["Taxonomy/Neoteleostei"] = 18000,
["Taxonomy/Nephrozoa"] = 485000,
["Taxonomy/Neuropteroidea"] = 83000,
["Taxonomy/Noctuidae"] = 8400,
["Taxonomy/Noctuinae"] = 2800,
["Taxonomy/Noctuoidea"] = 27000,
["Taxonomy/Non-protein_amino_acid-accumulating_clade"] = 2700,
["Taxonomy/Nudibranchia"] = 2700,
["Taxonomy/Nudipleura"] = 2700,
["Taxonomy/Nymphalidae"] = 4300,
["Taxonomy/Obazoa"] = 517000,
["Taxonomy/Obtectomera"] = 73000,
["Taxonomy/Odonata"] = 3100,
["Taxonomy/Odonatoptera"] = 3100,
["Taxonomy/Oestroidea"] = 5000,
["Taxonomy/Olfactores"] = 112000,
["Taxonomy/Ophidia"] = 5200,
["Taxonomy/Opisthokonta"] = 517000,
["Taxonomy/Opisthothelae"] = 18000,
["Taxonomy/Orchidaceae"] = 8100,
["Taxonomy/Orchidoideae"] = 2300,
["Taxonomy/Ornithodira"] = 5000,
["Taxonomy/Ornithurae"] = 19000,
["Taxonomy/Ornithurae/skip"] = 19000,
["Taxonomy/Orthoptera"] = 4400,
["Taxonomy/Ostariophysi"] = 10000,
["Taxonomy/Osteichthyes"] = 108000,
["Taxonomy/Otocephala"] = 11000,
["Taxonomy/Otophysi"] = 10000,
["Taxonomy/Ovalentaria"] = 5000,
["Taxonomy/Palaeoptera"] = 3800,
["Taxonomy/Pan-Carnivora"] = 2200,
["Taxonomy/Pan-Euteleostei"] = 19000,
["Taxonomy/Pan-Euungulata"] = 4100,
["Taxonomy/Panarthropoda"] = 307000,
["Taxonomy/Pancrustacea"] = 275000,
["Taxonomy/Panorpida"] = 141000,
["Taxonomy/Panpulmonata"] = 8600,
["Taxonomy/Pantetrapulmonata"] = 19000,
["Taxonomy/Papilionoidea"] = 13000,
["Taxonomy/ParaHoxozoa"] = 490000,
["Taxonomy/Parapleurota"] = 25000,
["Taxonomy/Parasitiformes"] = 3100,
["Taxonomy/Paraxonia"] = 2800,
["Taxonomy/Passerea"] = 13000,
["Taxonomy/Passeri"] = 7800,
["Taxonomy/Passerida"] = 3500,
["Taxonomy/Passerides"] = 5900,
["Taxonomy/Passeriformes"] = 9800,
["Taxonomy/Pentatomomorpha"] = 2300,
["Taxonomy/Peracarida"] = 2500,
["Taxonomy/Perciformes"] = 2800,
["Taxonomy/Percomorpha"] = 16000,
["Taxonomy/Pezizomycotina"] = 15000,
["Taxonomy/Phycitinae"] = 2600,
["Taxonomy/Phytophaga"] = 41000,
["Taxonomy/Placentalia"] = 17000,
["Taxonomy/Plantae"] = 112000,
["Taxonomy/Planulozoa"] = 3800,
["Taxonomy/Platyhelminthes"] = 2700,
["Taxonomy/Pleocyemata"] = 4100,
["Taxonomy/Poaceae"] = 4100,
["Taxonomy/Poales"] = 9400,
["Taxonomy/Podiata"] = 517000,
["Taxonomy/Polyneoptera"] = 8600,
["Taxonomy/Polyphaga"] = 68000,
["Taxonomy/Polypodiophyta"] = 2000,
["Taxonomy/Polypodiopsida"] = 2000,
["Taxonomy/Polysporangiophytes"] = 108000,
["Taxonomy/Polysporangiophytes/Plantae"] = 108000,
["Taxonomy/Proteales"] = 2000,
["Taxonomy/Protostomia"] = 370000,
["Taxonomy/Pseudomonadati"] = 8100,
["Taxonomy/Pseudomonadota"] = 5000,
["Taxonomy/Psittacopasseres"] = 11000,
["Taxonomy/Pteropliini"] = 2300,
["Taxonomy/Pterygota"] = 263000,
["Taxonomy/Pyralidae"] = 4500,
["Taxonomy/Pyraloidea"] = 16000,
["Taxonomy/Pyramidellidae"] = 2200,
["Taxonomy/Pyramidelloidea"] = 2200,
["Taxonomy/RTA_clade"] = 4400,
["Taxonomy/Ranoidea"] = 2900,
["Taxonomy/Reptantia"] = 3400,
["Taxonomy/Reptiliomorpha"] = 64000,
["Taxonomy/Rhabditophora"] = 2700,
["Taxonomy/Rhipidistia"] = 75000,
["Taxonomy/Ringipleura"] = 2800,
["Taxonomy/Rodentia"] = 4400,
["Taxonomy/Rosales"] = 3300,
["Taxonomy/Rosids"] = 31000,
["Taxonomy/Rouphozoa"] = 2800,
["Taxonomy/Rubiaceae"] = 2600,
["Taxonomy/Saccharomyceta"] = 15000,
["Taxonomy/Salientia"] = 7800,
["Taxonomy/Salticidae"] = 2900,
["Taxonomy/Salticinae"] = 2600,
["Taxonomy/Sapindales"] = 3300,
["Taxonomy/Sar"] = 4000,
["Taxonomy/Sarcopterygii"] = 75000,
["Taxonomy/Sauria"] = 23000,
["Taxonomy/Saurischia"] = 2900,
["Taxonomy/Sauropsida"] = 43000,
["Taxonomy/Scarabaeidae"] = 10000,
["Taxonomy/Scarabaeiformia"] = 11000,
["Taxonomy/Scarabaeoidea"] = 11000,
["Taxonomy/Schizophora"] = 12000,
["Taxonomy/Scincidae"] = 2100,
["Taxonomy/Scincomorpha"] = 2400,
["Taxonomy/Scrotifera"] = 8400,
["Taxonomy/Sericinae"] = 3900,
["Taxonomy/Sericini"] = 3600,
["Taxonomy/Serpentes"] = 5200,
["Taxonomy/Setaphyta"] = 2100,
["Taxonomy/Siluriformes"] = 3600,
["Taxonomy/Simplicidentata"] = 4400,
["Taxonomy/Sordariomyceta"] = 4600,
["Taxonomy/Sordariomycetes"] = 2900,
["Taxonomy/Spermatophyta"] = 105000,
["Taxonomy/Spermatophytes/Plantae"] = 105000,
["Taxonomy/Spilomelinae"] = 4300,
["Taxonomy/Spiralia"] = 60000,
["Taxonomy/Squamata"] = 15000,
["Taxonomy/Staphyliniformia"] = 3000,
["Taxonomy/Staphylinoidea"] = 2200,
["Taxonomy/Stegocephali"] = 74000,
["Taxonomy/Stylommatophora"] = 6000,
["Taxonomy/Superasterids"] = 38000,
["Taxonomy/Superrosids"] = 32000,
["Taxonomy/Syrphidae"] = 2100,
["Taxonomy/Syrphoidea"] = 2300,
["Taxonomy/TSAR"] = 4000,
["Taxonomy/Tachinidae"] = 4400,
["Taxonomy/Tectipleura"] = 9800,
["Taxonomy/Teleocephala"] = 30000,
["Taxonomy/Teleostei"] = 32000,
["Taxonomy/Teleosteomorpha"] = 32000,
["Taxonomy/Telluraves"] = 13000,
["Taxonomy/Tenebrionoidea"] = 3400,
["Taxonomy/Tephritidae"] = 3300,
["Taxonomy/Tephritinae"] = 2400,
["Taxonomy/Tephritoidea"] = 4300,
["Taxonomy/Tetrapoda"] = 74000,
["Taxonomy/Tetrapodomorpha"] = 74000,
["Taxonomy/Tetrapulmonata"] = 19000,
["Taxonomy/Theria"] = 18000,
["Taxonomy/Theria/skip"] = 18000,
["Taxonomy/Theropoda/skip"] = 19000,
["Taxonomy/Tortricidae"] = 8500,
["Taxonomy/Tortricinae"] = 5900,
["Taxonomy/Tortricoidea"] = 8500,
["Taxonomy/Toxicofera"] = 8400,
["Taxonomy/Tracheophyta"] = 108000,
["Taxonomy/Tracheophytes/Plantae"] = 108000,
["Taxonomy/Trilobita"] = 2200,
["Taxonomy/Trilobitomorpha"] = 2300,
["Taxonomy/Trochida"] = 2800,
["Taxonomy/Trochoidea"] = 2800,
["Taxonomy/Tyranni"] = 2000,
["Taxonomy/Unicalcarida"] = 14000,
["Taxonomy/Vertebrata"] = 112000,
["Taxonomy/Vetigastropoda"] = 4900,
["Taxonomy/Virus"] = 2900,
["Taxonomy/crown_Formicidae"] = 3200,
["Taxonomy_key"] = 150000,
["Taxonomy_preload"] = 150000,
["Tb"] = 13000,
["Team_roster_navbox"] = 34000,
["Technical"] = 4100,
["Technically_indistinguishable"] = 2500,
["Television_debuts_endings_antonym"] = 7200,
["Television_episode_redirect_handler"] = 24000,
["Television_episode_short_description"] = 13000,
["Template"] = 4700,
["Template-Class"] = 14000,
["TemplateData_header"] = 18000,
["Template_category"] = 36000,
["Template_display"] = 57000,
["Template_for_discussion/dated"] = 16000,
["Template_for_discussion/styles.css"] = 33000,
["Template_for_merging/dated"] = 17000,
["Template_link"] = 7550000,
["Template_link_code"] = 1160000,
["Template_link_code_with_subst"] = 20000,
["Template_link_expanded"] = 2620000,
["Template_link_expanded_with_subst"] = 5000,
["Template_link_general"] = 24000,
["Template_link_interwiki"] = 9000,
["Template_link_null"] = 9200,
["Template_link_universal"] = 12000,
["Template_link_with_alternate_text"] = 2200,
["Template_link_with_link_off"] = 9800,
["Template_link_with_linked_braces"] = 8200,
["Template_link_with_parameters"] = 70000,
["Template_link_with_subst"] = 54000,
["Template_links"] = 2500,
["Template_other"] = 4970000,
["Template_parameter_usage"] = 20000,
["Template_parameter_value"] = 51000,
["Template_rating"] = 2600,
["Template_reference_list"] = 7400,
["Template_sandbox_notice"] = 6500,
["Template_shortcut"] = 6500,
["TennisEventInfo"] = 6800,
["TennisEvents"] = 2200,
["Tennis_events"] = 13000,
["Tennis_icon"] = 2800,
["Tennis_icon2"] = 2800,
["Tennis_record"] = 3000,
["Terminate_sentence"] = 53000,
["Testcases_notice"] = 5100,
["Text_diff"] = 3500,
["Tfd_links"] = 6800,
["Th/abp"] = 115000,
["Thank"] = 2400,
["Thank_you"] = 5400,
["The_edit-summary_field"] = 8900,
["The_edit-summary_field/OOUI"] = 2400,
["Their"] = 15000,
["They"] = 11000,
["They_have"] = 39000,
["Thin_space"] = 29000,
["Thinsp"] = 26000,
["Third-party"] = 6700,
["Thirteen_Colonies_article_name"] = 2100,
["This_is_a_new_user"] = 7000,
["Thursday"] = 2800,
["Tick"] = 81000,
["Ticket_confirmation"] = 3200,
["Time"] = 2800,
["Time_ago"] = 185000,
["Time_signature"] = 3300,
["Time_with_time_zone_link"] = 4300,
["Title_case"] = 5800,
["Title_century"] = 31000,
["Title_country"] = 42000,
["Title_decade"] = 31000,
["Title_demonym"] = 39000,
["Title_disambig_text"] = 251000,
["Title_language"] = 2600,
["Title_monthname"] = 41000,
["Title_number"] = 4400,
["Title_year"] = 264000,
["Title_year+1"] = 14000,
["Title_year-1"] = 3900,
["Title_year2range"] = 7900,
["Title_year2range-1"] = 6400,
["Title_year_range"] = 13000,
["Tl"] = 7260000,
["Tl2"] = 8900,
["Tlc"] = 907000,
["Tld"] = 252000,
["Tlf"] = 9700,
["Tlg"] = 22000,
["Tlit"] = 3200,
["Tlp"] = 70000,
["Tls"] = 52000,
["Tlsc"] = 20000,
["Tlsp"] = 2300,
["Tlu"] = 12000,
["Tlx"] = 2620000,
["Tlxs"] = 3400,
["Tmbox"] = 2400000,
["Tmpv"] = 50000,
["Tn"] = 8200,
["Tnull"] = 9000,
["To"] = 3000,
["To_USD"] = 2500,
["To_USD/CurrencyCheck"] = 2500,
["To_USD/General"] = 2200,
["To_be_announced"] = 7200,
["To_do"] = 7700,
["Toc_right"] = 2100,
["Tocright"] = 7300,
["Todo"] = 2700,
["Tomorrow"] = 7200,
["Tone"] = 7700,
["Tone-cmn"] = 2800,
["Toolbar"] = 349000,
["Toolforge"] = 12000,
["Tooltip"] = 563000,
["Tooltip/styles.css"] = 563000,
["Top-Class"] = 15000,
["Top-importance"] = 15000,
["Top_25_Report"] = 3900,
["Top_25_report"] = 6000,
["Top_icon"] = 84000,
["Totd"] = 4300,
["Totd_nav"] = 5400,
["Tp"] = 2600,
["Tpq"] = 3900,
["Tpr"] = 2900,
["Tps"] = 12000,
["Tpw"] = 3600,
["Tq"] = 171000,
["Tq2"] = 5600,
["Tqb"] = 5300,
["Tqq"] = 7300,
["Tquote"] = 2200,
["Track_gauge"] = 26000,
["Track_listing"] = 123000,
["Tracking_category"] = 5200,
["Tracklist"] = 16000,
["Trademark"] = 7800,
["Trademarked"] = 4300,
["Transclude"] = 18000,
["Transclude_lead_excerpt"] = 3600,
["Transcluded_section"] = 4700,
["Transclusionless"] = 5000,
["Translated"] = 25000,
["Translated_page"] = 114000,
["Translation"] = 20000,
["Translation/Base"] = 2400,
["Translation/Information"] = 2100,
["Translation/Summary"] = 2100,
["Transliteration"] = 69000,
["Tree_chart"] = 8400,
["Tree_chart/end"] = 8400,
["Tree_chart/start"] = 8400,
["Tree_list"] = 25000,
["Tree_list/end"] = 25000,
["Tree_list/styles.css"] = 25000,
["Trim"] = 2980000,
["Trim_%"] = 6700,
["Trim_brackets"] = 3600,
["Trim_leading"] = 2100,
["Trim_quotes"] = 26000,
["Trout"] = 2200,
["Tsh"] = 3300,
["Tsp"] = 2200,
["Tuesday"] = 2800,
["TuttoCalciatori"] = 2200,
["Twitter"] = 16000,
["Two-digit_year"] = 6000,
["TwoLegResult"] = 5800,
["TwoLegStart"] = 4600,
["TwoLeg_start"] = 5800,
["Module:TNT"] = 10000,
["Module:TableTools"] = 9590000,
["Module:Table_empty_cell"] = 33000,
["Module:Taxobox_ranks"] = 656000,
["Module:TaxonItalics"] = 655000,
["Module:TaxonList"] = 28000,
["Module:Taxonbar"] = 503000,
["Module:Taxonbar/candidate"] = 501000,
["Module:Taxonbar/conf"] = 503000,
["Module:Taxonbar/exists"] = 501000,
["Module:Taxonbar/whitelist"] = 503000,
["Module:Team_appearances_list"] = 17000,
["Module:Team_appearances_list/data"] = 17000,
["Module:Team_bracket"] = 55000,
["Module:Team_bracket_tracking"] = 3700,
["Module:Team_roster_navbox"] = 35000,
["Module:Television_episode_redirect_handler"] = 24000,
["Module:Television_episode_short_description"] = 35000,
["Module:Television_infoboxes_disambiguation_check"] = 72000,
["Module:TemplatePar"] = 33000,
["Module:TemplateStyles"] = 598000,
["Module:Template_invocation"] = 3200,
["Module:Template_link_general"] = 3780000,
["Module:Template_parameter_value"] = 12100000,
["Module:Template_redirect_regex"] = 1460000,
["Module:Template_test_case"] = 3300,
["Module:Template_test_case/config"] = 3300,
["Module:Template_test_case/data"] = 3300,
["Module:Template_wrapper"] = 1040000,
["Module:Tennis_events_nav"] = 22000,
["Module:Text"] = 2060000,
["Module:Text/data"] = 53000,
["Module:Tfd_links"] = 6800,
["Module:Time"] = 4500,
["Module:Time/data"] = 4500,
["Module:Time_ago"] = 192000,
["Module:Title_monthname"] = 41000,
["Module:Toolbar"] = 1510000,
["Module:Top_25_report"] = 5900,
["Module:Track_gauge"] = 26000,
["Module:Track_gauge/data"] = 26000,
["Module:Track_listing"] = 123000,
["Module:Track_listing/configuration"] = 123000,
["Module:Track_listing/styles.css"] = 123000,
["Module:Transclusion_count"] = 64000,
["Module:Transclusion_count/data/A"] = 3700,
["Module:Transclusion_count/data/B"] = 2800,
["Module:Transclusion_count/data/C"] = 12000,
["Module:Transclusion_count/data/E"] = 2400,
["Module:Transclusion_count/data/G"] = 2000,
["Module:Transclusion_count/data/I"] = 3300,
["Module:Transclusion_count/data/L"] = 2000,
["Module:Transclusion_count/data/M"] = 3200,
["Module:Transclusion_count/data/N"] = 2800,
["Module:Transclusion_count/data/P"] = 2900,
["Module:Transclusion_count/data/S"] = 5000,
["Module:Transclusion_count/data/T"] = 2600,
["Module:Transclusion_count/data/U"] = 2600,
["Module:Transclusion_count/data/W"] = 3700,
["Module:Transclusion_count/data/other"] = 2200,
["Module:Tree_chart"] = 8400,
["Module:Tree_chart/data"] = 8400,
["Module:Trim_quotes"] = 68000,
["Module:TwitterSnowflake"] = 48000,
["Module:Type_in_location"] = 137000,
}
l4mwzmswz8sixynecilawrvwyezxpa4
9220
9219
2026-08-23T03:33:21Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/T]]
9219
Scribunto
text/plain
return {
["T"] = 324000,
["T1"] = 9000,
["T:TDYK"] = 2700,
["TAFI/Picture_box"] = 2800,
["TBA"] = 6500,
["TCH"] = 2300,
["TCMDb_name"] = 2700,
["TCMDb_title"] = 15000,
["TDMCA"] = 23000,
["TERYT"] = 53000,
["TFAFULL"] = 14000,
["TFAIMAGE"] = 3000,
["TFA_footer"] = 9700,
["TFAfooter"] = 9700,
["TFArecentlist"] = 5400,
["THA"] = 4500,
["TOC_bottom"] = 86000,
["TOC_left"] = 3100,
["TOC_left/styles.css"] = 3100,
["TOC_limit"] = 24000,
["TOC_limit/styles.css"] = 26000,
["TOC_right"] = 51000,
["TOC_right/styles.css"] = 51000,
["TOC_top"] = 86000,
["TOC_top/styles.css"] = 86000,
["TOClimit"] = 3100,
["TOCright"] = 7500,
["TPE"] = 2500,
["TUN"] = 2300,
["TUR"] = 8100,
["TWA/Logo/3"] = 74000,
["TWA/Navigation2"] = 5200,
["TWA_nav_inner_black"] = 38000,
["Tab"] = 6700,
["Tab/Number_of_defined_parameters"] = 6700,
["Tab/styles.css"] = 6700,
["TableTBA"] = 3100,
["Table_alignment"] = 19000,
["Table_alignment/styles.css"] = 19000,
["Tag"] = 7300,
["Talk"] = 4300,
["Talk_Header"] = 5800,
["Talk_archive"] = 45000,
["Talk_archive_navigation"] = 20000,
["Talk_header"] = 845000,
["Talk_header/archivebotparse"] = 115000,
["Talk_header/styles.css"] = 845000,
["Talk_other"] = 4520000,
["Talk_page"] = 8100,
["Talk_page_header"] = 4600,
["Talk_page_of_a_redirect"] = 4200,
["Talk_page_of_redirect"] = 36000,
["Talk_page_stalker"] = 13000,
["Talk_page_watcher"] = 3700,
["Talk_quote"] = 2500,
["Talk_quote_block"] = 22000,
["Talk_quote_block/styles.css"] = 22000,
["Talk_quote_inline"] = 176000,
["Talk_quote_inline/styles.css"] = 176000,
["Talk_quote_inline_with_italics"] = 2800,
["Talk_quote_inline_with_quotes"] = 7300,
["Talkarchive"] = 117000,
["Talkarchivenav"] = 31000,
["Talkback"] = 65000,
["Talkheader"] = 119000,
["Talkpage"] = 6100,
["Talkquote"] = 9200,
["Talkref"] = 3500,
["Talkspace_detect"] = 557000,
["Tallyho"] = 2300,
["Tan"] = 5200,
["Task_force_assessment_category"] = 3100,
["Task_force_assessment_category/core"] = 3100,
["Tasks"] = 938000,
["Taxobox"] = 3400,
["Taxobox/Error_colour"] = 506000,
["Taxobox/core"] = 506000,
["Taxobox/core/styles.css"] = 506000,
["Taxobox/species"] = 200000,
["Taxobox_colour"] = 657000,
["Taxon_author"] = 6300,
["Taxon_info"] = 546000,
["Taxon_italics"] = 395000,
["Taxonbar"] = 503000,
["Taxonbar/candidate"] = 501000,
["Taxonomy"] = 400000,
["Taxonomy/Acalyptratae"] = 6700,
["Taxonomy/Acanthomorpha"] = 17000,
["Taxonomy/Acanthopterygii"] = 17000,
["Taxonomy/Acrididea"] = 2100,
["Taxonomy/Actinomycetes"] = 2600,
["Taxonomy/Actinomycetota"] = 2800,
["Taxonomy/Actinopteri"] = 32000,
["Taxonomy/Actinopterygii"] = 33000,
["Taxonomy/Aculeata"] = 10000,
["Taxonomy/Adephaga"] = 14000,
["Taxonomy/Afrophidia"] = 4500,
["Taxonomy/Agaricales"] = 3600,
["Taxonomy/Agaricomycetes"] = 7200,
["Taxonomy/Agaricomycetidae"] = 4600,
["Taxonomy/Agaricomycotina"] = 7500,
["Taxonomy/Alethinophidia"] = 4700,
["Taxonomy/Allotriocarida"] = 266000,
["Taxonomy/Alphaproteobacteria"] = 2100,
["Taxonomy/Amastigomycota"] = 24000,
["Taxonomy/Ambulacraria"] = 3100,
["Taxonomy/Ammonoidea"] = 2400,
["Taxonomy/Amniota"] = 64000,
["Taxonomy/Amorphea"] = 517000,
["Taxonomy/Amphibia"] = 9100,
["Taxonomy/Amphiesmenoptera"] = 117000,
["Taxonomy/Angiosperms"] = 104000,
["Taxonomy/Animalia"] = 492000,
["Taxonomy/Antennoclypeata"] = 3200,
["Taxonomy/Anthophila"] = 4600,
["Taxonomy/Anthozoa"] = 2200,
["Taxonomy/Antliophora"] = 24000,
["Taxonomy/Anura"] = 7800,
["Taxonomy/Aparaglossata"] = 224000,
["Taxonomy/Apiales"] = 2200,
["Taxonomy/Apo-Chiroptera"] = 2000,
["Taxonomy/Apocrita"] = 14000,
["Taxonomy/Apoditrysia"] = 107000,
["Taxonomy/Apoidea"] = 5200,
["Taxonomy/Arachnida"] = 26000,
["Taxonomy/Arachnopulmonata"] = 19000,
["Taxonomy/Araneae"] = 18000,
["Taxonomy/Araneoidea"] = 3000,
["Taxonomy/Araneomorphae"] = 16000,
["Taxonomy/Archaeplastida"] = 113000,
["Taxonomy/Archelosauria"] = 7200,
["Taxonomy/Archosauria"] = 25000,
["Taxonomy/Archosauria/skip"] = 19000,
["Taxonomy/Archosauriformes"] = 5300,
["Taxonomy/Archosauromorpha"] = 5500,
["Taxonomy/Arctiinae"] = 11000,
["Taxonomy/Arctiini"] = 5200,
["Taxonomy/Arthropoda"] = 307000,
["Taxonomy/Artiodactyla"] = 2700,
["Taxonomy/Artiofabula"] = 2400,
["Taxonomy/Artiopoda"] = 2300,
["Taxonomy/Aschiza"] = 2500,
["Taxonomy/Ascomycota"] = 16000,
["Taxonomy/Asilomorpha"] = 3400,
["Taxonomy/Asparagales"] = 12000,
["Taxonomy/Asteraceae"] = 8600,
["Taxonomy/Asterales"] = 9900,
["Taxonomy/Asterids"] = 31000,
["Taxonomy/Asteroideae"] = 6600,
["Taxonomy/Auchenorrhyncha"] = 4000,
["Taxonomy/Australaves"] = 11000,
["Taxonomy/Avemetatarsalia"] = 5100,
["Taxonomy/Avemetatarsalia/skip"] = 19000,
["Taxonomy/Aves"] = 19000,
["Taxonomy/Avicularioidea"] = 2300,
["Taxonomy/BOP_clade"] = 2300,
["Taxonomy/Bacillati"] = 5700,
["Taxonomy/Bacillota"] = 2300,
["Taxonomy/Bacteria"] = 14000,
["Taxonomy/Basidiomycota"] = 8300,
["Taxonomy/Batrachia"] = 8800,
["Taxonomy/Batrachomorpha"] = 9100,
["Taxonomy/Bilateria"] = 486000,
["Taxonomy/Bivalvia"] = 2800,
["Taxonomy/Bombycoidea"] = 3800,
["Taxonomy/Boreoeutheria"] = 16000,
["Taxonomy/Brachycera"] = 20000,
["Taxonomy/Brachyura"] = 2000,
["Taxonomy/Bromeliaceae"] = 2300,
["Taxonomy/Buccinoidea"] = 2500,
["Taxonomy/CAM"] = 113000,
["Taxonomy/Caelifera"] = 2200,
["Taxonomy/Caenogastropoda"] = 25000,
["Taxonomy/Caenophidia"] = 4300,
["Taxonomy/Caesalpinioideae"] = 2200,
["Taxonomy/Calyptratae"] = 5600,
["Taxonomy/Campanulids"] = 13000,
["Taxonomy/Carabidae"] = 11000,
["Taxonomy/Caraboidea"] = 12000,
["Taxonomy/Carnivoramorpha"] = 2000,
["Taxonomy/Caryophyllales"] = 5600,
["Taxonomy/Cassidinae"] = 3900,
["Taxonomy/Cephalopoda"] = 5000,
["Taxonomy/Cerambycidae"] = 29000,
["Taxonomy/Cerambycinae"] = 6200,
["Taxonomy/Cetruminantia"] = 2200,
["Taxonomy/Chelicerata"] = 27000,
["Taxonomy/Chiroptera"] = 2000,
["Taxonomy/Choanozoa"] = 492000,
["Taxonomy/Chondrichthyes"] = 2700,
["Taxonomy/Chordata"] = 113000,
["Taxonomy/Chrysomelidae"] = 7500,
["Taxonomy/Chrysomeloidea"] = 37000,
["Taxonomy/Cicadomorpha"] = 2800,
["Taxonomy/Cimicomorpha"] = 2200,
["Taxonomy/Clupeocephala"] = 30000,
["Taxonomy/Cnidaria"] = 3800,
["Taxonomy/Coccinellidae"] = 2500,
["Taxonomy/Coccinelloidea"] = 2800,
["Taxonomy/Coelolepida"] = 116000,
["Taxonomy/Coleoptera"] = 82000,
["Taxonomy/Coleopterida"] = 82000,
["Taxonomy/Colubridae"] = 2700,
["Taxonomy/Colubroidea"] = 2700,
["Taxonomy/Colubroides"] = 4300,
["Taxonomy/Commelinids"] = 12000,
["Taxonomy/Conchifera"] = 5200,
["Taxonomy/Condylognatha"] = 12000,
["Taxonomy/Conoidea"] = 7300,
["Taxonomy/Core_eudicots"] = 70000,
["Taxonomy/Cosmopterigidae"] = 2100,
["Taxonomy/Cossoidea"] = 2800,
["Taxonomy/Crambidae"] = 12000,
["Taxonomy/Crambinae"] = 2300,
["Taxonomy/Crocopoda"] = 5400,
["Taxonomy/Ctenosquamata"] = 18000,
["Taxonomy/Cucujiformia"] = 49000,
["Taxonomy/Curculionidae"] = 3200,
["Taxonomy/Curculionoidea"] = 3900,
["Taxonomy/Cyclorrhapha"] = 12000,
["Taxonomy/Cyperaceae"] = 2500,
["Taxonomy/Cypriniformes"] = 5100,
["Taxonomy/Cypriniphysi"] = 5100,
["Taxonomy/Cyprinoidei"] = 3900,
["Taxonomy/Decapoda"] = 4300,
["Taxonomy/Dendrobiinae"] = 2100,
["Taxonomy/Depressariidae"] = 3100,
["Taxonomy/Deuteropoda"] = 306000,
["Taxonomy/Deuterostomia"] = 116000,
["Taxonomy/Diaphoretickes"] = 117000,
["Taxonomy/Diaphoretickes/showdomain"] = 5100,
["Taxonomy/Dicondylia"] = 263000,
["Taxonomy/Dictyoptera"] = 2400,
["Taxonomy/Dikarya"] = 24000,
["Taxonomy/Dinosauria"] = 4300,
["Taxonomy/Dinosauria/skip"] = 19000,
["Taxonomy/Dinosauromorpha"] = 4300,
["Taxonomy/Diptera"] = 24000,
["Taxonomy/Ditrysia"] = 113000,
["Taxonomy/Doryloformicia"] = 2900,
["Taxonomy/Dothideomyceta"] = 9700,
["Taxonomy/Dothideomycetes"] = 2700,
["Taxonomy/Ecdysozoa"] = 309000,
["Taxonomy/Echinodermata"] = 2800,
["Taxonomy/Elasmobranchii"] = 2200,
["Taxonomy/Elateriformia"] = 3800,
["Taxonomy/Elementaves"] = 2100,
["Taxonomy/Elpistostegalia"] = 74000,
["Taxonomy/Embryophytes"] = 110000,
["Taxonomy/Embryophytes/Plantae"] = 110000,
["Taxonomy/Ennominae"] = 2700,
["Taxonomy/Ensifera"] = 2200,
["Taxonomy/Entelegynae"] = 8100,
["Taxonomy/Eotetrapodiformes"] = 74000,
["Taxonomy/Epidendroideae"] = 5500,
["Taxonomy/Erebidae"] = 17000,
["Taxonomy/Eremoneura"] = 12000,
["Taxonomy/Ericales"] = 4200,
["Taxonomy/Euarchontoglires"] = 6300,
["Taxonomy/Eucarida"] = 4400,
["Taxonomy/Eucrocopoda"] = 5200,
["Taxonomy/Eudicots"] = 74000,
["Taxonomy/Eufalconimorphae"] = 11000,
["Taxonomy/Euformicia"] = 3200,
["Taxonomy/Eugnathostomata"] = 111000,
["Taxonomy/Eukaryota"] = 635000,
["Taxonomy/Eukaryota/displayed"] = 6400,
["Taxonomy/Eulepidoptera"] = 114000,
["Taxonomy/Eumalacostraca"] = 6900,
["Taxonomy/Eumetabola"] = 250000,
["Taxonomy/Eumetazoa"] = 490000,
["Taxonomy/Eupasseres"] = 9800,
["Taxonomy/Eupercaria"] = 5700,
["Taxonomy/Euphyllophytes"] = 2000,
["Taxonomy/Eupitheciini"] = 2000,
["Taxonomy/Eupulmonata"] = 6300,
["Taxonomy/Eurypterygii"] = 18000,
["Taxonomy/Euselachii"] = 2300,
["Taxonomy/Euteleostei"] = 19000,
["Taxonomy/Eutheria"] = 17000,
["Taxonomy/Euthyneura"] = 13000,
["Taxonomy/Euungulata"] = 4000,
["Taxonomy/Fabaceae"] = 6800,
["Taxonomy/Fabales"] = 7100,
["Taxonomy/Fabids"] = 18000,
["Taxonomy/Faboideae"] = 4000,
["Taxonomy/Ferae"] = 2400,
["Taxonomy/Ferungulata"] = 6400,
["Taxonomy/Filozoa"] = 492000,
["Taxonomy/Formicidae"] = 3300,
["Taxonomy/Formicoidea"] = 3300,
["Taxonomy/Fungi"] = 25000,
["Taxonomy/Gamasina"] = 2300,
["Taxonomy/Gammaproteobacteria"] = 2000,
["Taxonomy/Gastropoda"] = 44000,
["Taxonomy/Gekkonoidea"] = 2200,
["Taxonomy/Gekkonomorpha"] = 2600,
["Taxonomy/Gekkota"] = 2600,
["Taxonomy/Gelechiidae"] = 6100,
["Taxonomy/Gelechiinae"] = 3000,
["Taxonomy/Gelechioidea"] = 19000,
["Taxonomy/Gentianales"] = 5000,
["Taxonomy/Geometridae"] = 11000,
["Taxonomy/Geometroidea"] = 11000,
["Taxonomy/Glires"] = 4600,
["Taxonomy/Gliriformes"] = 4600,
["Taxonomy/Glossata"] = 116000,
["Taxonomy/Gnathostomata"] = 111000,
["Taxonomy/Gracillariidae"] = 2200,
["Taxonomy/Gracillarioidea"] = 2500,
["Taxonomy/Graminid_clade"] = 4100,
["Taxonomy/Halvaria"] = 3000,
["Taxonomy/Helicina_(suborder)"] = 5500,
["Taxonomy/Hemiptera"] = 10000,
["Taxonomy/Hesperiidae"] = 2700,
["Taxonomy/Heterobranchia"] = 13000,
["Taxonomy/Heteroneura"] = 115000,
["Taxonomy/Heteroptera"] = 5100,
["Taxonomy/Hexapoda"] = 265000,
["Taxonomy/Holometabola"] = 238000,
["Taxonomy/Holomycota"] = 25000,
["Taxonomy/Holozoa"] = 492000,
["Taxonomy/Hyloidea"] = 3600,
["Taxonomy/Hymenoptera"] = 14000,
["Taxonomy/Hymenopterida"] = 14000,
["Taxonomy/Iguania"] = 2500,
["Taxonomy/Iguanomorpha"] = 2500,
["Taxonomy/Insecta"] = 263000,
["Taxonomy/Lamiales"] = 6900,
["Taxonomy/Lamiids"] = 14000,
["Taxonomy/Lamiinae"] = 21000,
["Taxonomy/Larentiinae"] = 3700,
["Taxonomy/Laurasiatheria"] = 9200,
["Taxonomy/Lecanoromycetes"] = 4700,
["Taxonomy/Lecanoromycetidae"] = 3200,
["Taxonomy/Leotiomyceta"] = 14000,
["Taxonomy/Lepidoptera"] = 116000,
["Taxonomy/Lepidosauria"] = 15000,
["Taxonomy/Lepidosauromorpha"] = 15000,
["Taxonomy/Life"] = 653000,
["Taxonomy/Linyphiidae"] = 2100,
["Taxonomy/Lissamphibia"] = 9100,
["Taxonomy/Lithosiini"] = 3600,
["Taxonomy/Littorinimorpha"] = 5800,
["Taxonomy/Lophotrochozoa"] = 57000,
["Taxonomy/Lycaenidae"] = 4100,
["Taxonomy/Macroheterocera"] = 43000,
["Taxonomy/Magnoliids"] = 2900,
["Taxonomy/Malacostraca"] = 7100,
["Taxonomy/Malaxideae"] = 2200,
["Taxonomy/Malpighiales"] = 4900,
["Taxonomy/Malvales"] = 2700,
["Taxonomy/Malvids"] = 13000,
["Taxonomy/Mammalia"] = 19000,
["Taxonomy/Mammalia/skip"] = 19000,
["Taxonomy/Mandibulata"] = 277000,
["Taxonomy/Melolonthinae"] = 3000,
["Taxonomy/Meso-Papilionoideae"] = 3800,
["Taxonomy/Mesostigmata"] = 2800,
["Taxonomy/Mollusca"] = 52000,
["Taxonomy/Monocots"] = 27000,
["Taxonomy/Monogynaspida"] = 2500,
["Taxonomy/Multicrustacea"] = 8700,
["Taxonomy/Muricidae"] = 2200,
["Taxonomy/Muricoidea"] = 2200,
["Taxonomy/Muroidea"] = 2600,
["Taxonomy/Muscomorpha"] = 15000,
["Taxonomy/Mygalomorphae"] = 2400,
["Taxonomy/Myoglossata"] = 116000,
["Taxonomy/Myomorpha"] = 2700,
["Taxonomy/Myriapoda"] = 2400,
["Taxonomy/Myrtaceae"] = 3100,
["Taxonomy/Myrtales"] = 4600,
["Taxonomy/Myrtoideae"] = 3100,
["Taxonomy/Nematocera"] = 3300,
["Taxonomy/Neoaves"] = 17000,
["Taxonomy/Neobatrachia"] = 6800,
["Taxonomy/Neocephalopoda"] = 3900,
["Taxonomy/Neodiapsida"] = 24000,
["Taxonomy/Neogastropoda"] = 16000,
["Taxonomy/Neognathae"] = 18000,
["Taxonomy/Neolepidoptera"] = 116000,
["Taxonomy/Neoptera"] = 259000,
["Taxonomy/Neopterygii"] = 32000,
["Taxonomy/Neoreptilia"] = 25000,
["Taxonomy/Neoteleostei"] = 18000,
["Taxonomy/Nephrozoa"] = 485000,
["Taxonomy/Neuropteroidea"] = 83000,
["Taxonomy/Noctuidae"] = 8400,
["Taxonomy/Noctuinae"] = 2800,
["Taxonomy/Noctuoidea"] = 27000,
["Taxonomy/Non-protein_amino_acid-accumulating_clade"] = 2700,
["Taxonomy/Nudibranchia"] = 2700,
["Taxonomy/Nudipleura"] = 2700,
["Taxonomy/Nymphalidae"] = 4300,
["Taxonomy/Obazoa"] = 517000,
["Taxonomy/Obtectomera"] = 73000,
["Taxonomy/Odonata"] = 3100,
["Taxonomy/Odonatoptera"] = 3100,
["Taxonomy/Oestroidea"] = 5000,
["Taxonomy/Olfactores"] = 112000,
["Taxonomy/Ophidia"] = 5200,
["Taxonomy/Opisthokonta"] = 517000,
["Taxonomy/Opisthothelae"] = 18000,
["Taxonomy/Orchidaceae"] = 8100,
["Taxonomy/Orchidoideae"] = 2300,
["Taxonomy/Ornithodira"] = 5000,
["Taxonomy/Ornithurae"] = 19000,
["Taxonomy/Ornithurae/skip"] = 19000,
["Taxonomy/Orthoptera"] = 4400,
["Taxonomy/Ostariophysi"] = 10000,
["Taxonomy/Osteichthyes"] = 108000,
["Taxonomy/Otocephala"] = 11000,
["Taxonomy/Otophysi"] = 10000,
["Taxonomy/Ovalentaria"] = 5000,
["Taxonomy/Palaeoptera"] = 3800,
["Taxonomy/Pan-Carnivora"] = 2200,
["Taxonomy/Pan-Euteleostei"] = 19000,
["Taxonomy/Pan-Euungulata"] = 4100,
["Taxonomy/Panarthropoda"] = 307000,
["Taxonomy/Pancrustacea"] = 275000,
["Taxonomy/Panorpida"] = 141000,
["Taxonomy/Panpulmonata"] = 8600,
["Taxonomy/Pantetrapulmonata"] = 19000,
["Taxonomy/Papilionoidea"] = 13000,
["Taxonomy/ParaHoxozoa"] = 490000,
["Taxonomy/Parapleurota"] = 25000,
["Taxonomy/Parasitiformes"] = 3100,
["Taxonomy/Paraxonia"] = 2800,
["Taxonomy/Passerea"] = 13000,
["Taxonomy/Passeri"] = 7800,
["Taxonomy/Passerida"] = 3500,
["Taxonomy/Passerides"] = 5900,
["Taxonomy/Passeriformes"] = 9800,
["Taxonomy/Pentatomomorpha"] = 2300,
["Taxonomy/Peracarida"] = 2500,
["Taxonomy/Perciformes"] = 2800,
["Taxonomy/Percomorpha"] = 16000,
["Taxonomy/Pezizomycotina"] = 15000,
["Taxonomy/Phycitinae"] = 2600,
["Taxonomy/Phytophaga"] = 41000,
["Taxonomy/Placentalia"] = 17000,
["Taxonomy/Plantae"] = 112000,
["Taxonomy/Planulozoa"] = 3800,
["Taxonomy/Platyhelminthes"] = 2700,
["Taxonomy/Pleocyemata"] = 4100,
["Taxonomy/Poaceae"] = 4100,
["Taxonomy/Poales"] = 9400,
["Taxonomy/Podiata"] = 517000,
["Taxonomy/Polyneoptera"] = 8600,
["Taxonomy/Polyphaga"] = 68000,
["Taxonomy/Polypodiophyta"] = 2000,
["Taxonomy/Polypodiopsida"] = 2000,
["Taxonomy/Polysporangiophytes"] = 108000,
["Taxonomy/Polysporangiophytes/Plantae"] = 108000,
["Taxonomy/Proteales"] = 2000,
["Taxonomy/Protostomia"] = 370000,
["Taxonomy/Pseudomonadati"] = 8100,
["Taxonomy/Pseudomonadota"] = 5000,
["Taxonomy/Psittacopasseres"] = 11000,
["Taxonomy/Pteropliini"] = 2300,
["Taxonomy/Pterygota"] = 263000,
["Taxonomy/Pyralidae"] = 4500,
["Taxonomy/Pyraloidea"] = 16000,
["Taxonomy/Pyramidellidae"] = 2200,
["Taxonomy/Pyramidelloidea"] = 2200,
["Taxonomy/RTA_clade"] = 4400,
["Taxonomy/Ranoidea"] = 2900,
["Taxonomy/Reptantia"] = 3400,
["Taxonomy/Reptiliomorpha"] = 64000,
["Taxonomy/Rhabditophora"] = 2700,
["Taxonomy/Rhipidistia"] = 75000,
["Taxonomy/Ringipleura"] = 2800,
["Taxonomy/Rodentia"] = 4400,
["Taxonomy/Rosales"] = 3300,
["Taxonomy/Rosids"] = 31000,
["Taxonomy/Rouphozoa"] = 2800,
["Taxonomy/Rubiaceae"] = 2600,
["Taxonomy/Saccharomyceta"] = 15000,
["Taxonomy/Salientia"] = 7800,
["Taxonomy/Salticidae"] = 2900,
["Taxonomy/Salticinae"] = 2600,
["Taxonomy/Sapindales"] = 3300,
["Taxonomy/Sar"] = 4000,
["Taxonomy/Sarcopterygii"] = 75000,
["Taxonomy/Sauria"] = 23000,
["Taxonomy/Saurischia"] = 2900,
["Taxonomy/Sauropsida"] = 43000,
["Taxonomy/Scarabaeidae"] = 10000,
["Taxonomy/Scarabaeiformia"] = 11000,
["Taxonomy/Scarabaeoidea"] = 11000,
["Taxonomy/Schizophora"] = 12000,
["Taxonomy/Scincidae"] = 2100,
["Taxonomy/Scincomorpha"] = 2400,
["Taxonomy/Scrotifera"] = 8400,
["Taxonomy/Sericinae"] = 3900,
["Taxonomy/Sericini"] = 3600,
["Taxonomy/Serpentes"] = 5200,
["Taxonomy/Setaphyta"] = 2100,
["Taxonomy/Siluriformes"] = 3600,
["Taxonomy/Simplicidentata"] = 4400,
["Taxonomy/Sordariomyceta"] = 4600,
["Taxonomy/Sordariomycetes"] = 2900,
["Taxonomy/Spermatophyta"] = 105000,
["Taxonomy/Spermatophytes/Plantae"] = 105000,
["Taxonomy/Spilomelinae"] = 4300,
["Taxonomy/Spiralia"] = 60000,
["Taxonomy/Squamata"] = 15000,
["Taxonomy/Staphyliniformia"] = 3000,
["Taxonomy/Staphylinoidea"] = 2200,
["Taxonomy/Stegocephali"] = 74000,
["Taxonomy/Stylommatophora"] = 6000,
["Taxonomy/Superasterids"] = 38000,
["Taxonomy/Superrosids"] = 32000,
["Taxonomy/Syrphidae"] = 2100,
["Taxonomy/Syrphoidea"] = 2300,
["Taxonomy/TSAR"] = 4000,
["Taxonomy/Tachinidae"] = 4400,
["Taxonomy/Tectipleura"] = 9800,
["Taxonomy/Teleocephala"] = 30000,
["Taxonomy/Teleostei"] = 32000,
["Taxonomy/Teleosteomorpha"] = 32000,
["Taxonomy/Telluraves"] = 13000,
["Taxonomy/Tenebrionoidea"] = 3400,
["Taxonomy/Tephritidae"] = 3300,
["Taxonomy/Tephritinae"] = 2400,
["Taxonomy/Tephritoidea"] = 4300,
["Taxonomy/Tetrapoda"] = 74000,
["Taxonomy/Tetrapodomorpha"] = 74000,
["Taxonomy/Tetrapulmonata"] = 19000,
["Taxonomy/Theria"] = 18000,
["Taxonomy/Theria/skip"] = 18000,
["Taxonomy/Theropoda/skip"] = 19000,
["Taxonomy/Tortricidae"] = 8500,
["Taxonomy/Tortricinae"] = 5900,
["Taxonomy/Tortricoidea"] = 8500,
["Taxonomy/Toxicofera"] = 8400,
["Taxonomy/Tracheophyta"] = 108000,
["Taxonomy/Tracheophytes/Plantae"] = 108000,
["Taxonomy/Trilobita"] = 2200,
["Taxonomy/Trilobitomorpha"] = 2300,
["Taxonomy/Trochida"] = 2800,
["Taxonomy/Trochoidea"] = 2800,
["Taxonomy/Tyranni"] = 2000,
["Taxonomy/Unicalcarida"] = 14000,
["Taxonomy/Vertebrata"] = 112000,
["Taxonomy/Vetigastropoda"] = 4900,
["Taxonomy/Virus"] = 2900,
["Taxonomy/crown_Formicidae"] = 3200,
["Taxonomy_key"] = 150000,
["Taxonomy_preload"] = 150000,
["Tb"] = 13000,
["Team_roster_navbox"] = 34000,
["Technical"] = 4100,
["Technically_indistinguishable"] = 2500,
["Television_debuts_endings_antonym"] = 7200,
["Television_episode_redirect_handler"] = 24000,
["Television_episode_short_description"] = 13000,
["Template"] = 4700,
["Template-Class"] = 14000,
["TemplateData_header"] = 18000,
["Template_category"] = 36000,
["Template_display"] = 57000,
["Template_for_discussion/dated"] = 16000,
["Template_for_discussion/styles.css"] = 33000,
["Template_for_merging/dated"] = 17000,
["Template_link"] = 7550000,
["Template_link_code"] = 1160000,
["Template_link_code_with_subst"] = 20000,
["Template_link_expanded"] = 2620000,
["Template_link_expanded_with_subst"] = 5000,
["Template_link_general"] = 24000,
["Template_link_interwiki"] = 9000,
["Template_link_null"] = 9200,
["Template_link_universal"] = 12000,
["Template_link_with_alternate_text"] = 2200,
["Template_link_with_link_off"] = 9800,
["Template_link_with_linked_braces"] = 8200,
["Template_link_with_parameters"] = 70000,
["Template_link_with_subst"] = 54000,
["Template_links"] = 2500,
["Template_other"] = 4970000,
["Template_parameter_usage"] = 20000,
["Template_parameter_value"] = 51000,
["Template_rating"] = 2600,
["Template_reference_list"] = 7400,
["Template_sandbox_notice"] = 6500,
["Template_shortcut"] = 6500,
["TennisEventInfo"] = 6800,
["TennisEvents"] = 2200,
["Tennis_events"] = 13000,
["Tennis_icon"] = 2800,
["Tennis_icon2"] = 2800,
["Tennis_record"] = 3000,
["Terminate_sentence"] = 53000,
["Testcases_notice"] = 5100,
["Text_diff"] = 3500,
["Tfd_links"] = 6800,
["Th/abp"] = 115000,
["Thank"] = 2400,
["Thank_you"] = 5400,
["The_edit-summary_field"] = 8900,
["The_edit-summary_field/OOUI"] = 2400,
["Their"] = 15000,
["They"] = 11000,
["They_have"] = 39000,
["Thin_space"] = 29000,
["Thinsp"] = 26000,
["Third-party"] = 6700,
["Thirteen_Colonies_article_name"] = 2100,
["This_is_a_new_user"] = 7000,
["Thursday"] = 2800,
["Tick"] = 81000,
["Ticket_confirmation"] = 3200,
["Time"] = 2800,
["Time_ago"] = 185000,
["Time_signature"] = 3300,
["Time_with_time_zone_link"] = 4300,
["Title_case"] = 5800,
["Title_century"] = 31000,
["Title_country"] = 42000,
["Title_decade"] = 31000,
["Title_demonym"] = 39000,
["Title_disambig_text"] = 251000,
["Title_language"] = 2600,
["Title_monthname"] = 41000,
["Title_number"] = 4400,
["Title_year"] = 264000,
["Title_year+1"] = 14000,
["Title_year-1"] = 3900,
["Title_year2range"] = 7900,
["Title_year2range-1"] = 6400,
["Title_year_range"] = 13000,
["Tl"] = 7260000,
["Tl2"] = 8900,
["Tlc"] = 907000,
["Tld"] = 252000,
["Tlf"] = 9700,
["Tlg"] = 22000,
["Tlit"] = 3200,
["Tlp"] = 70000,
["Tls"] = 52000,
["Tlsc"] = 20000,
["Tlsp"] = 2300,
["Tlu"] = 12000,
["Tlx"] = 2620000,
["Tlxs"] = 3400,
["Tmbox"] = 2400000,
["Tmpv"] = 50000,
["Tn"] = 8200,
["Tnull"] = 9000,
["To"] = 3000,
["To_USD"] = 2500,
["To_USD/CurrencyCheck"] = 2500,
["To_USD/General"] = 2200,
["To_be_announced"] = 7200,
["To_do"] = 7700,
["Toc_right"] = 2100,
["Tocright"] = 7300,
["Todo"] = 2700,
["Tomorrow"] = 7200,
["Tone"] = 7700,
["Tone-cmn"] = 2800,
["Toolbar"] = 349000,
["Toolforge"] = 12000,
["Tooltip"] = 563000,
["Tooltip/styles.css"] = 563000,
["Top-Class"] = 15000,
["Top-importance"] = 15000,
["Top_25_Report"] = 3900,
["Top_25_report"] = 6000,
["Top_icon"] = 84000,
["Totd"] = 4300,
["Totd_nav"] = 5400,
["Tp"] = 2600,
["Tpq"] = 3900,
["Tpr"] = 2900,
["Tps"] = 12000,
["Tpw"] = 3600,
["Tq"] = 171000,
["Tq2"] = 5600,
["Tqb"] = 5300,
["Tqq"] = 7300,
["Tquote"] = 2200,
["Track_gauge"] = 26000,
["Track_listing"] = 123000,
["Tracking_category"] = 5200,
["Tracklist"] = 16000,
["Trademark"] = 7800,
["Trademarked"] = 4300,
["Transclude"] = 18000,
["Transclude_lead_excerpt"] = 3600,
["Transcluded_section"] = 4700,
["Transclusionless"] = 5000,
["Translated"] = 25000,
["Translated_page"] = 114000,
["Translation"] = 20000,
["Translation/Base"] = 2400,
["Translation/Information"] = 2100,
["Translation/Summary"] = 2100,
["Transliteration"] = 69000,
["Tree_chart"] = 8400,
["Tree_chart/end"] = 8400,
["Tree_chart/start"] = 8400,
["Tree_list"] = 25000,
["Tree_list/end"] = 25000,
["Tree_list/styles.css"] = 25000,
["Trim"] = 2980000,
["Trim_%"] = 6700,
["Trim_brackets"] = 3600,
["Trim_leading"] = 2100,
["Trim_quotes"] = 26000,
["Trout"] = 2200,
["Tsh"] = 3300,
["Tsp"] = 2200,
["Tuesday"] = 2800,
["TuttoCalciatori"] = 2200,
["Twitter"] = 16000,
["Two-digit_year"] = 6000,
["TwoLegResult"] = 5800,
["TwoLegStart"] = 4600,
["TwoLeg_start"] = 5800,
["Module:TNT"] = 10000,
["Module:TableTools"] = 9590000,
["Module:Table_empty_cell"] = 33000,
["Module:Taxobox_ranks"] = 656000,
["Module:TaxonItalics"] = 655000,
["Module:TaxonList"] = 28000,
["Module:Taxonbar"] = 503000,
["Module:Taxonbar/candidate"] = 501000,
["Module:Taxonbar/conf"] = 503000,
["Module:Taxonbar/exists"] = 501000,
["Module:Taxonbar/whitelist"] = 503000,
["Module:Team_appearances_list"] = 17000,
["Module:Team_appearances_list/data"] = 17000,
["Module:Team_bracket"] = 55000,
["Module:Team_bracket_tracking"] = 3700,
["Module:Team_roster_navbox"] = 35000,
["Module:Television_episode_redirect_handler"] = 24000,
["Module:Television_episode_short_description"] = 35000,
["Module:Television_infoboxes_disambiguation_check"] = 72000,
["Module:TemplatePar"] = 33000,
["Module:TemplateStyles"] = 598000,
["Module:Template_invocation"] = 3200,
["Module:Template_link_general"] = 3780000,
["Module:Template_parameter_value"] = 12100000,
["Module:Template_redirect_regex"] = 1460000,
["Module:Template_test_case"] = 3300,
["Module:Template_test_case/config"] = 3300,
["Module:Template_test_case/data"] = 3300,
["Module:Template_wrapper"] = 1040000,
["Module:Tennis_events_nav"] = 22000,
["Module:Text"] = 2060000,
["Module:Text/data"] = 53000,
["Module:Tfd_links"] = 6800,
["Module:Time"] = 4500,
["Module:Time/data"] = 4500,
["Module:Time_ago"] = 192000,
["Module:Title_monthname"] = 41000,
["Module:Toolbar"] = 1510000,
["Module:Top_25_report"] = 5900,
["Module:Track_gauge"] = 26000,
["Module:Track_gauge/data"] = 26000,
["Module:Track_listing"] = 123000,
["Module:Track_listing/configuration"] = 123000,
["Module:Track_listing/styles.css"] = 123000,
["Module:Transclusion_count"] = 64000,
["Module:Transclusion_count/data/A"] = 3700,
["Module:Transclusion_count/data/B"] = 2800,
["Module:Transclusion_count/data/C"] = 12000,
["Module:Transclusion_count/data/E"] = 2400,
["Module:Transclusion_count/data/G"] = 2000,
["Module:Transclusion_count/data/I"] = 3300,
["Module:Transclusion_count/data/L"] = 2000,
["Module:Transclusion_count/data/M"] = 3200,
["Module:Transclusion_count/data/N"] = 2800,
["Module:Transclusion_count/data/P"] = 2900,
["Module:Transclusion_count/data/S"] = 5000,
["Module:Transclusion_count/data/T"] = 2600,
["Module:Transclusion_count/data/U"] = 2600,
["Module:Transclusion_count/data/W"] = 3700,
["Module:Transclusion_count/data/other"] = 2200,
["Module:Tree_chart"] = 8400,
["Module:Tree_chart/data"] = 8400,
["Module:Trim_quotes"] = 68000,
["Module:TwitterSnowflake"] = 48000,
["Module:Type_in_location"] = 137000,
}
l4mwzmswz8sixynecilawrvwyezxpa4
Module:DemoTemplate
828
1107
9221
2022-10-21T06:42:10Z
en>Legoktm
0
Replace [[Module:No globals]] with require( "strict" )
9221
Scribunto
text/plain
require('strict')
local newBuffer = require('Module:OutputBuffer')
local mt = {}
function mt.__index(t, title)
return function(frame)
local getBuffer, print, printf = newBuffer()
printf('{{%s', title)
local ipairsArgs = {}
for k,v in ipairs(frame.args) do
if string.find(v, '=', 1, true) then
break
end
ipairsArgs[k] = true
printf('|%s', v)
end
for k,v in pairs(frame.args) do
if not ipairsArgs[k] then
printf('|%s=%s', string.gsub(k, '=', '{{=}}'), v)
end
end
print('}}')
local buffer = getBuffer()
-- rather than calling expandTemplate with the title and args we have, call preprocess, so that our code example will always match our output, even in the cases of pipes or other things we should have escaped but didn't
return string.format('<code>%s</code> → %s', mw.text.nowiki(buffer), frame:preprocess(buffer))
end
end
return setmetatable({}, mt)
8mlbnzfciphbgabjlzcptahim6afk3p
9222
9221
2026-08-23T03:33:21Z
RAPTOR7762
18
1 revision imported from [[:en:Module:DemoTemplate]]
9221
Scribunto
text/plain
require('strict')
local newBuffer = require('Module:OutputBuffer')
local mt = {}
function mt.__index(t, title)
return function(frame)
local getBuffer, print, printf = newBuffer()
printf('{{%s', title)
local ipairsArgs = {}
for k,v in ipairs(frame.args) do
if string.find(v, '=', 1, true) then
break
end
ipairsArgs[k] = true
printf('|%s', v)
end
for k,v in pairs(frame.args) do
if not ipairsArgs[k] then
printf('|%s=%s', string.gsub(k, '=', '{{=}}'), v)
end
end
print('}}')
local buffer = getBuffer()
-- rather than calling expandTemplate with the title and args we have, call preprocess, so that our code example will always match our output, even in the cases of pipes or other things we should have escaped but didn't
return string.format('<code>%s</code> → %s', mw.text.nowiki(buffer), frame:preprocess(buffer))
end
end
return setmetatable({}, mt)
8mlbnzfciphbgabjlzcptahim6afk3p
Tempilet:Terminate sentence/doc
10
1108
9223
2025-09-06T09:35:24Z
en>Carcharoth
0
it seems that this template does this sort of action, so categorising here
9223
wikitext
text/x-wiki
{{Documentation subpage}}
{{High-use}}
{{Lua|Module:Text}}
This template returns its first argument, after adding a full stop (or its second argument) if the sentence was not finished.
== Usage ==
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|The rain in Spain}}
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|falls mainly on the plain.}}
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|BANG|!}}
<includeonly>{{sandbox other||
<!-- Categories below this line -->
[[Category:Text-specific formatting and function templates]]
}}</includeonly>
erx0sdqzahcz13gmzjkyiagl16s63gy
9224
9223
2026-08-23T03:33:22Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Terminate_sentence/doc]]
9223
wikitext
text/x-wiki
{{Documentation subpage}}
{{High-use}}
{{Lua|Module:Text}}
This template returns its first argument, after adding a full stop (or its second argument) if the sentence was not finished.
== Usage ==
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|The rain in Spain}}
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|falls mainly on the plain.}}
* {{#invoke:DemoTemplate|{{BASEPAGENAME}}|BANG|!}}
<includeonly>{{sandbox other||
<!-- Categories below this line -->
[[Category:Text-specific formatting and function templates]]
}}</includeonly>
erx0sdqzahcz13gmzjkyiagl16s63gy
Module:Text/data
828
1109
9225
2025-11-04T01:48:35Z
en>Andrybak
0
extract ASCII codes for square brackets and the hyphen into local constants for clarity
9225
Scribunto
text/plain
-- Data required by [[Module:Text]].
-- Either Lua string patterns (defined by codepoint) or information about quotes
local data = {}
local LEFT_SQUARE_BRACKET = 91
local RIGHT_SQUARE_BRACKET = 93
local HYPHEN = 45
data.PatternCJK = mw.ustring.char( LEFT_SQUARE_BRACKET,
4352, HYPHEN, 4607,
11904, HYPHEN, 42191,
43072, HYPHEN, 43135,
44032, HYPHEN, 55215,
63744, HYPHEN, 64255,
65072, HYPHEN, 65103,
65381, HYPHEN, 65500,
131072, HYPHEN, 196607,
RIGHT_SQUARE_BRACKET )
data.PatternCombined = mw.ustring.char( LEFT_SQUARE_BRACKET,
0x0300, HYPHEN, 0x036F,
0x1AB0, HYPHEN, 0x1AFF,
0x1DC0, HYPHEN, 0x1DFF,
0xFE20, HYPHEN, 0xFE2F,
RIGHT_SQUARE_BRACKET )
local RangesLatin = { { 7, 687 },
{ 7531, 7578 },
{ 7680, 7935 },
{ 8194, 8250 } }
local PatternLatin = "^["
for i = 1, #RangesLatin do
local range = RangesLatin[ i ]
PatternLatin = PatternLatin .. mw.ustring.char( range[ 1 ], HYPHEN, range[ 2 ] )
end
PatternLatin = PatternLatin .. "]*$"
data.RangesLatin = RangesLatin
data.NumLatinRanges = #RangesLatin
data.PatternLatin = PatternLatin
data.PatternTerminated = mw.ustring.char( LEFT_SQUARE_BRACKET,
12290,
65281,
65294,
65311 )
.. "!%.%?…][\"'%]‹›«»‘’“”]*$"
data.QuoteLang = { af = "bd",
ar = "la",
be = "labd",
bg = "bd",
ca = "la",
cs = "bd",
da = "bd",
de = "bd",
dsb = "bd",
et = "bd",
el = "lald",
en = "ld",
es = "la",
eu = "la",
-- fa = "la",
fi = "rd",
fr = "laSPC",
ga = "ld",
he = "ldla",
hr = "bd",
hsb = "bd",
hu = "bd",
hy = "labd",
id = "rd",
is = "bd",
it = "ld",
ja = "x300C",
ka = "bd",
ko = "ld",
lt = "bd",
lv = "bd",
nl = "ld",
nn = "la",
no = "la",
pl = "bdla",
pt = "lald",
ro = "bdla",
ru = "labd",
sk = "bd",
sl = "bd",
sq = "la",
sr = "bx",
sv = "rd",
th = "ld",
tr = "ld",
uk = "la",
zh = "ld",
["de-ch"] = "la",
["en-gb"] = "lsld",
["en-us"] = "ld",
["fr-ch"] = "la",
["it-ch"] = "la",
["pt-br"] = "ldla",
["zh-tw"] = "x300C",
["zh-cn"] = "ld" }
data.QuoteType = { bd = { { 8222, 8220 }, { 8218, 8217 } },
bdla = { { 8222, 8220 }, { 171, 187 } },
bx = { { 8222, 8221 }, { 8218, 8217 } },
la = { { 171, 187 }, { 8249, 8250 } },
laSPC = { { 171, 187 }, { 8249, 8250 }, true },
labd = { { 171, 187 }, { 8222, 8220 } },
lald = { { 171, 187 }, { 8220, 8221 } },
ld = { { 8220, 8221 }, { 8216, 8217 } },
ldla = { { 8220, 8221 }, { 171, 187 } },
lsld = { { 8216, 8217 }, { 8220, 8221 } },
rd = { { 8221, 8221 }, { 8217, 8217 } },
x300C = { { 0x300C, 0x300D },
{ 0x300E, 0x300F } } }
data.SeekQuote = mw.ustring.char( 34, -- "
39, -- '
171, -- laquo
187, -- raquo
8216, -- lsquo
8217, -- rsquo
8218, -- sbquo
8220, -- ldquo
8221, -- rdquo
8222, -- bdquo
8249, -- lsaquo
8250, -- rsaquo
0x300C, -- CJK
0x300D, -- CJK
0x300E, -- CJK
0x300F ) -- CJK
return data
32zfplthqqurpuluwxl965oirtoogiz
9226
9225
2026-08-23T03:33:22Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Text/data]]
9225
Scribunto
text/plain
-- Data required by [[Module:Text]].
-- Either Lua string patterns (defined by codepoint) or information about quotes
local data = {}
local LEFT_SQUARE_BRACKET = 91
local RIGHT_SQUARE_BRACKET = 93
local HYPHEN = 45
data.PatternCJK = mw.ustring.char( LEFT_SQUARE_BRACKET,
4352, HYPHEN, 4607,
11904, HYPHEN, 42191,
43072, HYPHEN, 43135,
44032, HYPHEN, 55215,
63744, HYPHEN, 64255,
65072, HYPHEN, 65103,
65381, HYPHEN, 65500,
131072, HYPHEN, 196607,
RIGHT_SQUARE_BRACKET )
data.PatternCombined = mw.ustring.char( LEFT_SQUARE_BRACKET,
0x0300, HYPHEN, 0x036F,
0x1AB0, HYPHEN, 0x1AFF,
0x1DC0, HYPHEN, 0x1DFF,
0xFE20, HYPHEN, 0xFE2F,
RIGHT_SQUARE_BRACKET )
local RangesLatin = { { 7, 687 },
{ 7531, 7578 },
{ 7680, 7935 },
{ 8194, 8250 } }
local PatternLatin = "^["
for i = 1, #RangesLatin do
local range = RangesLatin[ i ]
PatternLatin = PatternLatin .. mw.ustring.char( range[ 1 ], HYPHEN, range[ 2 ] )
end
PatternLatin = PatternLatin .. "]*$"
data.RangesLatin = RangesLatin
data.NumLatinRanges = #RangesLatin
data.PatternLatin = PatternLatin
data.PatternTerminated = mw.ustring.char( LEFT_SQUARE_BRACKET,
12290,
65281,
65294,
65311 )
.. "!%.%?…][\"'%]‹›«»‘’“”]*$"
data.QuoteLang = { af = "bd",
ar = "la",
be = "labd",
bg = "bd",
ca = "la",
cs = "bd",
da = "bd",
de = "bd",
dsb = "bd",
et = "bd",
el = "lald",
en = "ld",
es = "la",
eu = "la",
-- fa = "la",
fi = "rd",
fr = "laSPC",
ga = "ld",
he = "ldla",
hr = "bd",
hsb = "bd",
hu = "bd",
hy = "labd",
id = "rd",
is = "bd",
it = "ld",
ja = "x300C",
ka = "bd",
ko = "ld",
lt = "bd",
lv = "bd",
nl = "ld",
nn = "la",
no = "la",
pl = "bdla",
pt = "lald",
ro = "bdla",
ru = "labd",
sk = "bd",
sl = "bd",
sq = "la",
sr = "bx",
sv = "rd",
th = "ld",
tr = "ld",
uk = "la",
zh = "ld",
["de-ch"] = "la",
["en-gb"] = "lsld",
["en-us"] = "ld",
["fr-ch"] = "la",
["it-ch"] = "la",
["pt-br"] = "ldla",
["zh-tw"] = "x300C",
["zh-cn"] = "ld" }
data.QuoteType = { bd = { { 8222, 8220 }, { 8218, 8217 } },
bdla = { { 8222, 8220 }, { 171, 187 } },
bx = { { 8222, 8221 }, { 8218, 8217 } },
la = { { 171, 187 }, { 8249, 8250 } },
laSPC = { { 171, 187 }, { 8249, 8250 }, true },
labd = { { 171, 187 }, { 8222, 8220 } },
lald = { { 171, 187 }, { 8220, 8221 } },
ld = { { 8220, 8221 }, { 8216, 8217 } },
ldla = { { 8220, 8221 }, { 171, 187 } },
lsld = { { 8216, 8217 }, { 8220, 8221 } },
rd = { { 8221, 8221 }, { 8217, 8217 } },
x300C = { { 0x300C, 0x300D },
{ 0x300E, 0x300F } } }
data.SeekQuote = mw.ustring.char( 34, -- "
39, -- '
171, -- laquo
187, -- raquo
8216, -- lsquo
8217, -- rsquo
8218, -- sbquo
8220, -- ldquo
8221, -- rdquo
8222, -- bdquo
8249, -- lsaquo
8250, -- rsaquo
0x300C, -- CJK
0x300D, -- CJK
0x300E, -- CJK
0x300F ) -- CJK
return data
32zfplthqqurpuluwxl965oirtoogiz
Tempilet:Template shortcut
10
1110
9227
2021-02-16T17:54:32Z
en>Nardog
0
TfM closed as convert
9227
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|template=yes}}</includeonly><noinclude>{{Documentation}}</noinclude>
me4jjte8wllgxkf22h7gbzu0e2tux3i
9228
9227
2026-08-23T03:37:33Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_shortcut]]
9227
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|template=yes}}</includeonly><noinclude>{{Documentation}}</noinclude>
me4jjte8wllgxkf22h7gbzu0e2tux3i
Tempilet:Yesno-yes
10
1111
9229
2018-03-11T01:06:35Z
en>JJMC89
0
allow subst
9229
wikitext
text/x-wiki
{{SAFESUBST:<noinclude />yesno|{{{1}}}|yes={{{yes|yes}}}|no={{{no|no}}}|blank={{{blank|yes}}}|¬={{{¬|yes}}}|def={{{def|yes}}}}}<noinclude>
{{Documentation|Template:Yesno/doc}}
<!--Categories go in the doc page referenced above; interwikis go in Wikidata.-->
</noinclude>
2ln5m2kzkd3wxvm1r25pwd6kj6j77we
9230
9229
2026-08-23T03:37:34Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Yesno-yes]]
9229
wikitext
text/x-wiki
{{SAFESUBST:<noinclude />yesno|{{{1}}}|yes={{{yes|yes}}}|no={{{no|no}}}|blank={{{blank|yes}}}|¬={{{¬|yes}}}|def={{{def|yes}}}}}<noinclude>
{{Documentation|Template:Yesno/doc}}
<!--Categories go in the doc page referenced above; interwikis go in Wikidata.-->
</noinclude>
2ln5m2kzkd3wxvm1r25pwd6kj6j77we
Module:Plain text
828
1112
9231
2024-12-24T01:02:36Z
en>Dpleibovitz
0
Fixed the stripping of + signs
9231
Scribunto
text/plain
--converts text with wikilinks to plain text, e.g "[[foo|gah]] is [[bar]]" to "gah is bar"
--removes anything enclosed in tags that isn't nested, mediawiki strip markers (references etc), files, italic and bold markup
require[[strict]]
local p = {}
function p.main(frame)
local text = frame.args[1]
local encode = require('Module:yesno')(frame.args.encode)
return p._main(text, encode)
end
function p._main(text, encode)
if not text then return end
text = mw.text.killMarkers(text)
:gsub(' ', ' ') --replace nbsp spaces with regular spaces
:gsub('<br ?/?>', ', ') --replace br with commas
:gsub('<span.->(.-)</span>', '%1') --remove spans while keeping text inside
:gsub('<i.->(.-)</i>', '%1') --remove italics while keeping text inside
:gsub('<b.->(.-)</b>', '%1') --remove bold while keeping text inside
:gsub('<em.->(.-)</em>', '%1') --remove emphasis while keeping text inside
:gsub('<strong.->(.-)</strong>', '%1') --remove strong while keeping text inside
:gsub('<sub.->(.-)</sub>', '%1') --remove subscript markup; retain contents
:gsub('<sup.->(.-)</sup>', '%1') --remove superscript markup; retain contents
:gsub('<u.->(.-)</u>', '%1') --remove underline markup; retain contents
:gsub('<.->.-<.->', '') --strip out remaining tags and the text inside
:gsub('<.->', '') --remove any other tag markup
:gsub('%[%[%s*[Ff][Ii][Ll][Ee]%s*:.-%]%]', '') --strip out files
:gsub('%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:.-%]%]', '') --strip out use of image:
:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:.-%]%]', '') --strip out categories
:gsub('%[%[[^%]]-|', '') --strip out piped link text
:gsub('([^%[])%[[^%[%]][^%]]-%s', '%1') --strip out external link text
:gsub('^%[[^%[%]][^%]]-%s', '') --strip out external link text
:gsub('[%[%]]', '') --then strip out remaining [ and ]
:gsub("'''''", "") --strip out bold italic markup
:gsub("'''?", "") --not stripping out '''' gives correct output for bolded text in quotes
:gsub('%-%-%-%-+', '') --remove ---- lines
:gsub("^%s+", "") --strip leading
:gsub("%s+$", "") --and trailing spaces
:gsub("%s+", " ") --strip redundant spaces
if encode then
return mw.text.encode(text)
else
return text
end
end
return p
hoter5uo4etb5wdwstjvk8cajoqttvl
9232
9231
2026-08-23T03:37:34Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Plain_text]]
9231
Scribunto
text/plain
--converts text with wikilinks to plain text, e.g "[[foo|gah]] is [[bar]]" to "gah is bar"
--removes anything enclosed in tags that isn't nested, mediawiki strip markers (references etc), files, italic and bold markup
require[[strict]]
local p = {}
function p.main(frame)
local text = frame.args[1]
local encode = require('Module:yesno')(frame.args.encode)
return p._main(text, encode)
end
function p._main(text, encode)
if not text then return end
text = mw.text.killMarkers(text)
:gsub(' ', ' ') --replace nbsp spaces with regular spaces
:gsub('<br ?/?>', ', ') --replace br with commas
:gsub('<span.->(.-)</span>', '%1') --remove spans while keeping text inside
:gsub('<i.->(.-)</i>', '%1') --remove italics while keeping text inside
:gsub('<b.->(.-)</b>', '%1') --remove bold while keeping text inside
:gsub('<em.->(.-)</em>', '%1') --remove emphasis while keeping text inside
:gsub('<strong.->(.-)</strong>', '%1') --remove strong while keeping text inside
:gsub('<sub.->(.-)</sub>', '%1') --remove subscript markup; retain contents
:gsub('<sup.->(.-)</sup>', '%1') --remove superscript markup; retain contents
:gsub('<u.->(.-)</u>', '%1') --remove underline markup; retain contents
:gsub('<.->.-<.->', '') --strip out remaining tags and the text inside
:gsub('<.->', '') --remove any other tag markup
:gsub('%[%[%s*[Ff][Ii][Ll][Ee]%s*:.-%]%]', '') --strip out files
:gsub('%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:.-%]%]', '') --strip out use of image:
:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:.-%]%]', '') --strip out categories
:gsub('%[%[[^%]]-|', '') --strip out piped link text
:gsub('([^%[])%[[^%[%]][^%]]-%s', '%1') --strip out external link text
:gsub('^%[[^%[%]][^%]]-%s', '') --strip out external link text
:gsub('[%[%]]', '') --then strip out remaining [ and ]
:gsub("'''''", "") --strip out bold italic markup
:gsub("'''?", "") --not stripping out '''' gives correct output for bolded text in quotes
:gsub('%-%-%-%-+', '') --remove ---- lines
:gsub("^%s+", "") --strip leading
:gsub("%s+$", "") --and trailing spaces
:gsub("%s+", " ") --strip redundant spaces
if encode then
return mw.text.encode(text)
else
return text
end
end
return p
hoter5uo4etb5wdwstjvk8cajoqttvl
Tempilet:Visible anchor
10
1113
9235
2026-04-27T17:19:05Z
en>Paine Ellsworth
0
per edit request on talk page - increase parameter limit from 10 to 30
9235
wikitext
text/x-wiki
<templatestyles src="Template:Visible anchor/styles.css" /><span class="vanchor"><!--
-->{{#if:{{{1|}}}|<span id="{{plain text|{{{1}}}}}"></span>}}<!--
-->{{#if:{{{2|}}}|<span id="{{plain text|{{{2}}}}}"></span>}}<!--
-->{{#if:{{{3|}}}|<span id="{{plain text|{{{3}}}}}"></span>}}<!--
-->{{#if:{{{4|}}}|<span id="{{plain text|{{{4}}}}}"></span>}}<!--
-->{{#if:{{{5|}}}|<span id="{{plain text|{{{5}}}}}"></span>}}<!--
-->{{#if:{{{6|}}}|<span id="{{plain text|{{{6}}}}}"></span>}}<!--
-->{{#if:{{{7|}}}|<span id="{{plain text|{{{7}}}}}"></span>}}<!--
-->{{#if:{{{8|}}}|<span id="{{plain text|{{{8}}}}}"></span>}}<!--
-->{{#if:{{{9|}}}|<span id="{{plain text|{{{9}}}}}"></span>}}<!--
-->{{#if:{{{10|}}}|<span id="{{plain text|{{{10}}}}}"></span>}}<!--
-->{{#if:{{{11|}}}|<span id="{{plain text|{{{11}}}}}"></span>}}<!--
-->{{#if:{{{12|}}}|<span id="{{plain text|{{{12}}}}}"></span>}}<!--
-->{{#if:{{{13|}}}|<span id="{{plain text|{{{13}}}}}"></span>}}<!--
-->{{#if:{{{14|}}}|<span id="{{plain text|{{{14}}}}}"></span>}}<!--
-->{{#if:{{{15|}}}|<span id="{{plain text|{{{15}}}}}"></span>}}<!--
-->{{#if:{{{16|}}}|<span id="{{plain text|{{{16}}}}}"></span>}}<!--
-->{{#if:{{{17|}}}|<span id="{{plain text|{{{17}}}}}"></span>}}<!--
-->{{#if:{{{18|}}}|<span id="{{plain text|{{{18}}}}}"></span>}}<!--
-->{{#if:{{{19|}}}|<span id="{{plain text|{{{19}}}}}"></span>}}<!--
-->{{#if:{{{20|}}}|<span id="{{plain text|{{{20}}}}}"></span>}}<!--
-->{{#if:{{{21|}}}|<span id="{{plain text|{{{21}}}}}"></span>}}<!--
-->{{#if:{{{22|}}}|<span id="{{plain text|{{{22}}}}}"></span>}}<!--
-->{{#if:{{{23|}}}|<span id="{{plain text|{{{23}}}}}"></span>}}<!--
-->{{#if:{{{24|}}}|<span id="{{plain text|{{{24}}}}}"></span>}}<!--
-->{{#if:{{{25|}}}|<span id="{{plain text|{{{25}}}}}"></span>}}<!--
-->{{#if:{{{26|}}}|<span id="{{plain text|{{{26}}}}}"></span>}}<!--
-->{{#if:{{{27|}}}|<span id="{{plain text|{{{27}}}}}"></span>}}<!--
-->{{#if:{{{28|}}}|<span id="{{plain text|{{{28}}}}}"></span>}}<!--
-->{{#if:{{{29|}}}|<span id="{{plain text|{{{29}}}}}"></span>}}<!--
-->{{#if:{{{30|}}}|<span id="{{plain text|{{{30}}}}}"></span>}}<!--
--><span class="vanchor-text">{{{text|{{{1}}}}}}</span><!--
-->{{#if:{{{31|}}}|<span class="error">{{Tl|Visible anchor}}: too many anchors, maximum is 30.</span>}}<!--
--></span><noinclude>
{{Documentation}}
<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE; INTERWIKIS GO TO WIKIDATA, THANK YOU! -->
</noinclude>
58aqwrtkzmllytfdj3hsoehrnukolpr
9236
9235
2026-08-23T03:37:35Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Visible_anchor]]
9235
wikitext
text/x-wiki
<templatestyles src="Template:Visible anchor/styles.css" /><span class="vanchor"><!--
-->{{#if:{{{1|}}}|<span id="{{plain text|{{{1}}}}}"></span>}}<!--
-->{{#if:{{{2|}}}|<span id="{{plain text|{{{2}}}}}"></span>}}<!--
-->{{#if:{{{3|}}}|<span id="{{plain text|{{{3}}}}}"></span>}}<!--
-->{{#if:{{{4|}}}|<span id="{{plain text|{{{4}}}}}"></span>}}<!--
-->{{#if:{{{5|}}}|<span id="{{plain text|{{{5}}}}}"></span>}}<!--
-->{{#if:{{{6|}}}|<span id="{{plain text|{{{6}}}}}"></span>}}<!--
-->{{#if:{{{7|}}}|<span id="{{plain text|{{{7}}}}}"></span>}}<!--
-->{{#if:{{{8|}}}|<span id="{{plain text|{{{8}}}}}"></span>}}<!--
-->{{#if:{{{9|}}}|<span id="{{plain text|{{{9}}}}}"></span>}}<!--
-->{{#if:{{{10|}}}|<span id="{{plain text|{{{10}}}}}"></span>}}<!--
-->{{#if:{{{11|}}}|<span id="{{plain text|{{{11}}}}}"></span>}}<!--
-->{{#if:{{{12|}}}|<span id="{{plain text|{{{12}}}}}"></span>}}<!--
-->{{#if:{{{13|}}}|<span id="{{plain text|{{{13}}}}}"></span>}}<!--
-->{{#if:{{{14|}}}|<span id="{{plain text|{{{14}}}}}"></span>}}<!--
-->{{#if:{{{15|}}}|<span id="{{plain text|{{{15}}}}}"></span>}}<!--
-->{{#if:{{{16|}}}|<span id="{{plain text|{{{16}}}}}"></span>}}<!--
-->{{#if:{{{17|}}}|<span id="{{plain text|{{{17}}}}}"></span>}}<!--
-->{{#if:{{{18|}}}|<span id="{{plain text|{{{18}}}}}"></span>}}<!--
-->{{#if:{{{19|}}}|<span id="{{plain text|{{{19}}}}}"></span>}}<!--
-->{{#if:{{{20|}}}|<span id="{{plain text|{{{20}}}}}"></span>}}<!--
-->{{#if:{{{21|}}}|<span id="{{plain text|{{{21}}}}}"></span>}}<!--
-->{{#if:{{{22|}}}|<span id="{{plain text|{{{22}}}}}"></span>}}<!--
-->{{#if:{{{23|}}}|<span id="{{plain text|{{{23}}}}}"></span>}}<!--
-->{{#if:{{{24|}}}|<span id="{{plain text|{{{24}}}}}"></span>}}<!--
-->{{#if:{{{25|}}}|<span id="{{plain text|{{{25}}}}}"></span>}}<!--
-->{{#if:{{{26|}}}|<span id="{{plain text|{{{26}}}}}"></span>}}<!--
-->{{#if:{{{27|}}}|<span id="{{plain text|{{{27}}}}}"></span>}}<!--
-->{{#if:{{{28|}}}|<span id="{{plain text|{{{28}}}}}"></span>}}<!--
-->{{#if:{{{29|}}}|<span id="{{plain text|{{{29}}}}}"></span>}}<!--
-->{{#if:{{{30|}}}|<span id="{{plain text|{{{30}}}}}"></span>}}<!--
--><span class="vanchor-text">{{{text|{{{1}}}}}}</span><!--
-->{{#if:{{{31|}}}|<span class="error">{{Tl|Visible anchor}}: too many anchors, maximum is 30.</span>}}<!--
--></span><noinclude>
{{Documentation}}
<!-- PLEASE ADD CATEGORIES TO THE /doc SUBPAGE; INTERWIKIS GO TO WIKIDATA, THANK YOU! -->
</noinclude>
58aqwrtkzmllytfdj3hsoehrnukolpr
Tempilet:Visible anchor/styles.css
10
1114
9237
2026-04-17T03:39:26Z
en>Moxy
0
Accessibility Guidelines (WCAG) 2.0.
9237
sanitized-css
text/css
/* {{pp-template}} */
.vanchor > :target ~ .vanchor-text {
background-color: #ebf4ff;
}
@media screen {
html.skin-theme-clientpref-night .vanchor > :target ~ .vanchor-text {
background-color: #0f4dc9;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .vanchor > :target ~ .vanchor-text {
background-color: #0f4dc9;
}
}
juuzxupy5l70okszqohfudkmnjxa092
9238
9237
2026-08-23T03:37:35Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Visible_anchor/styles.css]]
9237
sanitized-css
text/css
/* {{pp-template}} */
.vanchor > :target ~ .vanchor-text {
background-color: #ebf4ff;
}
@media screen {
html.skin-theme-clientpref-night .vanchor > :target ~ .vanchor-text {
background-color: #0f4dc9;
}
}
@media screen and (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .vanchor > :target ~ .vanchor-text {
background-color: #0f4dc9;
}
}
juuzxupy5l70okszqohfudkmnjxa092
Tempilet:Plain text
10
1115
9239
2022-08-01T20:08:40Z
en>Neveselbert
0
Reverting edit(s) by [[Special:Contributions/Neveselbert|Neveselbert]] ([[User_talk:Neveselbert|talk]]) to rev. 995473403 by Scottywong: Reverting [[WP:AGF|good faith]] edits [[w:en:WP:RW|(RW 16.1)]]
9239
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#invoke:Plain text|main|{{{1|}}}}}<noinclude>
{{documentation}}
</noinclude>
j1sd7nr4syu1ekxrua7t2dn2unwklsn
9240
9239
2026-08-23T03:37:35Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Plain_text]]
9239
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#invoke:Plain text|main|{{{1|}}}}}<noinclude>
{{documentation}}
</noinclude>
j1sd7nr4syu1ekxrua7t2dn2unwklsn
Tempilet:T
10
1116
9241
2022-06-05T04:09:28Z
en>Dinoguy1000
0
not that it matters much, but fix comment closing
9241
wikitext
text/x-wiki
#REDIRECT [[Template:Template link]]
{{Rcat shell|
{{R from template shortcut}}
}}
<!-- Used as Template:tl throughout English Wikipedia; demo template referenced only on meta -->
lundwspklp4q9oao3icq7qp0luocglh
9242
9241
2026-08-23T03:37:36Z
RAPTOR7762
18
1 revision imported from [[:en:Template:T]]
9241
wikitext
text/x-wiki
#REDIRECT [[Template:Template link]]
{{Rcat shell|
{{R from template shortcut}}
}}
<!-- Used as Template:tl throughout English Wikipedia; demo template referenced only on meta -->
lundwspklp4q9oao3icq7qp0luocglh
Tempilet:Tlc
10
1117
9243
2021-01-23T16:04:55Z
en>Elli
0
cats
9243
wikitext
text/x-wiki
#REDIRECT [[Template:Template link code]]
{{Redirect category shell|
{{R from template shortcut}}
{{R from high-use template}}
{{R from move}}
}}
8ipdye4ppl865bi7oqsxa27qaiw88f6
9244
9243
2026-08-23T03:37:36Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tlc]]
9243
wikitext
text/x-wiki
#REDIRECT [[Template:Template link code]]
{{Redirect category shell|
{{R from template shortcut}}
{{R from high-use template}}
{{R from move}}
}}
8ipdye4ppl865bi7oqsxa27qaiw88f6
Tempilet:Template link code
10
1118
9245
2020-11-21T12:06:22Z
en>Primefac
0
update
9245
wikitext
text/x-wiki
<includeonly>{{#Invoke:Template link general|main|nolink=yes|code=yes|nowrap=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlc}}
}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
0i49ncdivj3996big2nh593ty7aspr8
9246
9245
2026-08-23T03:37:36Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_link_code]]
9245
wikitext
text/x-wiki
<includeonly>{{#Invoke:Template link general|main|nolink=yes|code=yes|nowrap=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlc}}
}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
0i49ncdivj3996big2nh593ty7aspr8
Tempilet:Template link with link off
10
1119
9247
2020-11-21T12:06:17Z
en>Primefac
0
update
9247
wikitext
text/x-wiki
<includeonly>{{#Invoke:Template link general|main|nowrap=yes|nolink=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlf}}
}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
kmn80yu5079jyyvwn623d36xsqq3dch
9248
9247
2026-08-23T03:37:37Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_link_with_link_off]]
9247
wikitext
text/x-wiki
<includeonly>{{#Invoke:Template link general|main|nowrap=yes|nolink=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlf}}
}}
<!-- Add categories to the /doc subpage, not here! -->
</noinclude>
kmn80yu5079jyyvwn623d36xsqq3dch
Tempilet:Tlf
10
1120
9249
2020-04-13T14:42:57Z
en>Primefac
0
Primefac moved page [[Template:Tlf]] to [[Template:Template link with link off]]: full name to indicate what it does
9249
wikitext
text/x-wiki
#REDIRECT [[Template:Template link with link off]]
{{Redirect category shell|
{{R from move}}
}}
9mrb4gzoa8i94zzxq5i6opzke6v5ntr
9250
9249
2026-08-23T03:37:37Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tlf]]
9249
wikitext
text/x-wiki
#REDIRECT [[Template:Template link with link off]]
{{Redirect category shell|
{{R from move}}
}}
9mrb4gzoa8i94zzxq5i6opzke6v5ntr
Tempilet:Shortcut
10
1121
9251
2025-02-20T14:12:16Z
en>RMCD bot
0
Removing notice of move discussion
9251
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
5idoxkkbt62sniipoe18t8iorl88qpo
9252
9251
2026-08-23T03:37:37Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Shortcut]]
9251
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
5idoxkkbt62sniipoe18t8iorl88qpo
Tempilet:Short URL box
10
1122
9253
2025-11-16T14:18:03Z
en>FaviFake
0
fix link
9253
wikitext
text/x-wiki
{{shortcut|msg=<div class="module-shortcutlist" style="font-weight:normal">[[Wikipedia:URL Shortener|{{{text|Short URL}}}]]</div><br />
<span class="plainlinks">[https://w.wiki/{{{1<noinclude>|4Q7</noinclude>}}} w.wiki/{{{1<noinclude>|4Q7</noinclude>}}}]</span>}}<noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
4fy7n4obi3klcdwdtib9j513f7m6y42
9254
9253
2026-08-23T03:37:38Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Short_URL_box]]
9253
wikitext
text/x-wiki
{{shortcut|msg=<div class="module-shortcutlist" style="font-weight:normal">[[Wikipedia:URL Shortener|{{{text|Short URL}}}]]</div><br />
<span class="plainlinks">[https://w.wiki/{{{1<noinclude>|4Q7</noinclude>}}} w.wiki/{{{1<noinclude>|4Q7</noinclude>}}}]</span>}}<noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
4fy7n4obi3klcdwdtib9j513f7m6y42
Tempilet:Shortcut compact
10
1123
9255
2025-11-17T16:46:00Z
en>FaviFake
0
one more
9255
wikitext
text/x-wiki
<table class="shortcutbox shortcutbox-compact noprint" style="clear:right; float:right; border:1px solid #aaa; background:var(--background-color-base, #fff); color:inherit; margin:0.1em; padding:1px; text-align:center;"><tr><th style="border-right:1px solid #aaa; padding:2px;"><small><span style="font-weight:normal"> [[Wikipedia:Shortcut|Shortcut{{#if:{{{2|}}}|s}}]]: </span></small></th><th style="padding:2px;"> <small>{{#if:{{{1|}}}|[[{{{1}}}]]}}{{#if:{{{2|}}}| [[{{{2}}}]]}}{{#if:{{{3|}}}| [[{{{3}}}]]}}{{#if:{{{4|}}}|[[{{{4}}}]]}}{{#if:{{{5|}}}| [[{{{5}}}]]}} </small></th></tr></table><noinclude>
{{Documentation}}
</noinclude>
qdxvika355bmqeecfeb0p0zf1j73lk2
9256
9255
2026-08-23T03:37:38Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Shortcut_compact]]
9255
wikitext
text/x-wiki
<table class="shortcutbox shortcutbox-compact noprint" style="clear:right; float:right; border:1px solid #aaa; background:var(--background-color-base, #fff); color:inherit; margin:0.1em; padding:1px; text-align:center;"><tr><th style="border-right:1px solid #aaa; padding:2px;"><small><span style="font-weight:normal"> [[Wikipedia:Shortcut|Shortcut{{#if:{{{2|}}}|s}}]]: </span></small></th><th style="padding:2px;"> <small>{{#if:{{{1|}}}|[[{{{1}}}]]}}{{#if:{{{2|}}}| [[{{{2}}}]]}}{{#if:{{{3|}}}| [[{{{3}}}]]}}{{#if:{{{4|}}}|[[{{{4}}}]]}}{{#if:{{{5|}}}| [[{{{5}}}]]}} </small></th></tr></table><noinclude>
{{Documentation}}
</noinclude>
qdxvika355bmqeecfeb0p0zf1j73lk2
Tempilet:Template redirect
10
1124
9257
2022-03-31T17:59:41Z
en>MusikBot II
0
Protected "[[Template:Template redirect]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 255 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9257
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|template=yes|redirect=yes}}</includeonly><noinclude>{{Documentation}}</noinclude>
rlspkp5wnkjc5ccy5twdlm4zzrtlbql
9258
9257
2026-08-23T03:37:38Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_redirect]]
9257
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|template=yes|redirect=yes}}</includeonly><noinclude>{{Documentation}}</noinclude>
rlspkp5wnkjc5ccy5twdlm4zzrtlbql
Tempilet:Va
10
1125
9259
2023-03-27T18:00:04Z
en>MusikBot II
0
Protected "[[Template:Va]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 254 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9259
wikitext
text/x-wiki
#REDIRECT [[Template:visible anchor]]
i6gfixc1ov5k85lcqmmrva9zr1piq80
9260
9259
2026-08-23T03:37:38Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Va]]
9259
wikitext
text/x-wiki
#REDIRECT [[Template:visible anchor]]
i6gfixc1ov5k85lcqmmrva9zr1piq80
Tempilet:Format TemplateData
10
1126
9261
2021-10-05T19:23:32Z
en>MusikBot II
0
Protected "[[Template:Format TemplateData]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 305 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9261
wikitext
text/x-wiki
<includeonly>{{#ifeq:{{yesno-yes|{{{header}}}}}|yes|{{TemplateData header}}
}}{{#invoke:Format TemplateData| f |classNoNumTOC=nonumtoc |cssParams=border:#B3B7FF 1px solid;|docpageCreate=%s/doc |docpageDetect=/doc$ |msgDescMiss=Missing description |cat=Templates with TemplateData errors}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
in0weol9sija4upagvbgx1pbjtrzw7q
9262
9261
2026-08-23T03:37:39Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Format_TemplateData]]
9261
wikitext
text/x-wiki
<includeonly>{{#ifeq:{{yesno-yes|{{{header}}}}}|yes|{{TemplateData header}}
}}{{#invoke:Format TemplateData| f |classNoNumTOC=nonumtoc |cssParams=border:#B3B7FF 1px solid;|docpageCreate=%s/doc |docpageDetect=/doc$ |msgDescMiss=Missing description |cat=Templates with TemplateData errors}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
in0weol9sija4upagvbgx1pbjtrzw7q
Module:Format TemplateData
828
1127
9263
2026-07-23T06:01:42Z
en>A876
0
DON'T check for Module:JSONutil. (to stop this template from making ghost transclusion entries on many pages)
9263
Scribunto
text/plain
local TemplateData = {
item = 46997995,
serial = "2025-02-07",
suite = "TemplateData"
}
local Failsafe = TemplateData
local Config = {
-- Multiple option names mapped into unique internal fields.
basicCnf = {
catProblem = "strange",
classMultiColumns = "selMultClm",
classNoNumTOC = "suppressTOCnum",
classTable = "classTable",
cssParWrap = "cssTabWrap",
cssParams = "cssTable",
docpageCreate = "suffix",
docpageDetect = "subpage",
helpAliases = "supportAliases",
helpBoolean = "support4boolean",
helpContent = "support4content",
helpDate = "support4date",
helpDefault = "support4default",
helpFile = "support4wiki-file-name",
helpFormat = "supportFormat",
helpLine = "support4line",
helpNumber = "support4number",
helpPage = "support4wiki-page-name",
helpString = "support4string",
helpTemplate = "support4wiki-template-name",
helpURL = "support4url",
helpUser = "support4wiki-user-name",
msgDescMiss = "solo",
tStylesMultiColumns = "stylesMultClm",
tStylesTOCnum = "stylesTOCnum"
},
classTable = { "wikitable" }, -- Classes for params table
cssTable = false, -- Styles for params table
cssTabWrap = false, -- Styles for params table wrapper
debug = false,
debugmultilang = "#c0c0c0",
jsonDebug = "json-code-lint", -- Class for jsonDebug tool
loudly = false, -- Show exported element, etc.
solo = false, -- Complaint on missing description
strange = false, -- Title of maintenance category
subpage = false, -- Pattern to identify subpage
suffix = false, -- Subpage creation scheme
suppressTOCnum = false -- Class for TOC number suppression
}
local Data = {
div = false, -- <div class="mw-templatedata-doc-wrap">
got = false, -- table, initial templatedata object
heirs = false, -- table, params that are inherited
jump = false, -- source position at end of "params"
less = false, -- main description missing
lasting = false, -- old syntax encountered
lazy = false, -- doc mode; do not generate effective <templatedata>
leading = false, -- show TOC
-- low = false, -- 1= mode
order = false, -- parameter sequence
params = false, -- table, exported parameters
scream = false, -- error messages
sibling = false, -- TOC juxtaposed
slang = nil, -- project/user language code
slim = false, -- JSON reduced to plain
source = false, -- JSON input
strip = false, -- <templatedata> evaluation
tag = false, -- table, exported root element
title = false, -- page
tree = false -- table, rewritten templatedata object
}
local Permit = {
builder = {
after = "block",
align = "block",
block = "block",
compressed = "block",
dense = "block",
grouped = "inline",
half = "inline",
indent = "block",
inline = "inline",
last = "block",
lead = "block",
newlines = "*",
spaced = "inline"
},
colors = {
bg = "var(--background-color-base, #fff)",
deprecated = "#ffcbcb",
fg = "var(--color-base, #000)",
optional = "#eaecf0",
required = "#eaf3ff",
suggested = "#fff",
tableheadbg = "var(--background-color-progressive-subtle, #b3b7ff)"
},
params = {
aliases = "table",
autovalue = "string",
default = "string table I18N nowiki",
deprecated = "boolean string I18N",
description = "string table I18N",
example = "string table I18N nowiki",
inherits = "string",
label = "string table I18N",
required = "boolean",
style = "string table",
suggested = "boolean",
suggestedvalues = "string table number boolean",
type = "string"
},
root = {
description = "string table I18N",
format = "string",
maps = "table",
paramOrder = "table",
params = "table",
sets = "table"
},
search = "[{,]%%s*(['\"])%s%%1%%s*:%%s*%%{",
types = {
boolean = true,
content = true,
date = true,
line = true,
number = true,
string = true,
unknown = true,
url = true,
["string/line"] = "line",
["string/wiki-page-name"] = "wiki-page-name",
["string/wiki-user-name"] = "wiki-user-name",
["unbalanced-wikitext"] = true,
["wiki-file-name"] = true,
["wiki-page-name"] = true,
["wiki-template-name"] = true,
["wiki-user-name"] = true
}
}
local function Fault(alert)
-- Memorize error message.
-- Parameter:
-- alert -- string, error message
if Data.scream then
Data.scream = string.format("%s *** %s", Data.scream, alert)
else
Data.scream = alert
end
end -- Fault()
local function Fetch(ask, allow)
-- Fetch module.
-- Parameter:
-- ask -- string, with name
-- "/global"
-- "JSONutil"
-- "Multilingual"
-- "Text"
-- "WLink"
-- allow -- true: no error if unavailable
-- Returns table of module
-- Error: Module not available
local sign = ask
local r, stem
if sign:sub(1, 1) == "/" then
sign = TemplateData.frame:getTitle() .. sign
else
stem = sign
sign = "Module:" .. stem
end
if TemplateData.extern then
r = TemplateData.extern[sign]
else
TemplateData.extern = {}
end
if not r then
local lucky, g = pcall(require, sign)
if type(g) == "table" then
if stem and type(g[stem]) == "function" then
r = g[stem]()
else
r = g
end
TemplateData.extern[sign] = r
elseif not allow then
error(string.format("Fetch(%s) %s", sign, g), 0)
end
end
return r
end -- Fetch()
local function Foreign()
-- Guess human language, returns slang or not.
if type(Data.slang) == "nil" then
local Multilingual = Fetch("Multilingual", true)
if Multilingual and type(Multilingual.userLangCode) == "function" then
Data.slang = Multilingual.userLangCode()
else
Data.slang = mw.language.getContentLanguage():getCode():lower()
end
end
if Data.slang and mw.ustring.codepoint(Data.slang, 1, 1) > 122 then
Data.slang = false
end
return Data.slang
end -- Foreign()
local function facet(ask, at)
-- Find physical position of parameter definition in JSON.
-- Parameter:
-- ask -- string, parameter name
-- at -- number, physical position within definition
-- Returns number or nil.
local seek = string.format(Permit.search, ask:gsub("%%", "%%%%"):gsub("([%-.()+*?^$%[%]])", "%%%1"))
local i, k, r, slice, source
if not Data.jump then
Data.jump = Data.source:find("params", 2)
if Data.jump then
Data.jump = Data.jump + 7
else
Data.jump = 1
end
end
i, k = Data.source:find(seek, at + Data.jump)
while i and not r do
source = Data.source:sub(k + 1)
slice = source:match('^%s*"([^"]+)"s*:')
if not slice then
slice = source:match("^%s*'([^']+)'%s*:")
end
if (slice and Permit.params[slice]) or source:match("^%s*%}") then
r = k
else
i, k = Data.source:find(seek, k)
end
end -- while i
return r
end -- facet()
local function facilities(apply)
-- Retrieve details of suggestedvalues.
-- Parameter:
-- apply -- table, with plain or enhanced values
-- .suggestedvalues -- table|string|number, or more
-- Returns
-- 1 -- table, with suggestedvalues
-- 2 -- table, with CSS map, or not
-- 3 -- string, with class, or not
-- 4 -- string, with templatestyles, or not
local elements = apply.suggestedvalues
local s = type(elements)
local r1, r2, r3, r4
if s == "table" then
local values = elements.values
if type(values) == "table" then
r1 = values
if type(elements.scroll) == "string" then
r2 = r2 or {}
r2.height = apply.scroll
r2.overflow = "auto"
end
if type(elements.minwidth) == "string" then
local s = type(elements.maxcolumns)
r2 = r2 or {}
r2["column-width"] = elements.minwidth
if s == "string" or s == "number" then
s = tostring(elements.maxcolumns)
r2["column-count"] = s
end
if type(Config.selMultClm) == "string" then
r3 = Config.selMultClm
end
if type(Config.stylesMultClm) == "string" then
local src = Config.stylesMultClm .. "/styles.css"
r4 = TemplateData.frame:extensionTag("templatestyles", nil, { src = src })
end
end
elseif elements and elements ~= "" then
r1 = elements
end
elseif s == "string" then
s = mw.text.trim(about)
if s ~= "" then
r1 = {}
table.insert(r1, { code = s })
end
elseif s == "number" then
r1 = {}
table.insert(r1, { code = tostring(elements) })
end
return r1, r2, r3, r4
end -- facilities()
local function factory(adapt)
-- Retrieve localized text from system message.
-- Parameter:
-- adapt -- string, message ID after "templatedata-"
-- Returns string, with localized text
local o = mw.message.new("templatedata-" .. adapt)
if Foreign() then
o:inLanguage(Data.slang)
end
return o:plain()
end -- factory()
local function faculty(adjust)
-- Test template argument for Boolean.
-- adjust -- string or nil
-- Returns boolean.
local s = type(adjust)
local r
if s == "string" then
r = mw.text.trim(adjust)
r = (r ~= "" and r ~= "0")
elseif s == "boolean" then
r = adjust
else
r = false
end
return r
end -- faculty()
local function failures()
-- Retrieve error collection and category, returns string.
local r
if Data.scream then
local e = mw.html.create("span"):addClass("error"):wikitext(Data.scream)
r = tostring(e)
mw.addWarning("'''TemplateData'''<br />" .. Data.scream)
if Config.strange then
r = string.format("%s[[category:%s]]", r, Config.strange)
end
else
r = ""
end
return r
end -- failures()
local function fair(adjust)
-- Reduce text to one line of plain text, or noexport wikitext blocks.
-- adjust -- string
-- Returns string with adjusted text.
local f = function(a)
return a:gsub("%s*\n%s*", " "):gsub("%s%s+", " ")
end
local tags = {
{
start = "<noexport>",
stop = "</noexport>",
},
{
start = "<exportonly>",
stop = "</exportonly>",
l = false,
},
}
local r = adjust
local i, j, k, s, tag
for m = 1, 2 do
tag = tags[m]
if r:find(tag.start, 1, true) then
s = r
r = ""
i = 1
tag.l = true
j, k = s:find(tag.start, i, true)
while j do
if j > 1 then
r = r .. f(s:sub(i, j - 1))
end
i = k + 1
j, k = s:find(tag.stop, i, true)
if j then
if m == 1 then
r = r .. s:sub(i, j - 1)
end
i = k + 1
j, k = s:find(tag.start, i, true)
else
Fault("missing " .. tag.stop)
end
end -- while j
r = r .. s:sub(i)
elseif m == 1 then
r = f(r)
end
end -- for m
if tags[2].l then
r = r:gsub("<exportonly>.*</exportonly>", "")
end
return r
end -- fair()
local function fancy(advance, alert)
-- Present JSON source.
-- Parameter:
-- advance -- true, for nice
-- alert -- true, for visible
-- Returns string.
local r
if Data.source then
local support = Config.jsonDebug
local css
if advance then
css = {
height = "6em",
resize = "vertical",
}
r = {
[1] = "syntaxhighlight",
[2] = Data.source,
lang = "json",
style = table.concat(css, ";"),
}
if alert then
r.class(support)
end
r = TemplateData.frame:callParserFunction("#tag", r)
else
css = {
["font-size"] = "0.77em",
["line-height"] = "1.35",
}
if alert then
css.resize = "vertical"
else
css.display = "none"
end
r = mw.html.create("pre"):addClass(support):css(css):wikitext(mw.text.encode(Data.source))
r = tostring(r)
end
r = "\n" .. r
else
r = ""
end
return r
end -- fancy()
local function faraway(alternatives)
-- Retrieve best language version from multilingual text.
-- Parameter:
-- alternatives -- table, to be evaluated
-- Returns
-- 1 -- string, with best match
-- 2 -- table of other versions, if any
local n = 0
local variants = {}
local r1, r2
for k, v in pairs(alternatives) do
if type(v) == "string" then
v = mw.text.trim(v)
if v ~= "" and type(k) == "string" then
k = k:lower()
variants[k] = v
n = n + 1
end
end
end -- for k, v
if n > 0 then
local Multilingual = Fetch("Multilingual", true)
if Multilingual and type(Multilingual.i18n) == "function" then
local show, slang = Multilingual.i18n(variants)
if show then
r1 = show
variants[slang] = nil
r2 = variants
end
end
if not r1 then
Foreign()
for k, v in pairs(variants) do
if n == 1 then
r1 = v
elseif Data.slang == k then
variants[k] = nil
r1 = v
r2 = variants
end
end -- for k, v
end
if r2 and Multilingual then
for k, v in pairs(r2) do
if v and not Multilingual.isLang(k, true) then
Fault(string.format("%s <code>lang=%s</code>", "Invalid", k))
end
end -- for k, v
end
end
return r1, r2
end -- faraway()
local function fashioned(about, asked, assign)
-- Create description head.
-- Parameter:
-- about -- table, supposed to contain description
-- asked -- true, if mandatory description
-- assign -- <block>, if to be equipped
-- Returns <block> with head, or nil.
local para = assign or mw.html.create("div")
local plus, r
if about and about.description then
if type(about.description) == "string" then
para:wikitext(about.description)
else
para:wikitext(about.description[1])
plus = mw.html.create("ul")
plus:css("text-align", "left")
for k, v in pairs(about.description[2]) do
plus:node(
mw.html
.create("li")
:node(mw.html.create("code"):wikitext(k))
:node(mw.html.create("br"))
:wikitext(fair(v))
)
end -- for k, v
if Config.loudly then
plus = mw.html
.create("div")
:css("background-color", Config.debugmultilang)
:css("color", "inherit")
:node(plus)
else
plus:addClass("templatedata-maintain"):css("display", "none")
end
end
elseif Config.solo and asked then
para:addClass("error"):wikitext(Config.solo)
Data.less = true
else
para = false
end
if para then
if plus then
r = mw.html.create("div"):node(para):node(plus)
else
r = para
end
end
return r
end -- fashioned()
local function fatten(access)
-- Create table row for subheadline.
-- Parameter:
-- access -- string, with name
-- Returns <tr>.
local param = Data.tree.params[access]
local sub, sort = access:match("(=+)%s*(%S.*)$")
local headline = mw.html.create(string.format("h%d", #sub))
local r = mw.html.create("tr")
local td = mw.html.create("td"):attr("colspan", "5"):attr("data-sort-value", "!" .. sort)
local s
if param.style then
s = type(param.style)
if s == "table" then
td:css(param.style)
elseif s == "string" then
td:cssText(param.style)
end
end
s = fashioned(param, false, headline)
if s then
headline = s
else
headline:wikitext(sort)
end
td:node(headline)
r:node(td)
return r
end -- fatten()
local function fathers()
-- Merge parameters with inherited values.
local n = 0
local p = Data.params
local t = Data.tree.params
local p2, t2
for k, v in pairs(Data.heirs) do
n = n + 1
end -- for k, v
for i = 1, n do
if Data.heirs then
for k, v in pairs(Data.heirs) do
if v and not Data.heirs[v] then
n = n - 1
t[k].inherits = nil
Data.heirs[k] = nil
p2 = {}
t2 = {}
if p[v] then
for k2, v2 in pairs(p[v]) do
p2[k2] = v2
end -- for k2, v2
if p[k] then
for k2, v2 in pairs(p[k]) do
if type(v2) ~= "nil" then
p2[k2] = v2
end
end -- for k2, v2
end
p[k] = p2
for k2, v2 in pairs(t[v]) do
t2[k2] = v2
end -- for k2, v2
for k2, v2 in pairs(t[k]) do
if type(v2) ~= "nil" then
t2[k2] = v2
end
end -- for k2, v2
t[k] = t2
else
Fault("No params[] inherits " .. v)
end
end
end -- for k, v
end
end -- i = 1, n
if n > 0 then
local s
for k, v in pairs(Data.heirs) do
if v then
if s then
s = string.format("%s | %s", s, k)
else
s = "Circular inherits: " .. k
end
end
end -- for k, v
Fault(s)
end
end -- fathers()
local function favorize()
-- Local customization issues.
local boole = { ["font-size"] = "1.25em" }
local l, cx = pcall(mw.loadData, TemplateData.frame:getTitle() .. "/config")
local scripting, style
TemplateData.ltr = not mw.language.getContentLanguage():isRTL()
if TemplateData.ltr then
scripting = "left"
else
scripting = "right"
end
boole["margin-" .. scripting] = "3em"
Permit.boole = {
[false] = {
css = boole,
lead = true,
show = "☐",
},
[true] = {
css = boole,
lead = true,
show = "☑",
},
}
Permit.css = {}
for k, v in pairs(Permit.colors) do
if k == "tableheadbg" then
k = "tablehead"
end
if k == "fg" then
style = "color"
else
style = "background-color"
end
Permit.css[k] = {}
Permit.css[k][style] = v
end -- for k, v
if type(cx) == "table" then
local c, s
if type(cx.permit) == "table" then
if type(cx.permit.boole) == "table" then
if type(cx.permit.boole[true]) == "table" then
Permit.boole[false] = cx.permit.boole[false]
end
if type(cx.permit.boole[true]) == "table" then
Permit.boole[true] = cx.permit.boole[true]
end
end
if type(cx.permit.css) == "table" then
for k, v in pairs(cx.permit.css) do
if type(v) == "table" then
Permit.css[k] = v
end
end -- for k, v
end
end
for k, v in pairs(Config.basicCnf) do
s = type(cx[k])
if s == "string" or s == "table" then
Config[v] = cx[k]
end
end -- for k, v
end
if type(Config.subpage) ~= "string" or type(Config.suffix) ~= "string" then
local got = mw.message.new("templatedata-doc-subpage")
local suffix
if got:isDisabled() then
suffix = "doc"
else
suffix = got:plain()
end
if type(Config.subpage) ~= "string" then
Config.subpage = string.format("/%s$", suffix)
end
if type(Config.suffix) ~= "string" then
Config.suffix = string.format("%%s/%s", suffix)
end
end
end -- favorize()
local function feasible(all, at, about)
-- Deal with suggestedvalues within parameter.
-- Parameter:
-- all -- parameter details
-- .default
-- .type
-- at -- string, with parameter name
-- about -- suggestedvalues -- table,
-- value and possibly description
-- table may have elements:
-- .code -- mandatory
-- .label -- table|string
-- .support -- table|string
-- .icon -- string
-- .class -- table|string
-- .css -- table
-- .style -- string
-- .less -- true: suppress code
-- Returns
-- 1: mw.html object <ul>
-- 2: sequence table with values, or nil
local h = {}
local e, r1, r2, s, v
if #about > 0 then
for i = 1, #about do
e = about[i]
s = type(e)
if s == "table" then
if type(e.code) == "string" then
s = mw.text.trim(e.code)
if s == "" then
e = nil
else
e.code = s
end
else
e = nil
s = string.format("params.%s.%s[%d] %s", at, "suggestedvalues", i, "MISSING 'code:'")
end
elseif s == "string" then
s = mw.text.trim(e)
if s == "" then
e = nil
s = string.format("params.%s.%s[%d] EMPTY", at, "suggestedvalues", i)
Fault(s)
else
e = { code = s }
end
elseif s == "number" then
e = { code = tostring(e) }
else
s = string.format("params.%s.%s[%d] INVALID", at, "suggestedvalues", i)
Fault(s)
e = false
end
if e then
v = v or {}
table.insert(v, e)
if h[e.code] then
s = string.format("params.%s.%s REPEATED %s", at, "suggestedvalues", e.code)
Fault(s)
else
h[e.code] = true
end
end
end -- for i
else
Fault(string.format("params.%s.suggestedvalues %s", at, "NOT AN ARRAY"))
end
if v then
local code, d, k, less, story, swift, t, u
r1 = mw.html.create("ul")
r2 = {}
for i = 1, #v do
u = mw.html.create("li")
e = v[i]
table.insert(r2, e.code)
story = false
less = (e.less == true)
if not less then
swift = e.code
if e.support then
local scream, support
s = type(e.support)
if s == "string" then
support = e.support
elseif s == "table" then
support = faraway(e.support)
else
scream = "INVALID"
end
if support then
s = mw.text.trim(support)
if s == "" then
scream = "EMPTY"
elseif s:find("[%[%]|%<%>]") then
scream = "BAD PAGE"
else
support = s
end
end
if scream then
s = string.format("params.%s.%s[%d].support %s", at, "suggestedvalues", i, scream)
Fault(s)
else
swift = string.format("[[:%s|%s]]", support, swift)
end
end
if all.type:sub(1, 5) == "wiki-" and swift == e.code then
local rooms = {
file = 6,
temp = 10,
user = 2,
}
local ns = rooms[all.type:sub(6, 9)] or 0
t = mw.title.makeTitle(ns, swift)
if t and t.exists then
swift = string.format("[[:%s|%s]]", t.prefixedText, swift)
end
end
if e.code == all.default then
k = 800
else
k = 300
end
code =
mw.html.create("code"):css("font-weight", tostring(k)):css("white-space", "nowrap"):wikitext(swift)
u:node(code)
end
if e.class then
s = type(e.class)
if s == "string" then
u:addClass(e.class)
elseif s == "table" then
for k, s in pairs(e.class) do
u:addClass(s)
end -- for k, s
else
s = string.format("params.%s.%s[%d].class INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if e.css then
if type(e.css) == "table" then
u:css(e.css)
else
s = string.format("params.%s.%s[%d].css INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if e.style then
if type(e.style) == "string" then
u:cssText(e.style)
else
s = string.format("params.%s.%s[%d].style INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if all.type == "wiki-file-name" and not e.icon then
e.icon = e.code
end
if e.label then
s = type(e.label)
if s == "string" then
s = mw.text.trim(e.label)
if s == "" then
s = string.format("params.%s.%s[%d].label %s", at, "suggestedvalues", i, "EMPTY")
Fault(s)
else
story = s
end
elseif s == "table" then
story = faraway(e.label)
else
s = string.format("params.%s.%s[%d].label INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
s = false
if type(e.icon) == "string" then
t = mw.title.makeTitle(6, e.icon)
if t and t.file.exists then
local g = mw.html.create("span")
s = string.format("[[%s|16px]]", t.prefixedText)
g:attr("role", "presentation"):wikitext(s)
s = tostring(g)
end
end
if not s and not less and e.label then
s = mw.ustring.char(0x2013)
end
if s then
d = mw.html.create("span"):wikitext(s)
if TemplateData.ltr then
if not less then
d:css("margin-left", "0.5em")
end
if story then
d:css("margin-right", "0.5em")
end
else
if not less then
d:css("margin-right", "0.5em")
end
if story then
d:css("margin-left", "0.5em")
end
end
u:node(d)
end
if story then
u:wikitext(story)
end
r1:newline():node(u)
end -- for i
end
if not r1 and v ~= false then
Fault(string.format("params.%s.suggestedvalues INVALID", at))
r1 = mw.html.create("code"):addClass("error"):wikitext("INVALID")
end
return r1, r2
end -- feasible()
local function feat()
-- Check and store parameter sequence.
if Data.source then
local i = 0
local s
for k, v in pairs(Data.tree.params) do
if i == 0 then
Data.order = {}
i = 1
s = k
else
i = 2
break -- for k, v
end
end -- for k, v
if i > 1 then
local pointers = {}
local points = {}
local given = {}
for k, v in pairs(Data.tree.params) do
i = facet(k, 1)
if type(v) == "table" then
if type(v.label) == "string" then
s = mw.text.trim(v.label)
if s == "" then
s = k
end
else
s = k
end
if given[s] then
if given[s] == 1 then
local scream = "Parameter label '%s' detected multiple times"
Fault(string.format(scream, s))
given[s] = 2
end
else
given[s] = 1
end
end
if i then
table.insert(points, i)
pointers[i] = k
i = facet(k, i)
if i then
s = "Parameter '%s' detected twice"
Fault(string.format(s, k))
end
else
s = "Parameter '%s' not detected"
Fault(string.format(s, k))
end
end -- for k, v
table.sort(points)
for i = 1, #points do
table.insert(Data.order, pointers[points[i]])
end -- i = 1, #points
elseif s then
table.insert(Data.order, s)
end
end
end -- feat()
local function feature(access)
-- Create table row for parameter, check and display violations.
-- Parameter:
-- access -- string, with name
-- Returns <tr>.
local mode, s, status
local fine = function(a)
s = mw.text.trim(a)
return a == s and a ~= "" and not a:find("%|=\n") and not a:find("%s%s")
end
local begin = mw.html.create("td")
local code = mw.html.create("code")
local desc = mw.html.create("td")
local eager = mw.html.create("td")
local legal = true
local param = Data.tree.params[access]
local ranking = { "required", "suggested", "optional", "deprecated" }
local r = mw.html.create("tr")
local styles = "mw-templatedata-doc-param-"
local sort, typed
for k, v in pairs(param) do
if v == "" then
param[k] = false
end
end -- for k, v
-- label
sort = param.label or access
if sort:match("^%d+$") then
begin:attr("data-sort-value", string.format("%05d", tonumber(sort)))
end
begin:css("font-weight", "700"):wikitext(sort)
-- name and aliases
code:css("font-size", "0.92em"):css("white-space", "nowrap"):wikitext(access)
if not fine(access) then
code:addClass("error")
Fault(string.format("Bad ID params.<code>%s</code>", access))
legal = false
begin:attr("data-sort-value", " " .. sort)
end
code = mw.html.create("td"):addClass(styles .. "name"):node(code)
if access:match("^%d+$") then
code:attr("data-sort-value", string.format("%05d", tonumber(access)))
end
if type(param.aliases) == "table" then
local lapsus, syn
for k, v in pairs(param.aliases) do
code:tag("br")
if type(v) == "string" then
if not fine(v) then
lapsus = true
code:node(mw.html.create("span"):addClass("error"):css("font-style", "italic"):wikitext("string"))
:wikitext(s)
else
if Config.supportAliases then
s = string.format("[[%s|%s]]", Config.supportAliases, mw.text.nowiki(s))
end
syn = mw.html.create("span"):addClass(styles .. "alias"):css("white-space", "nowrap"):wikitext(s)
code:node(syn)
end
else
lapsus = true
code:node(mw.html.create("code"):addClass("error"):wikitext(type(v)))
end
end -- for k, v
if lapsus then
s = string.format("params.<code>%s</code>.aliases", access)
Fault(factory("invalid-value"):gsub("$1", s))
legal = false
end
end
-- description etc.
s = fashioned(param)
if s then
desc:node(s)
end
if param.style then
s = type(param.style)
if s == "table" then
desc:css(param.style)
elseif s == "string" then
desc:cssText(param.style)
end
end
if param.suggestedvalues or param.default or param.example or param.autovalue then
local details = {
"suggestedvalues",
"default",
"example",
"autovalue",
}
local dl = mw.html.create("dl")
local dd, section, show
for i = 1, #details do
s = details[i]
show = param[s]
if show then
dd = mw.html.create("dd")
section = factory("doc-param-" .. s)
if s == "default" and Config.support4default then
section = string.format("[[%s|%s]]", Config.support4default, mw.text.nowiki(section))
end
if param.type == "boolean" and (show == "0" or show == "1") then
local boole = Permit.boole[(show == "1")]
if boole.lead == true then
dd:node(mw.html.create("code"):wikitext(show)):wikitext(" ")
end
if type(boole.show) == "string" then
local v = mw.html.create("span"):attr("aria-hidden", "true"):wikitext(boole.show)
if boole.css then
v:css(boole.css)
end
dd:node(v)
end
if type(boole.suffix) == "string" then
dd:wikitext(boole.suffix)
end
if boole.lead == false then
dd:wikitext(" "):node(mw.html.create("code"):wikitext(show))
end
elseif s == "suggestedvalues" then
local v, css, class, ts = facilities(param)
if v then
local ul
ul, v = feasible(param, access, v)
if v then
dd:newline():node(ul)
if css then
dd:css(css)
if class then
dd:addClass(class)
end
if ts then
dd:newline()
dd:node(ts)
end
end
Data.params[access].suggestedvalues = v
end
end
else
dd:wikitext(show)
end
dl:node(mw.html.create("dt"):wikitext(section)):node(dd)
end
end -- i = 1, #details
desc:node(dl)
end
-- type
if type(param.type) == "string" then
param.type = mw.text.trim(param.type)
if param.type == "" then
param.type = false
end
end
if param.type then
s = Permit.types[param.type]
typed = mw.html.create("td"):addClass(styles .. "type")
if s then
if s == "string" then
Data.params[access].type = s
typed:wikitext(factory("doc-param-type-" .. s)):tag("br")
typed:node(mw.html.create("span"):addClass("error"):wikitext(param.type))
Data.lasting = true
else
local support = Config["support4" .. param.type]
s = factory("doc-param-type-" .. param.type)
if support then
s = string.format("[[%s|%s]]", support, s)
end
typed:wikitext(s)
end
else
Data.params[access].type = "unknown"
typed:addClass("error"):wikitext("INVALID")
s = string.format("params.<code>%s</code>.type", access)
Fault(factory("invalid-value"):gsub("$1", s))
legal = false
end
else
typed = mw.html.create("td"):wikitext(factory("doc-param-type-unknown"))
Data.params[access].type = "unknown"
if param.default then
Data.params[access].default = nil
Fault("Default value requires <code>type</code>")
legal = false
end
end
typed:addClass("navigation-not-searchable")
-- status
if param.required then
mode = 1
if param.autovalue then
Fault(string.format("autovalued <code>%s</code> required", access))
legal = false
end
if param.default then
Fault(string.format("Defaulted <code>%s</code> required", access))
legal = false
end
if param.deprecated then
Fault(string.format("Required deprecated <code>%s</code>", access))
legal = false
end
elseif param.deprecated then
mode = 4
elseif param.suggested then
mode = 2
else
mode = 3
end
status = ranking[mode]
ranking = factory("doc-param-status-" .. status)
if mode == 1 or mode == 4 then
ranking = mw.html.create("span"):css("font-weight", "700"):wikitext(ranking)
if type(param.deprecated) == "string" then
ranking:tag("br")
ranking:wikitext(param.deprecated)
end
if param.suggested and mode == 4 then
s = string.format("Suggesting deprecated <code>%s</code>", access)
Fault(s)
legal = false
end
end
eager
:attr("data-sort-value", tostring(mode))
:node(ranking)
:addClass(string.format("%sstatus-%s %s", styles, status, "navigation-not-searchable"))
-- <tr>
r:attr("id", "templatedata:" .. mw.uri.anchorEncode(access))
:css(Permit.css[status])
:addClass(styles .. status)
:node(begin)
:node(code)
:node(desc)
:node(typed)
:node(eager)
:newline()
if not legal then
r:css("border", "3px solid #f00")
end
return r
end -- feature()
local function features()
-- Create <table> for parameters.
-- Returns <table>, or nil.
local r
if Data.tree and Data.tree.params then
local tbl = mw.html.create("table")
local tr = mw.html.create("tr")
feat()
if Data.order and #Data.order > 1 then
tbl:addClass("sortable")
end
if type(Config.classTable) == "table" then
for k, v in pairs(Config.classTable) do
tbl:addClass(v)
end -- for k, v
end
if type(Config.cssTable) == "table" then
tbl:css(Config.cssTable)
end
tr:addClass("navigation-not-searchable")
:node(
mw.html.create("th"):attr("colspan", "2"):css(Permit.css.tablehead):wikitext(factory("doc-param-name"))
)
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-desc")))
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-type")))
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-status")))
tbl
:newline()
-- :node( mw.html.create( "thead" )
:node(tr)
-- )
:newline()
if Data.order then
local leave, s
for i = 1, #Data.order do
s = Data.order[i]
if s:sub(1, 1) == "=" then
leave = true
tbl:node(fatten(s))
Data.order[i] = false
elseif s:match("[=|]") then
Fault(string.format("Bad param <code>%s</code>", s))
else
tbl:node(feature(s))
end
end -- for i = 1, #Data.order
if leave then
for i = #Data.order, 1, -1 do
if not Data.order[i] then
table.remove(Data.order, i)
end
end -- for i = #Data.order, 1, -1
end
Data.tag.paramOrder = Data.order
end
if Config.cssTabWrap or Data.scroll then
r = mw.html.create("div")
if type(Config.cssTabWrap) == "table" then
r:css(Config.cssTabWrap)
elseif type(Config.cssTabWrap) == "string" then
-- deprecated
r:cssText(Config.cssTabWrap)
end
if Data.scroll then
r:css("height", Data.scroll):css("overflow", "auto")
end
r:node(tbl)
else
r = tbl
end
end
return r
end -- features()
local function fellow(any, assigned, at)
-- Check sets[] parameter and issue error message, if necessary.
-- Parameter:
-- any -- should be number
-- assigned -- parameter name
-- at -- number, of set
local s
if type(any) ~= "number" then
s = "<code>sets[%d].params[%s]</code>??"
Fault(string.format(s, at, mw.text.nowiki(tostring(any))))
elseif type(assigned) == "string" then
if not Data.got.params[assigned] then
s = "<code>sets[%d].params %s</code> is undefined"
Fault(string.format(s, at, assigned))
end
else
s = "<code>sets[%d].params[%d] = %s</code>??"
Fault(string.format(s, k, type(assigned)))
end
end -- fellow()
local function fellows()
-- Check sets[] and issue error message, if necessary.
local s
if type(Data.got.sets) == "table" then
if type(Data.got.params) == "table" then
for k, v in pairs(Data.got.sets) do
if type(k) == "number" then
if type(v) == "table" then
for ek, ev in pairs(v) do
if ek == "label" then
s = type(ev)
if s ~= "string" and s ~= "table" then
s = "<code>sets[%d].label</code>??"
Fault(string.format(s, k))
end
elseif ek == "params" and type(ev) == "table" then
for pk, pv in pairs(ev) do
fellow(pk, pv, k)
end -- for pk, pv
else
ek = mw.text.nowiki(tostring(ek))
s = "<code>sets[%d][%s]</code>??"
Fault(string.format(s, k, ek))
end
end -- for ek, ev
else
k = mw.text.nowiki(tostring(k))
v = mw.text.nowiki(tostring(v))
s = string.format("<code>sets[%s][%s]</code>??", k, v)
Fault(s)
end
else
k = mw.text.nowiki(tostring(k))
s = string.format("<code>sets[%s]</code> ?????", k)
Fault(s)
end
end -- for k, v
else
s = "<code>params</code> required for <code>sets</code>"
Fault(s)
end
else
s = "<code>sets</code> needs to be of <code>object</code> type"
Fault(s)
end
end -- fellows()
local function finalize(advance)
-- Wrap presentation into frame.
-- Parameter:
-- advance -- true, for nice
-- Returns string.
local r, lapsus
if Data.div then
r = tostring(Data.div)
elseif Data.strip then
r = Data.strip
else
lapsus = true
r = ""
end
r = r .. failures()
if Data.source then
local live = (advance or lapsus)
if not live then
live = TemplateData.frame:preprocess("{{REVISIONID}}")
live = (live == "")
end
if live then
r = r .. fancy(advance, lapsus)
end
end
return r
end -- finalize()
local function find()
-- Find JSON data within page source (title).
-- Returns string, or nil.
local s = Data.title:getContent()
local i, j = s:find("<templatedata>", 1, true)
local r
if i then
local k = s:find("</templatedata>", j, true)
if k then
r = mw.text.trim(s:sub(j + 1, k - 1))
end
end
return r
end -- find()
local function flat(adjust)
-- Remove formatting from text string for VisualEditor.
-- Parameter:
-- arglist -- string, to be stripped, or nil
-- Returns string, or nil.
local r
if adjust then
r = adjust:gsub("\n", " ")
if r:find("<noexport>", 1, true) then
r = r:gsub("<noexport>.*</noexport>", "")
end
if r:find("<exportonly>", 1, true) then
r = r:gsub("</?exportonly>", "")
end
if r:find("''", 1, true) then
r = r:gsub("'''", ""):gsub("''", "")
end
if r:find("<", 1, true) then
local Text = Fetch("Text")
r = r:gsub("<br */?>", "\r\n"):gsub("<sup>2</sup>", "²"):gsub("<sup>3</sup>", "³")
r = Text.getPlain(r)
end
if r:find("[", 1, true) then
local WLink = Fetch("WLink")
if WLink.isBracketedURL(r) then
r = r:gsub("%[([hf]tt?ps?://%S+) [^%]]+%]", "%1")
end
r = WLink.getPlain(r)
end
if r:find("&", 1, true) then
r = mw.text.decode(r)
if r:find("­", 1, true) then
r = r:gsub("­", "")
end
end
end
return r
end -- flat()
local function flush()
-- JSON encode narrowed input; obey unnamed (numerical) parameters.
-- Returns <templatedata> JSON string.
local r
if Data.tag then
r = mw.text.jsonEncode(Data.tag):gsub("%}$", ",")
else
r = "{"
end
r = r .. '\n"params":{'
if Data.order then
local sep = ""
local s
for i = 1, #Data.order do
s = Data.order[i]
r = string.format("%s%s\n%s:%s", r, sep, mw.text.jsonEncode(s), mw.text.jsonEncode(Data.params[s]))
sep = ",\n"
end -- for i = 1, #Data.order
end
r = r .. "\n}\n}"
return r
end -- flush()
local function focus(access)
-- Check components; focus multilingual description, build trees.
-- Parameter:
-- access -- string, name of parameter, nil for root
local f = function(a, at)
local r
if at then
r = string.format("<code>params.%s</code>", at)
else
r = "''root''"
end
if a then
r = string.format("%s<code>.%s</code>", r, a)
end
return r
end
local parent
if access then
parent = Data.got.params[access]
else
parent = Data.got
end
if type(parent) == "table" then
local elem, permit, s, scope, slot, tag, target
if access then
permit = Permit.params
if type(access) == "number" then
slot = tostring(access)
else
slot = access
end
else
permit = Permit.root
end
for k, v in pairs(parent) do
scope = permit[k]
if scope then
s = type(v)
if s == "string" and k ~= "format" then
v = mw.text.trim(v)
end
if scope:find(s, 1, true) then
if scope:find("I18N", 1, true) then
if s == "string" then
elem = fair(v)
elseif s == "table" then
local translated
v, translated = faraway(v)
if v then
if translated and k == "description" then
elem = {
[1] = fair(v),
[2] = translated,
}
else
elem = fair(v)
end
else
elem = false
end
end
if type(v) == "string" then
if k == "deprecated" then
if v == "1" then
v = true
elseif v == "0" then
v = false
end
elem = v
elseif scope:find("nowiki", 1, true) then
elem = mw.text.nowiki(v)
elem = elem:gsub(" " .. string.char(10), "<br>")
v = v:gsub(string.char(13), "")
else
v = flat(v)
end
elseif s == "boolean" then
if scope:find("boolean", 1, true) then
elem = v
else
s = "Type <code>boolean</code> bad for " .. f(k, slot)
Fault(s)
end
end
else
if k == "params" and not access then
v = nil
elem = nil
elseif k == "format" and not access then
elem = mw.text.decode(v)
v = nil
elseif k == "inherits" then
elem = v
if not Data.heirs then
Data.heirs = {}
end
Data.heirs[slot] = v
v = nil
elseif k == "style" then
elem = v
v = nil
elseif s == "string" then
v = mw.text.nowiki(v)
elem = v
else
elem = v
end
end
if type(elem) ~= "nil" then
if not target then
if access then
if not Data.tree.params then
Data.tree.params = {}
end
Data.tree.params[slot] = {}
target = Data.tree.params[slot]
else
Data.tree = {}
target = Data.tree
end
end
target[k] = elem
elem = false
end
if type(v) ~= "nil" then
if not tag then
if access then
if type(v) == "string" and v.sub(1, 1) == "=" then
v = nil
else
if not Data.params then
Data.params = {}
end
Data.params[slot] = {}
tag = Data.params[slot]
end
else
Data.tag = {}
tag = Data.tag
end
end
if type(v) ~= "nil" and k ~= "suggestedvalues" then
tag[k] = v
end
end
else
s = string.format("Type <code>%s</code> bad for %s", scope, f(k, slot))
Fault(s)
end
else
Fault("Unknown component " .. f(k, slot))
end
end -- for k, v
if not access and Data.got.sets then
fellows()
end
else
Fault(f() .. " needs to be of <code>object</code> type")
end
end -- focus()
local function format()
-- Build formatted element.
-- Returns <inline>.
local source = Data.tree.format:lower()
local r, s
if source == "inline" or source == "block" then
r = mw.html.create("i"):wikitext(source)
else
local code
if source:find("|", 1, true) then
local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$"
if source:match(scan) then
code = source:gsub("\n", "N")
else
s = mw.text.nowiki(source):gsub("\n", "\n")
s = tostring(mw.html.create("code"):wikitext(s))
Fault("Invalid format " .. s)
source = false
end
else
local words = mw.text.split(source, "%s+")
local show, start, support, unknown
for i = 1, #words do
s = words[i]
if i == 1 then
start = s
end
support = Permit.builder[s]
if support == start or support == "*" then
Permit.builder[s] = true
elseif s:match("^[1-9]%d?") and Permit.builder.align then
Permit.builder.align = tonumber(s)
else
if unknown then
unknown = string.format("%s %s", unknown, s)
else
unknown = s
end
end
end -- i = 1, #words
if unknown then
s = tostring(mw.html.create("code"):css("white-space", "nowrap"):wikitext(s))
Fault("Unknown/misplaced format keyword " .. s)
source = false
start = false
end
if start == "inline" then
if Permit.builder.half == true then
show = "inline half"
code = "{{_ |_=_}}"
elseif Permit.builder.grouped == true then
show = "inline grouped"
code = "{{_ | _=_}}"
elseif Permit.builder.spaced == true then
show = "inline spaced"
code = "{{_ | _ = _ }}"
end
if Permit.builder.newlines == true then
show = show or "inline"
code = code or "{{_|_=_}}"
show = show .. " newlines"
code = string.format("N%sN", code)
end
elseif start == "block" then
local space = "" -- amid "|" and name
local spaced = " " -- preceding "="
local spacer = " " -- following "="
local suffix = "N" -- closing "}}" on new line
show = "block"
if Permit.builder.indent == true then
start = " "
show = "block indent"
else
start = ""
end
if Permit.builder.compressed == true then
spaced = ""
spacer = ""
show = show .. " compressed"
if Permit.builder.last == true then
show = show .. " last"
else
suffix = ""
end
else
if Permit.builder.lead == true then
show = show .. " lead"
space = " "
end
if type(Permit.builder.align) ~= "string" then
local n
s = " align"
if Permit.builder.align == true then
n = 0
if type(Data.got) == "table" and type(Data.got.params) == "table" then
for k, v in pairs(Data.got.params) do
if type(v) == "table" and not v.deprecated and type(k) == "string" then
k = mw.ustring.len(k)
if k > n then
n = k
end
end
end -- for k, v
end
else
n = Permit.builder.align
if type(n) == "number" and n > 1 then
s = string.format("%s %d", s, n)
else
n = 0 -- How come?
end
end
if n > 1 then
spaced = string.rep("_", n - 1) .. " "
end
show = show .. s
elseif Permit.builder.after == true then
spaced = ""
show = show .. " after"
elseif Permit.builder.dense == true then
spaced = ""
spacer = ""
show = show .. " dense"
end
if Permit.builder.last == true then
suffix = spacer
show = show .. " last"
end
end
code = string.format("N{{_N%s|%s_%s=%s_%s}}N", start, space, spaced, spacer, suffix)
if show == "block" then
show = "block newlines"
end
end
if show then
r = mw.html.create("span"):wikitext(show)
end
end
if code then
source = code:gsub("N", "\n")
code = mw.text.nowiki(code):gsub("N", "\n")
code = mw.html.create("code"):css("margin-left", "1em"):css("margin-right", "1em"):wikitext(code)
if r then
r = mw.html.create("span"):node(r):node(code)
else
r = code
end
end
end
if source and Data.tag then
Data.tag.format = source
end
return r
end -- format()
local function formatter()
-- Build presented documentation.
-- Returns <div>.
local r = mw.html.create("div")
local x = fashioned(Data.tree, true, r)
local s
if x then
r = x
end
if Data.leading then
local toc = mw.html.create("div")
local shift
if Config.suppressTOCnum then
toc:addClass(Config.suppressTOCnum)
if type(Config.stylesTOCnum) == "string" then
local src = Config.stylesTOCnum .. "/styles.css"
s = TemplateData.frame:extensionTag("templatestyles", nil, { src = src })
r:newline():node(s)
end
end
toc:addClass("navigation-not-searchable"):css("margin-top", "0.5em"):wikitext("__TOC__")
if Data.sibling then
local block = mw.html.create("div")
if TemplateData.ltr then
shift = "right"
else
shift = "left"
end
block:css("float", shift):wikitext(Data.sibling)
r:newline():node(block):newline()
end
r:newline():node(toc):newline()
if shift then
r:node(mw.html.create("div"):css("clear", shift)):newline()
end
end
s = features()
if s then
if Data.leading then
r:node(mw.html.create("h" .. Config.nested):wikitext(factory("doc-params"))):newline()
end
r:node(s)
end
if Data.shared then
local global = mw.html.create("div"):attr("id", "templatedata-global")
local shift
if TemplateData.ltr then
shift = "right"
else
shift = "left"
end
global:css("float", shift):wikitext(string.format("[[%s|%s]]", Data.shared, "Global"))
r:newline():node(global)
end
if Data.tree and Data.tree.format then
local e = format()
if e then
local show = "Format"
if Config.supportFormat then
show = string.format("[[%s|%s]]", Config.supportFormat, show)
end
r:node(mw.html.create("p"):addClass("navigation-not-searchable"):wikitext(show .. ": "):node(e))
end
end
return r
end -- formatter()
local function free()
-- Remove JSON comment lines.
if Data.source:find("//", 1, true) then
Data.source:gsub("([{,\"'])(%s*\n%s*//.*\n%s*)([{},\"'])", "%1%3")
end
end -- free()
local function full()
-- Build survey table from JSON data, append invisible <templatedata>.
Data.div = mw.html.create("div"):addClass("mw-templatedata-doc-wrap")
if Permit.css.bg then
Data.div:css(Permit.css.bg)
end
if Permit.css.fg then
Data.div:css(Permit.css.fg)
end
focus()
if Data.tag then
if type(Data.got.params) == "table" then
for k, v in pairs(Data.got.params) do
focus(k)
end -- for k, v
if Data.heirs then
fathers()
end
end
end
Data.div:node(formatter())
if not Data.lazy then
Data.slim = flush()
if TemplateData.frame then
local div = mw.html.create("div")
local tdata = {
[1] = "templatedata",
[2] = Data.slim,
}
Data.strip = TemplateData.frame:callParserFunction("#tag", tdata)
div:wikitext(Data.strip)
if Config.loudly then
Data.div:node(mw.html.create("hr"):css({ height = "7ex" }))
else
div:css("display", "none")
end
Data.div:node(div)
end
end
if Data.lasting then
Fault("deprecated type syntax")
end
if Data.less then
Fault(Config.solo)
end
end -- full()
local function furnish(adapt, arglist)
-- Analyze transclusion.
-- Parameter:
-- adapt -- table, #invoke parameters
-- arglist -- table, template parameters
-- Returns string.
local source
favorize()
-- deprecated:
for k, v in pairs(Config.basicCnf) do
if adapt[k] and adapt[k] ~= "" then
Config[v] = adapt[k]
end
end -- for k, v
if arglist.heading and arglist.heading:match("^[3-6]$") then
Config.nested = arglist.heading
else
Config.nested = "2"
end
Config.loudly = faculty(arglist.debug or adapt.debug)
Data.lazy = faculty(arglist.lazy) and not Config.loudly
Data.leading = faculty(arglist.TOC)
if Data.leading and arglist.TOCsibling then
Data.sibling = mw.text.trim(arglist.TOCsibling)
end
if arglist.lang then
Data.slang = arglist.lang:lower()
elseif adapt.lang then
Data.slang = adapt.lang:lower()
end
if arglist.JSON then
source = arglist.JSON
elseif arglist.Global then
source = TemplateData.getGlobalJSON(arglist.Global, arglist.Local)
elseif arglist[1] then
local s = mw.text.trim(arglist[1])
local start = s:sub(1, 1)
if start == "<" then
Data.strip = s
elseif start == "{" then
source = s
elseif mw.ustring.sub(s, 1, 8) == mw.ustring.char(127, 39, 34, 96, 85, 78, 73, 81) then
Data.strip = s
end
end
if type(arglist.vertical) == "string" and arglist.vertical:match("^%d*%.?%d+[emprx]+$") then
Data.scroll = arglist.vertical
end
if not source then
Data.title = mw.title.getCurrentTitle()
source = find()
if not source and not Data.title.text:match(Config.subpage) then
local s = string.format(Config.suffix, Data.title.prefixedText)
Data.title = mw.title.new(s)
if Data.title.exists then
source = find()
end
end
end
if not Data.lazy then
if not Data.title then
Data.title = mw.title.getCurrentTitle()
end
Data.lazy = Data.title.text:match(Config.subpage)
end
if type(source) == "string" then
TemplateData.getPlainJSON(source)
end
return finalize(faculty(arglist.source))
end -- furnish()
Failsafe.failsafe = function(atleast)
-- Retrieve versioning and check for compliance.
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2024-03-01
local since = atleast
local last = (since == "~")
local linked = (since == "@")
local link = (since == "item")
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type(item) == "number" and item > 0 then
local suited = string.format("Q%d", item)
if link then
r = suited
else
local entity = mw.wikibase.getEntity(suited)
if type(entity) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues(seek)
if type(vsn) == "table" and type(vsn.value) == "string" and vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText == mw.wikibase.getSitelink(suited) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
elseif link then
r = false
end
end
if type(r) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
TemplateData.getGlobalJSON = function(access, adapt)
-- Retrieve TemplateData from a global repository (JSON).
-- Parameter:
-- access -- string, with page specifier (on WikiMedia Commons)
-- adapt -- JSON string or table with local overrides
-- Returns true, if succeeded.
local plugin = Fetch("/global")
local r
if type(plugin) == "table" and type(plugin.fetch) == "function" then
local s, got = plugin.fetch(access, adapt)
if got then
Data.got = got
Data.order = got.paramOrder
Data.shared = s
r = true
full()
else
Fault(s)
end
end
return r
end -- TemplateData.getGlobalJSON()
TemplateData.getPlainJSON = function(adapt)
-- Reduce enhanced JSON data to plain text localized JSON.
-- Parameter:
-- adapt -- string, with enhanced JSON
-- Returns string, or not.
if type(adapt) == "string" then
-- local JSONutil = Fetch("JSONutil", true) -- DON'T check for Module:JSONutil. (doesn't exist in English WP, blocked from creation.)
local JSONutil = nil -- DO act as if Fetch() failed.
Data.source = adapt
free()
if JSONutil then
local Multilingual = Fetch("Multilingual", true)
local f
if Multilingual then
f = Multilingual.i18n
end
Data.got = JSONutil.fetch(Data.source, true, f)
else
local lucky
lucky, Data.got = pcall(mw.text.jsonDecode, Data.source)
end
if type(Data.got) == "table" then
full()
elseif not Data.strip then
local scream = type(Data.got)
if scream == "string" then
scream = Data.got
else
scream = "Data.got: " .. scream
end
Fault("fatal JSON error: " .. scream)
end
end
return Data.slim
end -- TemplateData.getPlainJSON()
TemplateData.test = function(adapt, arglist)
TemplateData.frame = mw.getCurrentFrame()
return furnish(adapt, arglist)
end -- TemplateData.test()
-- Export.
local p = {}
p.f = function(frame)
-- Template call.
local lucky, r
TemplateData.frame = frame
lucky, r = pcall(furnish, frame.args, frame:getParent().args)
if not lucky then
Fault("INTERNAL: " .. r)
r = failures()
end
return r
end -- p.f
p.failsafe = function(frame)
-- Versioning interface.
local s = type(frame)
local since
if s == "table" then
since = frame.args[1]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim(since)
if since == "" then
since = false
end
end
return Failsafe.failsafe(since) or ""
end -- p.failsafe
p.TemplateData = function()
-- Module interface.
return TemplateData
end
setmetatable(p, {
__call = function(func, ...)
setmetatable(p, nil)
return Failsafe
end,
})
return p
2dd3b90kpdohdijcui9w39wr2ft47sq
9264
9263
2026-08-23T03:37:39Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Format_TemplateData]]
9263
Scribunto
text/plain
local TemplateData = {
item = 46997995,
serial = "2025-02-07",
suite = "TemplateData"
}
local Failsafe = TemplateData
local Config = {
-- Multiple option names mapped into unique internal fields.
basicCnf = {
catProblem = "strange",
classMultiColumns = "selMultClm",
classNoNumTOC = "suppressTOCnum",
classTable = "classTable",
cssParWrap = "cssTabWrap",
cssParams = "cssTable",
docpageCreate = "suffix",
docpageDetect = "subpage",
helpAliases = "supportAliases",
helpBoolean = "support4boolean",
helpContent = "support4content",
helpDate = "support4date",
helpDefault = "support4default",
helpFile = "support4wiki-file-name",
helpFormat = "supportFormat",
helpLine = "support4line",
helpNumber = "support4number",
helpPage = "support4wiki-page-name",
helpString = "support4string",
helpTemplate = "support4wiki-template-name",
helpURL = "support4url",
helpUser = "support4wiki-user-name",
msgDescMiss = "solo",
tStylesMultiColumns = "stylesMultClm",
tStylesTOCnum = "stylesTOCnum"
},
classTable = { "wikitable" }, -- Classes for params table
cssTable = false, -- Styles for params table
cssTabWrap = false, -- Styles for params table wrapper
debug = false,
debugmultilang = "#c0c0c0",
jsonDebug = "json-code-lint", -- Class for jsonDebug tool
loudly = false, -- Show exported element, etc.
solo = false, -- Complaint on missing description
strange = false, -- Title of maintenance category
subpage = false, -- Pattern to identify subpage
suffix = false, -- Subpage creation scheme
suppressTOCnum = false -- Class for TOC number suppression
}
local Data = {
div = false, -- <div class="mw-templatedata-doc-wrap">
got = false, -- table, initial templatedata object
heirs = false, -- table, params that are inherited
jump = false, -- source position at end of "params"
less = false, -- main description missing
lasting = false, -- old syntax encountered
lazy = false, -- doc mode; do not generate effective <templatedata>
leading = false, -- show TOC
-- low = false, -- 1= mode
order = false, -- parameter sequence
params = false, -- table, exported parameters
scream = false, -- error messages
sibling = false, -- TOC juxtaposed
slang = nil, -- project/user language code
slim = false, -- JSON reduced to plain
source = false, -- JSON input
strip = false, -- <templatedata> evaluation
tag = false, -- table, exported root element
title = false, -- page
tree = false -- table, rewritten templatedata object
}
local Permit = {
builder = {
after = "block",
align = "block",
block = "block",
compressed = "block",
dense = "block",
grouped = "inline",
half = "inline",
indent = "block",
inline = "inline",
last = "block",
lead = "block",
newlines = "*",
spaced = "inline"
},
colors = {
bg = "var(--background-color-base, #fff)",
deprecated = "#ffcbcb",
fg = "var(--color-base, #000)",
optional = "#eaecf0",
required = "#eaf3ff",
suggested = "#fff",
tableheadbg = "var(--background-color-progressive-subtle, #b3b7ff)"
},
params = {
aliases = "table",
autovalue = "string",
default = "string table I18N nowiki",
deprecated = "boolean string I18N",
description = "string table I18N",
example = "string table I18N nowiki",
inherits = "string",
label = "string table I18N",
required = "boolean",
style = "string table",
suggested = "boolean",
suggestedvalues = "string table number boolean",
type = "string"
},
root = {
description = "string table I18N",
format = "string",
maps = "table",
paramOrder = "table",
params = "table",
sets = "table"
},
search = "[{,]%%s*(['\"])%s%%1%%s*:%%s*%%{",
types = {
boolean = true,
content = true,
date = true,
line = true,
number = true,
string = true,
unknown = true,
url = true,
["string/line"] = "line",
["string/wiki-page-name"] = "wiki-page-name",
["string/wiki-user-name"] = "wiki-user-name",
["unbalanced-wikitext"] = true,
["wiki-file-name"] = true,
["wiki-page-name"] = true,
["wiki-template-name"] = true,
["wiki-user-name"] = true
}
}
local function Fault(alert)
-- Memorize error message.
-- Parameter:
-- alert -- string, error message
if Data.scream then
Data.scream = string.format("%s *** %s", Data.scream, alert)
else
Data.scream = alert
end
end -- Fault()
local function Fetch(ask, allow)
-- Fetch module.
-- Parameter:
-- ask -- string, with name
-- "/global"
-- "JSONutil"
-- "Multilingual"
-- "Text"
-- "WLink"
-- allow -- true: no error if unavailable
-- Returns table of module
-- Error: Module not available
local sign = ask
local r, stem
if sign:sub(1, 1) == "/" then
sign = TemplateData.frame:getTitle() .. sign
else
stem = sign
sign = "Module:" .. stem
end
if TemplateData.extern then
r = TemplateData.extern[sign]
else
TemplateData.extern = {}
end
if not r then
local lucky, g = pcall(require, sign)
if type(g) == "table" then
if stem and type(g[stem]) == "function" then
r = g[stem]()
else
r = g
end
TemplateData.extern[sign] = r
elseif not allow then
error(string.format("Fetch(%s) %s", sign, g), 0)
end
end
return r
end -- Fetch()
local function Foreign()
-- Guess human language, returns slang or not.
if type(Data.slang) == "nil" then
local Multilingual = Fetch("Multilingual", true)
if Multilingual and type(Multilingual.userLangCode) == "function" then
Data.slang = Multilingual.userLangCode()
else
Data.slang = mw.language.getContentLanguage():getCode():lower()
end
end
if Data.slang and mw.ustring.codepoint(Data.slang, 1, 1) > 122 then
Data.slang = false
end
return Data.slang
end -- Foreign()
local function facet(ask, at)
-- Find physical position of parameter definition in JSON.
-- Parameter:
-- ask -- string, parameter name
-- at -- number, physical position within definition
-- Returns number or nil.
local seek = string.format(Permit.search, ask:gsub("%%", "%%%%"):gsub("([%-.()+*?^$%[%]])", "%%%1"))
local i, k, r, slice, source
if not Data.jump then
Data.jump = Data.source:find("params", 2)
if Data.jump then
Data.jump = Data.jump + 7
else
Data.jump = 1
end
end
i, k = Data.source:find(seek, at + Data.jump)
while i and not r do
source = Data.source:sub(k + 1)
slice = source:match('^%s*"([^"]+)"s*:')
if not slice then
slice = source:match("^%s*'([^']+)'%s*:")
end
if (slice and Permit.params[slice]) or source:match("^%s*%}") then
r = k
else
i, k = Data.source:find(seek, k)
end
end -- while i
return r
end -- facet()
local function facilities(apply)
-- Retrieve details of suggestedvalues.
-- Parameter:
-- apply -- table, with plain or enhanced values
-- .suggestedvalues -- table|string|number, or more
-- Returns
-- 1 -- table, with suggestedvalues
-- 2 -- table, with CSS map, or not
-- 3 -- string, with class, or not
-- 4 -- string, with templatestyles, or not
local elements = apply.suggestedvalues
local s = type(elements)
local r1, r2, r3, r4
if s == "table" then
local values = elements.values
if type(values) == "table" then
r1 = values
if type(elements.scroll) == "string" then
r2 = r2 or {}
r2.height = apply.scroll
r2.overflow = "auto"
end
if type(elements.minwidth) == "string" then
local s = type(elements.maxcolumns)
r2 = r2 or {}
r2["column-width"] = elements.minwidth
if s == "string" or s == "number" then
s = tostring(elements.maxcolumns)
r2["column-count"] = s
end
if type(Config.selMultClm) == "string" then
r3 = Config.selMultClm
end
if type(Config.stylesMultClm) == "string" then
local src = Config.stylesMultClm .. "/styles.css"
r4 = TemplateData.frame:extensionTag("templatestyles", nil, { src = src })
end
end
elseif elements and elements ~= "" then
r1 = elements
end
elseif s == "string" then
s = mw.text.trim(about)
if s ~= "" then
r1 = {}
table.insert(r1, { code = s })
end
elseif s == "number" then
r1 = {}
table.insert(r1, { code = tostring(elements) })
end
return r1, r2, r3, r4
end -- facilities()
local function factory(adapt)
-- Retrieve localized text from system message.
-- Parameter:
-- adapt -- string, message ID after "templatedata-"
-- Returns string, with localized text
local o = mw.message.new("templatedata-" .. adapt)
if Foreign() then
o:inLanguage(Data.slang)
end
return o:plain()
end -- factory()
local function faculty(adjust)
-- Test template argument for Boolean.
-- adjust -- string or nil
-- Returns boolean.
local s = type(adjust)
local r
if s == "string" then
r = mw.text.trim(adjust)
r = (r ~= "" and r ~= "0")
elseif s == "boolean" then
r = adjust
else
r = false
end
return r
end -- faculty()
local function failures()
-- Retrieve error collection and category, returns string.
local r
if Data.scream then
local e = mw.html.create("span"):addClass("error"):wikitext(Data.scream)
r = tostring(e)
mw.addWarning("'''TemplateData'''<br />" .. Data.scream)
if Config.strange then
r = string.format("%s[[category:%s]]", r, Config.strange)
end
else
r = ""
end
return r
end -- failures()
local function fair(adjust)
-- Reduce text to one line of plain text, or noexport wikitext blocks.
-- adjust -- string
-- Returns string with adjusted text.
local f = function(a)
return a:gsub("%s*\n%s*", " "):gsub("%s%s+", " ")
end
local tags = {
{
start = "<noexport>",
stop = "</noexport>",
},
{
start = "<exportonly>",
stop = "</exportonly>",
l = false,
},
}
local r = adjust
local i, j, k, s, tag
for m = 1, 2 do
tag = tags[m]
if r:find(tag.start, 1, true) then
s = r
r = ""
i = 1
tag.l = true
j, k = s:find(tag.start, i, true)
while j do
if j > 1 then
r = r .. f(s:sub(i, j - 1))
end
i = k + 1
j, k = s:find(tag.stop, i, true)
if j then
if m == 1 then
r = r .. s:sub(i, j - 1)
end
i = k + 1
j, k = s:find(tag.start, i, true)
else
Fault("missing " .. tag.stop)
end
end -- while j
r = r .. s:sub(i)
elseif m == 1 then
r = f(r)
end
end -- for m
if tags[2].l then
r = r:gsub("<exportonly>.*</exportonly>", "")
end
return r
end -- fair()
local function fancy(advance, alert)
-- Present JSON source.
-- Parameter:
-- advance -- true, for nice
-- alert -- true, for visible
-- Returns string.
local r
if Data.source then
local support = Config.jsonDebug
local css
if advance then
css = {
height = "6em",
resize = "vertical",
}
r = {
[1] = "syntaxhighlight",
[2] = Data.source,
lang = "json",
style = table.concat(css, ";"),
}
if alert then
r.class(support)
end
r = TemplateData.frame:callParserFunction("#tag", r)
else
css = {
["font-size"] = "0.77em",
["line-height"] = "1.35",
}
if alert then
css.resize = "vertical"
else
css.display = "none"
end
r = mw.html.create("pre"):addClass(support):css(css):wikitext(mw.text.encode(Data.source))
r = tostring(r)
end
r = "\n" .. r
else
r = ""
end
return r
end -- fancy()
local function faraway(alternatives)
-- Retrieve best language version from multilingual text.
-- Parameter:
-- alternatives -- table, to be evaluated
-- Returns
-- 1 -- string, with best match
-- 2 -- table of other versions, if any
local n = 0
local variants = {}
local r1, r2
for k, v in pairs(alternatives) do
if type(v) == "string" then
v = mw.text.trim(v)
if v ~= "" and type(k) == "string" then
k = k:lower()
variants[k] = v
n = n + 1
end
end
end -- for k, v
if n > 0 then
local Multilingual = Fetch("Multilingual", true)
if Multilingual and type(Multilingual.i18n) == "function" then
local show, slang = Multilingual.i18n(variants)
if show then
r1 = show
variants[slang] = nil
r2 = variants
end
end
if not r1 then
Foreign()
for k, v in pairs(variants) do
if n == 1 then
r1 = v
elseif Data.slang == k then
variants[k] = nil
r1 = v
r2 = variants
end
end -- for k, v
end
if r2 and Multilingual then
for k, v in pairs(r2) do
if v and not Multilingual.isLang(k, true) then
Fault(string.format("%s <code>lang=%s</code>", "Invalid", k))
end
end -- for k, v
end
end
return r1, r2
end -- faraway()
local function fashioned(about, asked, assign)
-- Create description head.
-- Parameter:
-- about -- table, supposed to contain description
-- asked -- true, if mandatory description
-- assign -- <block>, if to be equipped
-- Returns <block> with head, or nil.
local para = assign or mw.html.create("div")
local plus, r
if about and about.description then
if type(about.description) == "string" then
para:wikitext(about.description)
else
para:wikitext(about.description[1])
plus = mw.html.create("ul")
plus:css("text-align", "left")
for k, v in pairs(about.description[2]) do
plus:node(
mw.html
.create("li")
:node(mw.html.create("code"):wikitext(k))
:node(mw.html.create("br"))
:wikitext(fair(v))
)
end -- for k, v
if Config.loudly then
plus = mw.html
.create("div")
:css("background-color", Config.debugmultilang)
:css("color", "inherit")
:node(plus)
else
plus:addClass("templatedata-maintain"):css("display", "none")
end
end
elseif Config.solo and asked then
para:addClass("error"):wikitext(Config.solo)
Data.less = true
else
para = false
end
if para then
if plus then
r = mw.html.create("div"):node(para):node(plus)
else
r = para
end
end
return r
end -- fashioned()
local function fatten(access)
-- Create table row for subheadline.
-- Parameter:
-- access -- string, with name
-- Returns <tr>.
local param = Data.tree.params[access]
local sub, sort = access:match("(=+)%s*(%S.*)$")
local headline = mw.html.create(string.format("h%d", #sub))
local r = mw.html.create("tr")
local td = mw.html.create("td"):attr("colspan", "5"):attr("data-sort-value", "!" .. sort)
local s
if param.style then
s = type(param.style)
if s == "table" then
td:css(param.style)
elseif s == "string" then
td:cssText(param.style)
end
end
s = fashioned(param, false, headline)
if s then
headline = s
else
headline:wikitext(sort)
end
td:node(headline)
r:node(td)
return r
end -- fatten()
local function fathers()
-- Merge parameters with inherited values.
local n = 0
local p = Data.params
local t = Data.tree.params
local p2, t2
for k, v in pairs(Data.heirs) do
n = n + 1
end -- for k, v
for i = 1, n do
if Data.heirs then
for k, v in pairs(Data.heirs) do
if v and not Data.heirs[v] then
n = n - 1
t[k].inherits = nil
Data.heirs[k] = nil
p2 = {}
t2 = {}
if p[v] then
for k2, v2 in pairs(p[v]) do
p2[k2] = v2
end -- for k2, v2
if p[k] then
for k2, v2 in pairs(p[k]) do
if type(v2) ~= "nil" then
p2[k2] = v2
end
end -- for k2, v2
end
p[k] = p2
for k2, v2 in pairs(t[v]) do
t2[k2] = v2
end -- for k2, v2
for k2, v2 in pairs(t[k]) do
if type(v2) ~= "nil" then
t2[k2] = v2
end
end -- for k2, v2
t[k] = t2
else
Fault("No params[] inherits " .. v)
end
end
end -- for k, v
end
end -- i = 1, n
if n > 0 then
local s
for k, v in pairs(Data.heirs) do
if v then
if s then
s = string.format("%s | %s", s, k)
else
s = "Circular inherits: " .. k
end
end
end -- for k, v
Fault(s)
end
end -- fathers()
local function favorize()
-- Local customization issues.
local boole = { ["font-size"] = "1.25em" }
local l, cx = pcall(mw.loadData, TemplateData.frame:getTitle() .. "/config")
local scripting, style
TemplateData.ltr = not mw.language.getContentLanguage():isRTL()
if TemplateData.ltr then
scripting = "left"
else
scripting = "right"
end
boole["margin-" .. scripting] = "3em"
Permit.boole = {
[false] = {
css = boole,
lead = true,
show = "☐",
},
[true] = {
css = boole,
lead = true,
show = "☑",
},
}
Permit.css = {}
for k, v in pairs(Permit.colors) do
if k == "tableheadbg" then
k = "tablehead"
end
if k == "fg" then
style = "color"
else
style = "background-color"
end
Permit.css[k] = {}
Permit.css[k][style] = v
end -- for k, v
if type(cx) == "table" then
local c, s
if type(cx.permit) == "table" then
if type(cx.permit.boole) == "table" then
if type(cx.permit.boole[true]) == "table" then
Permit.boole[false] = cx.permit.boole[false]
end
if type(cx.permit.boole[true]) == "table" then
Permit.boole[true] = cx.permit.boole[true]
end
end
if type(cx.permit.css) == "table" then
for k, v in pairs(cx.permit.css) do
if type(v) == "table" then
Permit.css[k] = v
end
end -- for k, v
end
end
for k, v in pairs(Config.basicCnf) do
s = type(cx[k])
if s == "string" or s == "table" then
Config[v] = cx[k]
end
end -- for k, v
end
if type(Config.subpage) ~= "string" or type(Config.suffix) ~= "string" then
local got = mw.message.new("templatedata-doc-subpage")
local suffix
if got:isDisabled() then
suffix = "doc"
else
suffix = got:plain()
end
if type(Config.subpage) ~= "string" then
Config.subpage = string.format("/%s$", suffix)
end
if type(Config.suffix) ~= "string" then
Config.suffix = string.format("%%s/%s", suffix)
end
end
end -- favorize()
local function feasible(all, at, about)
-- Deal with suggestedvalues within parameter.
-- Parameter:
-- all -- parameter details
-- .default
-- .type
-- at -- string, with parameter name
-- about -- suggestedvalues -- table,
-- value and possibly description
-- table may have elements:
-- .code -- mandatory
-- .label -- table|string
-- .support -- table|string
-- .icon -- string
-- .class -- table|string
-- .css -- table
-- .style -- string
-- .less -- true: suppress code
-- Returns
-- 1: mw.html object <ul>
-- 2: sequence table with values, or nil
local h = {}
local e, r1, r2, s, v
if #about > 0 then
for i = 1, #about do
e = about[i]
s = type(e)
if s == "table" then
if type(e.code) == "string" then
s = mw.text.trim(e.code)
if s == "" then
e = nil
else
e.code = s
end
else
e = nil
s = string.format("params.%s.%s[%d] %s", at, "suggestedvalues", i, "MISSING 'code:'")
end
elseif s == "string" then
s = mw.text.trim(e)
if s == "" then
e = nil
s = string.format("params.%s.%s[%d] EMPTY", at, "suggestedvalues", i)
Fault(s)
else
e = { code = s }
end
elseif s == "number" then
e = { code = tostring(e) }
else
s = string.format("params.%s.%s[%d] INVALID", at, "suggestedvalues", i)
Fault(s)
e = false
end
if e then
v = v or {}
table.insert(v, e)
if h[e.code] then
s = string.format("params.%s.%s REPEATED %s", at, "suggestedvalues", e.code)
Fault(s)
else
h[e.code] = true
end
end
end -- for i
else
Fault(string.format("params.%s.suggestedvalues %s", at, "NOT AN ARRAY"))
end
if v then
local code, d, k, less, story, swift, t, u
r1 = mw.html.create("ul")
r2 = {}
for i = 1, #v do
u = mw.html.create("li")
e = v[i]
table.insert(r2, e.code)
story = false
less = (e.less == true)
if not less then
swift = e.code
if e.support then
local scream, support
s = type(e.support)
if s == "string" then
support = e.support
elseif s == "table" then
support = faraway(e.support)
else
scream = "INVALID"
end
if support then
s = mw.text.trim(support)
if s == "" then
scream = "EMPTY"
elseif s:find("[%[%]|%<%>]") then
scream = "BAD PAGE"
else
support = s
end
end
if scream then
s = string.format("params.%s.%s[%d].support %s", at, "suggestedvalues", i, scream)
Fault(s)
else
swift = string.format("[[:%s|%s]]", support, swift)
end
end
if all.type:sub(1, 5) == "wiki-" and swift == e.code then
local rooms = {
file = 6,
temp = 10,
user = 2,
}
local ns = rooms[all.type:sub(6, 9)] or 0
t = mw.title.makeTitle(ns, swift)
if t and t.exists then
swift = string.format("[[:%s|%s]]", t.prefixedText, swift)
end
end
if e.code == all.default then
k = 800
else
k = 300
end
code =
mw.html.create("code"):css("font-weight", tostring(k)):css("white-space", "nowrap"):wikitext(swift)
u:node(code)
end
if e.class then
s = type(e.class)
if s == "string" then
u:addClass(e.class)
elseif s == "table" then
for k, s in pairs(e.class) do
u:addClass(s)
end -- for k, s
else
s = string.format("params.%s.%s[%d].class INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if e.css then
if type(e.css) == "table" then
u:css(e.css)
else
s = string.format("params.%s.%s[%d].css INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if e.style then
if type(e.style) == "string" then
u:cssText(e.style)
else
s = string.format("params.%s.%s[%d].style INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
if all.type == "wiki-file-name" and not e.icon then
e.icon = e.code
end
if e.label then
s = type(e.label)
if s == "string" then
s = mw.text.trim(e.label)
if s == "" then
s = string.format("params.%s.%s[%d].label %s", at, "suggestedvalues", i, "EMPTY")
Fault(s)
else
story = s
end
elseif s == "table" then
story = faraway(e.label)
else
s = string.format("params.%s.%s[%d].label INVALID", at, "suggestedvalues", i)
Fault(s)
end
end
s = false
if type(e.icon) == "string" then
t = mw.title.makeTitle(6, e.icon)
if t and t.file.exists then
local g = mw.html.create("span")
s = string.format("[[%s|16px]]", t.prefixedText)
g:attr("role", "presentation"):wikitext(s)
s = tostring(g)
end
end
if not s and not less and e.label then
s = mw.ustring.char(0x2013)
end
if s then
d = mw.html.create("span"):wikitext(s)
if TemplateData.ltr then
if not less then
d:css("margin-left", "0.5em")
end
if story then
d:css("margin-right", "0.5em")
end
else
if not less then
d:css("margin-right", "0.5em")
end
if story then
d:css("margin-left", "0.5em")
end
end
u:node(d)
end
if story then
u:wikitext(story)
end
r1:newline():node(u)
end -- for i
end
if not r1 and v ~= false then
Fault(string.format("params.%s.suggestedvalues INVALID", at))
r1 = mw.html.create("code"):addClass("error"):wikitext("INVALID")
end
return r1, r2
end -- feasible()
local function feat()
-- Check and store parameter sequence.
if Data.source then
local i = 0
local s
for k, v in pairs(Data.tree.params) do
if i == 0 then
Data.order = {}
i = 1
s = k
else
i = 2
break -- for k, v
end
end -- for k, v
if i > 1 then
local pointers = {}
local points = {}
local given = {}
for k, v in pairs(Data.tree.params) do
i = facet(k, 1)
if type(v) == "table" then
if type(v.label) == "string" then
s = mw.text.trim(v.label)
if s == "" then
s = k
end
else
s = k
end
if given[s] then
if given[s] == 1 then
local scream = "Parameter label '%s' detected multiple times"
Fault(string.format(scream, s))
given[s] = 2
end
else
given[s] = 1
end
end
if i then
table.insert(points, i)
pointers[i] = k
i = facet(k, i)
if i then
s = "Parameter '%s' detected twice"
Fault(string.format(s, k))
end
else
s = "Parameter '%s' not detected"
Fault(string.format(s, k))
end
end -- for k, v
table.sort(points)
for i = 1, #points do
table.insert(Data.order, pointers[points[i]])
end -- i = 1, #points
elseif s then
table.insert(Data.order, s)
end
end
end -- feat()
local function feature(access)
-- Create table row for parameter, check and display violations.
-- Parameter:
-- access -- string, with name
-- Returns <tr>.
local mode, s, status
local fine = function(a)
s = mw.text.trim(a)
return a == s and a ~= "" and not a:find("%|=\n") and not a:find("%s%s")
end
local begin = mw.html.create("td")
local code = mw.html.create("code")
local desc = mw.html.create("td")
local eager = mw.html.create("td")
local legal = true
local param = Data.tree.params[access]
local ranking = { "required", "suggested", "optional", "deprecated" }
local r = mw.html.create("tr")
local styles = "mw-templatedata-doc-param-"
local sort, typed
for k, v in pairs(param) do
if v == "" then
param[k] = false
end
end -- for k, v
-- label
sort = param.label or access
if sort:match("^%d+$") then
begin:attr("data-sort-value", string.format("%05d", tonumber(sort)))
end
begin:css("font-weight", "700"):wikitext(sort)
-- name and aliases
code:css("font-size", "0.92em"):css("white-space", "nowrap"):wikitext(access)
if not fine(access) then
code:addClass("error")
Fault(string.format("Bad ID params.<code>%s</code>", access))
legal = false
begin:attr("data-sort-value", " " .. sort)
end
code = mw.html.create("td"):addClass(styles .. "name"):node(code)
if access:match("^%d+$") then
code:attr("data-sort-value", string.format("%05d", tonumber(access)))
end
if type(param.aliases) == "table" then
local lapsus, syn
for k, v in pairs(param.aliases) do
code:tag("br")
if type(v) == "string" then
if not fine(v) then
lapsus = true
code:node(mw.html.create("span"):addClass("error"):css("font-style", "italic"):wikitext("string"))
:wikitext(s)
else
if Config.supportAliases then
s = string.format("[[%s|%s]]", Config.supportAliases, mw.text.nowiki(s))
end
syn = mw.html.create("span"):addClass(styles .. "alias"):css("white-space", "nowrap"):wikitext(s)
code:node(syn)
end
else
lapsus = true
code:node(mw.html.create("code"):addClass("error"):wikitext(type(v)))
end
end -- for k, v
if lapsus then
s = string.format("params.<code>%s</code>.aliases", access)
Fault(factory("invalid-value"):gsub("$1", s))
legal = false
end
end
-- description etc.
s = fashioned(param)
if s then
desc:node(s)
end
if param.style then
s = type(param.style)
if s == "table" then
desc:css(param.style)
elseif s == "string" then
desc:cssText(param.style)
end
end
if param.suggestedvalues or param.default or param.example or param.autovalue then
local details = {
"suggestedvalues",
"default",
"example",
"autovalue",
}
local dl = mw.html.create("dl")
local dd, section, show
for i = 1, #details do
s = details[i]
show = param[s]
if show then
dd = mw.html.create("dd")
section = factory("doc-param-" .. s)
if s == "default" and Config.support4default then
section = string.format("[[%s|%s]]", Config.support4default, mw.text.nowiki(section))
end
if param.type == "boolean" and (show == "0" or show == "1") then
local boole = Permit.boole[(show == "1")]
if boole.lead == true then
dd:node(mw.html.create("code"):wikitext(show)):wikitext(" ")
end
if type(boole.show) == "string" then
local v = mw.html.create("span"):attr("aria-hidden", "true"):wikitext(boole.show)
if boole.css then
v:css(boole.css)
end
dd:node(v)
end
if type(boole.suffix) == "string" then
dd:wikitext(boole.suffix)
end
if boole.lead == false then
dd:wikitext(" "):node(mw.html.create("code"):wikitext(show))
end
elseif s == "suggestedvalues" then
local v, css, class, ts = facilities(param)
if v then
local ul
ul, v = feasible(param, access, v)
if v then
dd:newline():node(ul)
if css then
dd:css(css)
if class then
dd:addClass(class)
end
if ts then
dd:newline()
dd:node(ts)
end
end
Data.params[access].suggestedvalues = v
end
end
else
dd:wikitext(show)
end
dl:node(mw.html.create("dt"):wikitext(section)):node(dd)
end
end -- i = 1, #details
desc:node(dl)
end
-- type
if type(param.type) == "string" then
param.type = mw.text.trim(param.type)
if param.type == "" then
param.type = false
end
end
if param.type then
s = Permit.types[param.type]
typed = mw.html.create("td"):addClass(styles .. "type")
if s then
if s == "string" then
Data.params[access].type = s
typed:wikitext(factory("doc-param-type-" .. s)):tag("br")
typed:node(mw.html.create("span"):addClass("error"):wikitext(param.type))
Data.lasting = true
else
local support = Config["support4" .. param.type]
s = factory("doc-param-type-" .. param.type)
if support then
s = string.format("[[%s|%s]]", support, s)
end
typed:wikitext(s)
end
else
Data.params[access].type = "unknown"
typed:addClass("error"):wikitext("INVALID")
s = string.format("params.<code>%s</code>.type", access)
Fault(factory("invalid-value"):gsub("$1", s))
legal = false
end
else
typed = mw.html.create("td"):wikitext(factory("doc-param-type-unknown"))
Data.params[access].type = "unknown"
if param.default then
Data.params[access].default = nil
Fault("Default value requires <code>type</code>")
legal = false
end
end
typed:addClass("navigation-not-searchable")
-- status
if param.required then
mode = 1
if param.autovalue then
Fault(string.format("autovalued <code>%s</code> required", access))
legal = false
end
if param.default then
Fault(string.format("Defaulted <code>%s</code> required", access))
legal = false
end
if param.deprecated then
Fault(string.format("Required deprecated <code>%s</code>", access))
legal = false
end
elseif param.deprecated then
mode = 4
elseif param.suggested then
mode = 2
else
mode = 3
end
status = ranking[mode]
ranking = factory("doc-param-status-" .. status)
if mode == 1 or mode == 4 then
ranking = mw.html.create("span"):css("font-weight", "700"):wikitext(ranking)
if type(param.deprecated) == "string" then
ranking:tag("br")
ranking:wikitext(param.deprecated)
end
if param.suggested and mode == 4 then
s = string.format("Suggesting deprecated <code>%s</code>", access)
Fault(s)
legal = false
end
end
eager
:attr("data-sort-value", tostring(mode))
:node(ranking)
:addClass(string.format("%sstatus-%s %s", styles, status, "navigation-not-searchable"))
-- <tr>
r:attr("id", "templatedata:" .. mw.uri.anchorEncode(access))
:css(Permit.css[status])
:addClass(styles .. status)
:node(begin)
:node(code)
:node(desc)
:node(typed)
:node(eager)
:newline()
if not legal then
r:css("border", "3px solid #f00")
end
return r
end -- feature()
local function features()
-- Create <table> for parameters.
-- Returns <table>, or nil.
local r
if Data.tree and Data.tree.params then
local tbl = mw.html.create("table")
local tr = mw.html.create("tr")
feat()
if Data.order and #Data.order > 1 then
tbl:addClass("sortable")
end
if type(Config.classTable) == "table" then
for k, v in pairs(Config.classTable) do
tbl:addClass(v)
end -- for k, v
end
if type(Config.cssTable) == "table" then
tbl:css(Config.cssTable)
end
tr:addClass("navigation-not-searchable")
:node(
mw.html.create("th"):attr("colspan", "2"):css(Permit.css.tablehead):wikitext(factory("doc-param-name"))
)
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-desc")))
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-type")))
:node(mw.html.create("th"):css(Permit.css.tablehead):wikitext(factory("doc-param-status")))
tbl
:newline()
-- :node( mw.html.create( "thead" )
:node(tr)
-- )
:newline()
if Data.order then
local leave, s
for i = 1, #Data.order do
s = Data.order[i]
if s:sub(1, 1) == "=" then
leave = true
tbl:node(fatten(s))
Data.order[i] = false
elseif s:match("[=|]") then
Fault(string.format("Bad param <code>%s</code>", s))
else
tbl:node(feature(s))
end
end -- for i = 1, #Data.order
if leave then
for i = #Data.order, 1, -1 do
if not Data.order[i] then
table.remove(Data.order, i)
end
end -- for i = #Data.order, 1, -1
end
Data.tag.paramOrder = Data.order
end
if Config.cssTabWrap or Data.scroll then
r = mw.html.create("div")
if type(Config.cssTabWrap) == "table" then
r:css(Config.cssTabWrap)
elseif type(Config.cssTabWrap) == "string" then
-- deprecated
r:cssText(Config.cssTabWrap)
end
if Data.scroll then
r:css("height", Data.scroll):css("overflow", "auto")
end
r:node(tbl)
else
r = tbl
end
end
return r
end -- features()
local function fellow(any, assigned, at)
-- Check sets[] parameter and issue error message, if necessary.
-- Parameter:
-- any -- should be number
-- assigned -- parameter name
-- at -- number, of set
local s
if type(any) ~= "number" then
s = "<code>sets[%d].params[%s]</code>??"
Fault(string.format(s, at, mw.text.nowiki(tostring(any))))
elseif type(assigned) == "string" then
if not Data.got.params[assigned] then
s = "<code>sets[%d].params %s</code> is undefined"
Fault(string.format(s, at, assigned))
end
else
s = "<code>sets[%d].params[%d] = %s</code>??"
Fault(string.format(s, k, type(assigned)))
end
end -- fellow()
local function fellows()
-- Check sets[] and issue error message, if necessary.
local s
if type(Data.got.sets) == "table" then
if type(Data.got.params) == "table" then
for k, v in pairs(Data.got.sets) do
if type(k) == "number" then
if type(v) == "table" then
for ek, ev in pairs(v) do
if ek == "label" then
s = type(ev)
if s ~= "string" and s ~= "table" then
s = "<code>sets[%d].label</code>??"
Fault(string.format(s, k))
end
elseif ek == "params" and type(ev) == "table" then
for pk, pv in pairs(ev) do
fellow(pk, pv, k)
end -- for pk, pv
else
ek = mw.text.nowiki(tostring(ek))
s = "<code>sets[%d][%s]</code>??"
Fault(string.format(s, k, ek))
end
end -- for ek, ev
else
k = mw.text.nowiki(tostring(k))
v = mw.text.nowiki(tostring(v))
s = string.format("<code>sets[%s][%s]</code>??", k, v)
Fault(s)
end
else
k = mw.text.nowiki(tostring(k))
s = string.format("<code>sets[%s]</code> ?????", k)
Fault(s)
end
end -- for k, v
else
s = "<code>params</code> required for <code>sets</code>"
Fault(s)
end
else
s = "<code>sets</code> needs to be of <code>object</code> type"
Fault(s)
end
end -- fellows()
local function finalize(advance)
-- Wrap presentation into frame.
-- Parameter:
-- advance -- true, for nice
-- Returns string.
local r, lapsus
if Data.div then
r = tostring(Data.div)
elseif Data.strip then
r = Data.strip
else
lapsus = true
r = ""
end
r = r .. failures()
if Data.source then
local live = (advance or lapsus)
if not live then
live = TemplateData.frame:preprocess("{{REVISIONID}}")
live = (live == "")
end
if live then
r = r .. fancy(advance, lapsus)
end
end
return r
end -- finalize()
local function find()
-- Find JSON data within page source (title).
-- Returns string, or nil.
local s = Data.title:getContent()
local i, j = s:find("<templatedata>", 1, true)
local r
if i then
local k = s:find("</templatedata>", j, true)
if k then
r = mw.text.trim(s:sub(j + 1, k - 1))
end
end
return r
end -- find()
local function flat(adjust)
-- Remove formatting from text string for VisualEditor.
-- Parameter:
-- arglist -- string, to be stripped, or nil
-- Returns string, or nil.
local r
if adjust then
r = adjust:gsub("\n", " ")
if r:find("<noexport>", 1, true) then
r = r:gsub("<noexport>.*</noexport>", "")
end
if r:find("<exportonly>", 1, true) then
r = r:gsub("</?exportonly>", "")
end
if r:find("''", 1, true) then
r = r:gsub("'''", ""):gsub("''", "")
end
if r:find("<", 1, true) then
local Text = Fetch("Text")
r = r:gsub("<br */?>", "\r\n"):gsub("<sup>2</sup>", "²"):gsub("<sup>3</sup>", "³")
r = Text.getPlain(r)
end
if r:find("[", 1, true) then
local WLink = Fetch("WLink")
if WLink.isBracketedURL(r) then
r = r:gsub("%[([hf]tt?ps?://%S+) [^%]]+%]", "%1")
end
r = WLink.getPlain(r)
end
if r:find("&", 1, true) then
r = mw.text.decode(r)
if r:find("­", 1, true) then
r = r:gsub("­", "")
end
end
end
return r
end -- flat()
local function flush()
-- JSON encode narrowed input; obey unnamed (numerical) parameters.
-- Returns <templatedata> JSON string.
local r
if Data.tag then
r = mw.text.jsonEncode(Data.tag):gsub("%}$", ",")
else
r = "{"
end
r = r .. '\n"params":{'
if Data.order then
local sep = ""
local s
for i = 1, #Data.order do
s = Data.order[i]
r = string.format("%s%s\n%s:%s", r, sep, mw.text.jsonEncode(s), mw.text.jsonEncode(Data.params[s]))
sep = ",\n"
end -- for i = 1, #Data.order
end
r = r .. "\n}\n}"
return r
end -- flush()
local function focus(access)
-- Check components; focus multilingual description, build trees.
-- Parameter:
-- access -- string, name of parameter, nil for root
local f = function(a, at)
local r
if at then
r = string.format("<code>params.%s</code>", at)
else
r = "''root''"
end
if a then
r = string.format("%s<code>.%s</code>", r, a)
end
return r
end
local parent
if access then
parent = Data.got.params[access]
else
parent = Data.got
end
if type(parent) == "table" then
local elem, permit, s, scope, slot, tag, target
if access then
permit = Permit.params
if type(access) == "number" then
slot = tostring(access)
else
slot = access
end
else
permit = Permit.root
end
for k, v in pairs(parent) do
scope = permit[k]
if scope then
s = type(v)
if s == "string" and k ~= "format" then
v = mw.text.trim(v)
end
if scope:find(s, 1, true) then
if scope:find("I18N", 1, true) then
if s == "string" then
elem = fair(v)
elseif s == "table" then
local translated
v, translated = faraway(v)
if v then
if translated and k == "description" then
elem = {
[1] = fair(v),
[2] = translated,
}
else
elem = fair(v)
end
else
elem = false
end
end
if type(v) == "string" then
if k == "deprecated" then
if v == "1" then
v = true
elseif v == "0" then
v = false
end
elem = v
elseif scope:find("nowiki", 1, true) then
elem = mw.text.nowiki(v)
elem = elem:gsub(" " .. string.char(10), "<br>")
v = v:gsub(string.char(13), "")
else
v = flat(v)
end
elseif s == "boolean" then
if scope:find("boolean", 1, true) then
elem = v
else
s = "Type <code>boolean</code> bad for " .. f(k, slot)
Fault(s)
end
end
else
if k == "params" and not access then
v = nil
elem = nil
elseif k == "format" and not access then
elem = mw.text.decode(v)
v = nil
elseif k == "inherits" then
elem = v
if not Data.heirs then
Data.heirs = {}
end
Data.heirs[slot] = v
v = nil
elseif k == "style" then
elem = v
v = nil
elseif s == "string" then
v = mw.text.nowiki(v)
elem = v
else
elem = v
end
end
if type(elem) ~= "nil" then
if not target then
if access then
if not Data.tree.params then
Data.tree.params = {}
end
Data.tree.params[slot] = {}
target = Data.tree.params[slot]
else
Data.tree = {}
target = Data.tree
end
end
target[k] = elem
elem = false
end
if type(v) ~= "nil" then
if not tag then
if access then
if type(v) == "string" and v.sub(1, 1) == "=" then
v = nil
else
if not Data.params then
Data.params = {}
end
Data.params[slot] = {}
tag = Data.params[slot]
end
else
Data.tag = {}
tag = Data.tag
end
end
if type(v) ~= "nil" and k ~= "suggestedvalues" then
tag[k] = v
end
end
else
s = string.format("Type <code>%s</code> bad for %s", scope, f(k, slot))
Fault(s)
end
else
Fault("Unknown component " .. f(k, slot))
end
end -- for k, v
if not access and Data.got.sets then
fellows()
end
else
Fault(f() .. " needs to be of <code>object</code> type")
end
end -- focus()
local function format()
-- Build formatted element.
-- Returns <inline>.
local source = Data.tree.format:lower()
local r, s
if source == "inline" or source == "block" then
r = mw.html.create("i"):wikitext(source)
else
local code
if source:find("|", 1, true) then
local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$"
if source:match(scan) then
code = source:gsub("\n", "N")
else
s = mw.text.nowiki(source):gsub("\n", "\n")
s = tostring(mw.html.create("code"):wikitext(s))
Fault("Invalid format " .. s)
source = false
end
else
local words = mw.text.split(source, "%s+")
local show, start, support, unknown
for i = 1, #words do
s = words[i]
if i == 1 then
start = s
end
support = Permit.builder[s]
if support == start or support == "*" then
Permit.builder[s] = true
elseif s:match("^[1-9]%d?") and Permit.builder.align then
Permit.builder.align = tonumber(s)
else
if unknown then
unknown = string.format("%s %s", unknown, s)
else
unknown = s
end
end
end -- i = 1, #words
if unknown then
s = tostring(mw.html.create("code"):css("white-space", "nowrap"):wikitext(s))
Fault("Unknown/misplaced format keyword " .. s)
source = false
start = false
end
if start == "inline" then
if Permit.builder.half == true then
show = "inline half"
code = "{{_ |_=_}}"
elseif Permit.builder.grouped == true then
show = "inline grouped"
code = "{{_ | _=_}}"
elseif Permit.builder.spaced == true then
show = "inline spaced"
code = "{{_ | _ = _ }}"
end
if Permit.builder.newlines == true then
show = show or "inline"
code = code or "{{_|_=_}}"
show = show .. " newlines"
code = string.format("N%sN", code)
end
elseif start == "block" then
local space = "" -- amid "|" and name
local spaced = " " -- preceding "="
local spacer = " " -- following "="
local suffix = "N" -- closing "}}" on new line
show = "block"
if Permit.builder.indent == true then
start = " "
show = "block indent"
else
start = ""
end
if Permit.builder.compressed == true then
spaced = ""
spacer = ""
show = show .. " compressed"
if Permit.builder.last == true then
show = show .. " last"
else
suffix = ""
end
else
if Permit.builder.lead == true then
show = show .. " lead"
space = " "
end
if type(Permit.builder.align) ~= "string" then
local n
s = " align"
if Permit.builder.align == true then
n = 0
if type(Data.got) == "table" and type(Data.got.params) == "table" then
for k, v in pairs(Data.got.params) do
if type(v) == "table" and not v.deprecated and type(k) == "string" then
k = mw.ustring.len(k)
if k > n then
n = k
end
end
end -- for k, v
end
else
n = Permit.builder.align
if type(n) == "number" and n > 1 then
s = string.format("%s %d", s, n)
else
n = 0 -- How come?
end
end
if n > 1 then
spaced = string.rep("_", n - 1) .. " "
end
show = show .. s
elseif Permit.builder.after == true then
spaced = ""
show = show .. " after"
elseif Permit.builder.dense == true then
spaced = ""
spacer = ""
show = show .. " dense"
end
if Permit.builder.last == true then
suffix = spacer
show = show .. " last"
end
end
code = string.format("N{{_N%s|%s_%s=%s_%s}}N", start, space, spaced, spacer, suffix)
if show == "block" then
show = "block newlines"
end
end
if show then
r = mw.html.create("span"):wikitext(show)
end
end
if code then
source = code:gsub("N", "\n")
code = mw.text.nowiki(code):gsub("N", "\n")
code = mw.html.create("code"):css("margin-left", "1em"):css("margin-right", "1em"):wikitext(code)
if r then
r = mw.html.create("span"):node(r):node(code)
else
r = code
end
end
end
if source and Data.tag then
Data.tag.format = source
end
return r
end -- format()
local function formatter()
-- Build presented documentation.
-- Returns <div>.
local r = mw.html.create("div")
local x = fashioned(Data.tree, true, r)
local s
if x then
r = x
end
if Data.leading then
local toc = mw.html.create("div")
local shift
if Config.suppressTOCnum then
toc:addClass(Config.suppressTOCnum)
if type(Config.stylesTOCnum) == "string" then
local src = Config.stylesTOCnum .. "/styles.css"
s = TemplateData.frame:extensionTag("templatestyles", nil, { src = src })
r:newline():node(s)
end
end
toc:addClass("navigation-not-searchable"):css("margin-top", "0.5em"):wikitext("__TOC__")
if Data.sibling then
local block = mw.html.create("div")
if TemplateData.ltr then
shift = "right"
else
shift = "left"
end
block:css("float", shift):wikitext(Data.sibling)
r:newline():node(block):newline()
end
r:newline():node(toc):newline()
if shift then
r:node(mw.html.create("div"):css("clear", shift)):newline()
end
end
s = features()
if s then
if Data.leading then
r:node(mw.html.create("h" .. Config.nested):wikitext(factory("doc-params"))):newline()
end
r:node(s)
end
if Data.shared then
local global = mw.html.create("div"):attr("id", "templatedata-global")
local shift
if TemplateData.ltr then
shift = "right"
else
shift = "left"
end
global:css("float", shift):wikitext(string.format("[[%s|%s]]", Data.shared, "Global"))
r:newline():node(global)
end
if Data.tree and Data.tree.format then
local e = format()
if e then
local show = "Format"
if Config.supportFormat then
show = string.format("[[%s|%s]]", Config.supportFormat, show)
end
r:node(mw.html.create("p"):addClass("navigation-not-searchable"):wikitext(show .. ": "):node(e))
end
end
return r
end -- formatter()
local function free()
-- Remove JSON comment lines.
if Data.source:find("//", 1, true) then
Data.source:gsub("([{,\"'])(%s*\n%s*//.*\n%s*)([{},\"'])", "%1%3")
end
end -- free()
local function full()
-- Build survey table from JSON data, append invisible <templatedata>.
Data.div = mw.html.create("div"):addClass("mw-templatedata-doc-wrap")
if Permit.css.bg then
Data.div:css(Permit.css.bg)
end
if Permit.css.fg then
Data.div:css(Permit.css.fg)
end
focus()
if Data.tag then
if type(Data.got.params) == "table" then
for k, v in pairs(Data.got.params) do
focus(k)
end -- for k, v
if Data.heirs then
fathers()
end
end
end
Data.div:node(formatter())
if not Data.lazy then
Data.slim = flush()
if TemplateData.frame then
local div = mw.html.create("div")
local tdata = {
[1] = "templatedata",
[2] = Data.slim,
}
Data.strip = TemplateData.frame:callParserFunction("#tag", tdata)
div:wikitext(Data.strip)
if Config.loudly then
Data.div:node(mw.html.create("hr"):css({ height = "7ex" }))
else
div:css("display", "none")
end
Data.div:node(div)
end
end
if Data.lasting then
Fault("deprecated type syntax")
end
if Data.less then
Fault(Config.solo)
end
end -- full()
local function furnish(adapt, arglist)
-- Analyze transclusion.
-- Parameter:
-- adapt -- table, #invoke parameters
-- arglist -- table, template parameters
-- Returns string.
local source
favorize()
-- deprecated:
for k, v in pairs(Config.basicCnf) do
if adapt[k] and adapt[k] ~= "" then
Config[v] = adapt[k]
end
end -- for k, v
if arglist.heading and arglist.heading:match("^[3-6]$") then
Config.nested = arglist.heading
else
Config.nested = "2"
end
Config.loudly = faculty(arglist.debug or adapt.debug)
Data.lazy = faculty(arglist.lazy) and not Config.loudly
Data.leading = faculty(arglist.TOC)
if Data.leading and arglist.TOCsibling then
Data.sibling = mw.text.trim(arglist.TOCsibling)
end
if arglist.lang then
Data.slang = arglist.lang:lower()
elseif adapt.lang then
Data.slang = adapt.lang:lower()
end
if arglist.JSON then
source = arglist.JSON
elseif arglist.Global then
source = TemplateData.getGlobalJSON(arglist.Global, arglist.Local)
elseif arglist[1] then
local s = mw.text.trim(arglist[1])
local start = s:sub(1, 1)
if start == "<" then
Data.strip = s
elseif start == "{" then
source = s
elseif mw.ustring.sub(s, 1, 8) == mw.ustring.char(127, 39, 34, 96, 85, 78, 73, 81) then
Data.strip = s
end
end
if type(arglist.vertical) == "string" and arglist.vertical:match("^%d*%.?%d+[emprx]+$") then
Data.scroll = arglist.vertical
end
if not source then
Data.title = mw.title.getCurrentTitle()
source = find()
if not source and not Data.title.text:match(Config.subpage) then
local s = string.format(Config.suffix, Data.title.prefixedText)
Data.title = mw.title.new(s)
if Data.title.exists then
source = find()
end
end
end
if not Data.lazy then
if not Data.title then
Data.title = mw.title.getCurrentTitle()
end
Data.lazy = Data.title.text:match(Config.subpage)
end
if type(source) == "string" then
TemplateData.getPlainJSON(source)
end
return finalize(faculty(arglist.source))
end -- furnish()
Failsafe.failsafe = function(atleast)
-- Retrieve versioning and check for compliance.
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2024-03-01
local since = atleast
local last = (since == "~")
local linked = (since == "@")
local link = (since == "item")
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type(item) == "number" and item > 0 then
local suited = string.format("Q%d", item)
if link then
r = suited
else
local entity = mw.wikibase.getEntity(suited)
if type(entity) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues(seek)
if type(vsn) == "table" and type(vsn.value) == "string" and vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText == mw.wikibase.getSitelink(suited) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
elseif link then
r = false
end
end
if type(r) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
TemplateData.getGlobalJSON = function(access, adapt)
-- Retrieve TemplateData from a global repository (JSON).
-- Parameter:
-- access -- string, with page specifier (on WikiMedia Commons)
-- adapt -- JSON string or table with local overrides
-- Returns true, if succeeded.
local plugin = Fetch("/global")
local r
if type(plugin) == "table" and type(plugin.fetch) == "function" then
local s, got = plugin.fetch(access, adapt)
if got then
Data.got = got
Data.order = got.paramOrder
Data.shared = s
r = true
full()
else
Fault(s)
end
end
return r
end -- TemplateData.getGlobalJSON()
TemplateData.getPlainJSON = function(adapt)
-- Reduce enhanced JSON data to plain text localized JSON.
-- Parameter:
-- adapt -- string, with enhanced JSON
-- Returns string, or not.
if type(adapt) == "string" then
-- local JSONutil = Fetch("JSONutil", true) -- DON'T check for Module:JSONutil. (doesn't exist in English WP, blocked from creation.)
local JSONutil = nil -- DO act as if Fetch() failed.
Data.source = adapt
free()
if JSONutil then
local Multilingual = Fetch("Multilingual", true)
local f
if Multilingual then
f = Multilingual.i18n
end
Data.got = JSONutil.fetch(Data.source, true, f)
else
local lucky
lucky, Data.got = pcall(mw.text.jsonDecode, Data.source)
end
if type(Data.got) == "table" then
full()
elseif not Data.strip then
local scream = type(Data.got)
if scream == "string" then
scream = Data.got
else
scream = "Data.got: " .. scream
end
Fault("fatal JSON error: " .. scream)
end
end
return Data.slim
end -- TemplateData.getPlainJSON()
TemplateData.test = function(adapt, arglist)
TemplateData.frame = mw.getCurrentFrame()
return furnish(adapt, arglist)
end -- TemplateData.test()
-- Export.
local p = {}
p.f = function(frame)
-- Template call.
local lucky, r
TemplateData.frame = frame
lucky, r = pcall(furnish, frame.args, frame:getParent().args)
if not lucky then
Fault("INTERNAL: " .. r)
r = failures()
end
return r
end -- p.f
p.failsafe = function(frame)
-- Versioning interface.
local s = type(frame)
local since
if s == "table" then
since = frame.args[1]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim(since)
if since == "" then
since = false
end
end
return Failsafe.failsafe(since) or ""
end -- p.failsafe
p.TemplateData = function()
-- Module interface.
return TemplateData
end
setmetatable(p, {
__call = function(func, ...)
setmetatable(p, nil)
return Failsafe
end,
})
return p
2dd3b90kpdohdijcui9w39wr2ft47sq
Tempilet:Tlr
10
1128
9265
2016-01-28T02:35:51Z
en>Rezonansowy
0
#REDIRECT [[Template:Template redirect]]
9265
wikitext
text/x-wiki
#REDIRECT [[Template:Template redirect]]
5bpr55x4wctko3p7981xwjwra72dfo0
9266
9265
2026-08-23T03:37:39Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tlr]]
9265
wikitext
text/x-wiki
#REDIRECT [[Template:Template redirect]]
5bpr55x4wctko3p7981xwjwra72dfo0
Tempilet:Template shortcut/doc
10
1129
9267
2026-08-03T17:01:09Z
en>FaviFake
0
/* */ Fix order of templates at the top
9267
wikitext
text/x-wiki
{{Documentation subpage}}
{{tlr|Template shortcuts|Templateshortcut}}
{{tsh|tsh|tsc}}
{{lua|Module:Shortcut}}
{{High-use}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template displays one or more of a template's shortcuts (that is, redirects, also known as aliases), as in the box appearing at the right. {{tl-r|Tsh}} is a shortcut to this template, {{tlf|template shortcut}}, and can be used in its place, as it is in this documentation's [[Wikipedia:View source|source]] [[wikitext]].
== Usage ==
Place this template and its list of few to one, carefully selected shortcut(s) at the top of the template documentation page's [[Wikipedia:Wikitext|wikitext]], right underneath {{tl|Documentation subpage}}. In the saved, rendered text, those shortcuts will appear in this template's Shortcut(s) box, whose title will reflect the number of list items by automatically being singular or plural in form.
=== Which ones to display here ===
Although the template can show up to ten shortcuts, you are ''encouraged to choose well'' which ones to display in this template's box. Even if many redirects exist, ''two or three at the most'' is almost always enough. By keeping the number of redirects presented in the Shortcut box small, it makes it easier to remember them, and the documentation is kept well organized.
=== Where to list any others ===
List others in the Redirects section of the [[Wikipedia:Template documentation|template documentation]]. Again, not all of them need to be listed; some shortcuts are there just for historical reasons, and others differ only in minor points such as white spaces or capitalization. Such shortcut-name variations are unnecessary to list at all—just list the standard, most common version of such a variation.
=== Optional parameters ===
This template has several optional parameters:
* '''float''' – if set to "left", then the box will float to the left of the page, instead of the default float "right".
* '''clear''' – if set to "right" (when float also is set to "right"), the box will be pushed to the right margin of the page, and {{clarify|text=prevent it from nest to the left of other right-floating elements.}} Similarly, if set to "left" (when float also is set to "left"), the box will be pushed to the left margin of the page.
* '''pre''' – can be used to show some text before the shortcut links, but within the braces. This is mostly used to add the text "subst:". This shows the proper syntax for using the template with [[Wikipedia:Substitution|substitution]].
* '''pre1, pre2 ...''' – like above, but adds the prefix only to the nth shortcut.
== Examples of basic code ==
To display one template shortcut named {{tl|uw-v1}}:
{{tlc|template shortcut|uw-v1}}
{{template shortcut|uw-v1}}
{{clear}}
To display three template shortcuts for {{tl|uw-vandalism1}} named {{tl|uw-v1}}, {{tl|uw-vand1}}, and {{tl|uw-vandal1}}:
{{tlc|template shortcut|uw-v1|uw-vand1|uw-vandal1}}
{{template shortcut|uw-v1|uw-vand1|uw-vandal1}}
{{clear}}
== Example with the float parameter ==
Using {{para|float|<var>left</var>}} makes this template flow to the left of the page:
<code><nowiki>{{template shortcut|float=left|uw-v1}}</nowiki></code>
{{template shortcut|float=left|uw-v1}}
{{clear}}
== Example with text ("subst:") within the braces ==
This is mostly used to add text to show how the template could be used with [[Wikipedia:Substitution|substitution]].
Use {{para|pre2|<var>subst:</var>}} and {{para|pre3|<var>subst:</var>}} to show "subst:" before the shortcut links, but within the braces:
<code><nowiki>{{template shortcut|uw-v1|pre2=subst:|uw-vand1|pre3=subst:|uw-vandal1}}</nowiki></code>
{{template shortcut|uw-v1|pre2=subst:|uw-vand1|pre3=subst:|uw-vandal1}}
{{clear}}
If you use {{para|pre|<var>subst:</var>}}, it applies to all of the shortcuts:
<code><nowiki>{{template shortcut|pre=subst:|uw-v1|uw-vand1|uw-vandal1}}</nowiki></code>
{{template shortcut|pre=subst:|uw-v1|uw-vand1|uw-vandal1}}
{{clear}}
== TemplateData ==
{{Format TemplateData|<templatedata>
{
"description": "This template displays one or more of a template's shortcuts.",
"format": "inline",
"params": {
"redirect": {
"label": "Redirect?",
"description": "Whether to refer to the \"shortcut/s\" as \"redirect/s\" instead.",
"default": "0",
"type": "boolean"
},
"target": {
"label": "Target?",
"description": "Whether to not add the <code>redirect=no</code> URL parameter.",
"default": "0",
"type": "boolean"
},
"float": {
"label": "Float",
"description": "The CSS <code>float</code> property value.",
"default": "right",
"suggestedvalues": [
"left",
"right"
],
"type": "string"
},
"clear": {
"label": "Clear",
"description": "The CSS <code>clear</code> property value.",
"suggestedvalues": [
"left",
"right",
"both"
],
"type": "string"
},
"category": {
"label": "Categorize",
"description": "Whether to add pages to the error category if no alias or <code>msg</code> is specified.",
"default": "1",
"type": "boolean"
},
"msg": {
"label": "Message",
"description": "An unlinked message that goes after the shortcut links.",
"type": "content"
},
"pre": {
"label": "Default prefix",
"description": "The default prefix",
"example": "subst:",
"type": "string"
},
"pre1": {
"label": "Prefix 1",
"description": "Prefix for template shortcut 1",
"example": "subst:",
"type": "string"
},
"1": {
"label": "Shortcut 1",
"description": "Template shortcut 1",
"required": true,
"type": "wiki-template-name"
},
"pre2": {
"label": "Prefix 2",
"description": "Prefix for template shortcut 2",
"example": "subst:",
"type": "string"
},
"2": {
"label": "Shortcut 2",
"description": "Template shortcut 2",
"type": "wiki-template-name"
},
"pre3": {
"label": "Prefix 3",
"description": "Prefix for template shortcut 3",
"example": "subst:",
"type": "string"
},
"3": {
"label": "Shortcut 3",
"description": "Template shortcut 3",
"type": "wiki-template-name"
},
"pre4": {
"label": "Prefix 4",
"description": "Prefix for template shortcut 4",
"example": "subst:",
"type": "string"
},
"4": {
"label": "Shortcut 4",
"description": "Template shortcut 4",
"type": "wiki-template-name"
},
"pre5": {
"label": "Prefix 5",
"description": "Prefix for template shortcut 5",
"example": "subst:",
"type": "string"
},
"5": {
"label": "Shortcut 5",
"description": "Template shortcut 5",
"type": "wiki-template-name"
},
"pre6": {
"label": "Prefix 6",
"description": "Prefix for template shortcut 6",
"example": "subst:",
"type": "string"
},
"6": {
"label": "Shortcut 6",
"description": "Template shortcut 6",
"type": "wiki-template-name"
},
"pre7": {
"label": "Prefix 7",
"description": "Prefix for template shortcut 7",
"example": "subst:",
"type": "string"
},
"7": {
"label": "Shortcut 7",
"description": "Template shortcut 7",
"type": "wiki-template-name"
},
"pre8": {
"label": "Prefix 8",
"description": "Prefix for template shortcut 8",
"example": "subst:",
"type": "string"
},
"8": {
"label": "Shortcut 8",
"description": "Template shortcut 8",
"type": "wiki-template-name"
},
"pre9": {
"label": "Prefix 9",
"description": "Prefix for template shortcut 9",
"example": "subst:",
"type": "string"
},
"9": {
"label": "Shortcut 9",
"description": "Template shortcut 9",
"type": "wiki-template-name"
}
}
}
</templatedata>}}
== See also ==
{{Shortcut templates}}
<includeonly>{{Sandbox other||
<!----CATEGORIES BELOW THIS LINE, PLEASE:---->
[[Category:Shortcut templates]]
[[Category:Documentation templates|shortcut]]<!--Yes, this is intended for template doc pages.-->
}}</includeonly>
dw8lzl6yplq8qyaahu5crt0v8jz52vx
9268
9267
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_shortcut/doc]]
9267
wikitext
text/x-wiki
{{Documentation subpage}}
{{tlr|Template shortcuts|Templateshortcut}}
{{tsh|tsh|tsc}}
{{lua|Module:Shortcut}}
{{High-use}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template displays one or more of a template's shortcuts (that is, redirects, also known as aliases), as in the box appearing at the right. {{tl-r|Tsh}} is a shortcut to this template, {{tlf|template shortcut}}, and can be used in its place, as it is in this documentation's [[Wikipedia:View source|source]] [[wikitext]].
== Usage ==
Place this template and its list of few to one, carefully selected shortcut(s) at the top of the template documentation page's [[Wikipedia:Wikitext|wikitext]], right underneath {{tl|Documentation subpage}}. In the saved, rendered text, those shortcuts will appear in this template's Shortcut(s) box, whose title will reflect the number of list items by automatically being singular or plural in form.
=== Which ones to display here ===
Although the template can show up to ten shortcuts, you are ''encouraged to choose well'' which ones to display in this template's box. Even if many redirects exist, ''two or three at the most'' is almost always enough. By keeping the number of redirects presented in the Shortcut box small, it makes it easier to remember them, and the documentation is kept well organized.
=== Where to list any others ===
List others in the Redirects section of the [[Wikipedia:Template documentation|template documentation]]. Again, not all of them need to be listed; some shortcuts are there just for historical reasons, and others differ only in minor points such as white spaces or capitalization. Such shortcut-name variations are unnecessary to list at all—just list the standard, most common version of such a variation.
=== Optional parameters ===
This template has several optional parameters:
* '''float''' – if set to "left", then the box will float to the left of the page, instead of the default float "right".
* '''clear''' – if set to "right" (when float also is set to "right"), the box will be pushed to the right margin of the page, and {{clarify|text=prevent it from nest to the left of other right-floating elements.}} Similarly, if set to "left" (when float also is set to "left"), the box will be pushed to the left margin of the page.
* '''pre''' – can be used to show some text before the shortcut links, but within the braces. This is mostly used to add the text "subst:". This shows the proper syntax for using the template with [[Wikipedia:Substitution|substitution]].
* '''pre1, pre2 ...''' – like above, but adds the prefix only to the nth shortcut.
== Examples of basic code ==
To display one template shortcut named {{tl|uw-v1}}:
{{tlc|template shortcut|uw-v1}}
{{template shortcut|uw-v1}}
{{clear}}
To display three template shortcuts for {{tl|uw-vandalism1}} named {{tl|uw-v1}}, {{tl|uw-vand1}}, and {{tl|uw-vandal1}}:
{{tlc|template shortcut|uw-v1|uw-vand1|uw-vandal1}}
{{template shortcut|uw-v1|uw-vand1|uw-vandal1}}
{{clear}}
== Example with the float parameter ==
Using {{para|float|<var>left</var>}} makes this template flow to the left of the page:
<code><nowiki>{{template shortcut|float=left|uw-v1}}</nowiki></code>
{{template shortcut|float=left|uw-v1}}
{{clear}}
== Example with text ("subst:") within the braces ==
This is mostly used to add text to show how the template could be used with [[Wikipedia:Substitution|substitution]].
Use {{para|pre2|<var>subst:</var>}} and {{para|pre3|<var>subst:</var>}} to show "subst:" before the shortcut links, but within the braces:
<code><nowiki>{{template shortcut|uw-v1|pre2=subst:|uw-vand1|pre3=subst:|uw-vandal1}}</nowiki></code>
{{template shortcut|uw-v1|pre2=subst:|uw-vand1|pre3=subst:|uw-vandal1}}
{{clear}}
If you use {{para|pre|<var>subst:</var>}}, it applies to all of the shortcuts:
<code><nowiki>{{template shortcut|pre=subst:|uw-v1|uw-vand1|uw-vandal1}}</nowiki></code>
{{template shortcut|pre=subst:|uw-v1|uw-vand1|uw-vandal1}}
{{clear}}
== TemplateData ==
{{Format TemplateData|<templatedata>
{
"description": "This template displays one or more of a template's shortcuts.",
"format": "inline",
"params": {
"redirect": {
"label": "Redirect?",
"description": "Whether to refer to the \"shortcut/s\" as \"redirect/s\" instead.",
"default": "0",
"type": "boolean"
},
"target": {
"label": "Target?",
"description": "Whether to not add the <code>redirect=no</code> URL parameter.",
"default": "0",
"type": "boolean"
},
"float": {
"label": "Float",
"description": "The CSS <code>float</code> property value.",
"default": "right",
"suggestedvalues": [
"left",
"right"
],
"type": "string"
},
"clear": {
"label": "Clear",
"description": "The CSS <code>clear</code> property value.",
"suggestedvalues": [
"left",
"right",
"both"
],
"type": "string"
},
"category": {
"label": "Categorize",
"description": "Whether to add pages to the error category if no alias or <code>msg</code> is specified.",
"default": "1",
"type": "boolean"
},
"msg": {
"label": "Message",
"description": "An unlinked message that goes after the shortcut links.",
"type": "content"
},
"pre": {
"label": "Default prefix",
"description": "The default prefix",
"example": "subst:",
"type": "string"
},
"pre1": {
"label": "Prefix 1",
"description": "Prefix for template shortcut 1",
"example": "subst:",
"type": "string"
},
"1": {
"label": "Shortcut 1",
"description": "Template shortcut 1",
"required": true,
"type": "wiki-template-name"
},
"pre2": {
"label": "Prefix 2",
"description": "Prefix for template shortcut 2",
"example": "subst:",
"type": "string"
},
"2": {
"label": "Shortcut 2",
"description": "Template shortcut 2",
"type": "wiki-template-name"
},
"pre3": {
"label": "Prefix 3",
"description": "Prefix for template shortcut 3",
"example": "subst:",
"type": "string"
},
"3": {
"label": "Shortcut 3",
"description": "Template shortcut 3",
"type": "wiki-template-name"
},
"pre4": {
"label": "Prefix 4",
"description": "Prefix for template shortcut 4",
"example": "subst:",
"type": "string"
},
"4": {
"label": "Shortcut 4",
"description": "Template shortcut 4",
"type": "wiki-template-name"
},
"pre5": {
"label": "Prefix 5",
"description": "Prefix for template shortcut 5",
"example": "subst:",
"type": "string"
},
"5": {
"label": "Shortcut 5",
"description": "Template shortcut 5",
"type": "wiki-template-name"
},
"pre6": {
"label": "Prefix 6",
"description": "Prefix for template shortcut 6",
"example": "subst:",
"type": "string"
},
"6": {
"label": "Shortcut 6",
"description": "Template shortcut 6",
"type": "wiki-template-name"
},
"pre7": {
"label": "Prefix 7",
"description": "Prefix for template shortcut 7",
"example": "subst:",
"type": "string"
},
"7": {
"label": "Shortcut 7",
"description": "Template shortcut 7",
"type": "wiki-template-name"
},
"pre8": {
"label": "Prefix 8",
"description": "Prefix for template shortcut 8",
"example": "subst:",
"type": "string"
},
"8": {
"label": "Shortcut 8",
"description": "Template shortcut 8",
"type": "wiki-template-name"
},
"pre9": {
"label": "Prefix 9",
"description": "Prefix for template shortcut 9",
"example": "subst:",
"type": "string"
},
"9": {
"label": "Shortcut 9",
"description": "Template shortcut 9",
"type": "wiki-template-name"
}
}
}
</templatedata>}}
== See also ==
{{Shortcut templates}}
<includeonly>{{Sandbox other||
<!----CATEGORIES BELOW THIS LINE, PLEASE:---->
[[Category:Shortcut templates]]
[[Category:Documentation templates|shortcut]]<!--Yes, this is intended for template doc pages.-->
}}</includeonly>
dw8lzl6yplq8qyaahu5crt0v8jz52vx
Tempilet:Shortcut-style further links
10
1130
9269
2026-08-03T16:44:24Z
en>FaviFake
0
consistency
9269
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|shortcut-heading=Further info|target=yes}}</includeonly><noinclude>{{doc}}</noinclude>
k3wb9855n53cgybqo4wjq1iendp35q7
9270
9269
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Shortcut-style_further_links]]
9269
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main|shortcut-heading=Further info|target=yes}}</includeonly><noinclude>{{doc}}</noinclude>
k3wb9855n53cgybqo4wjq1iendp35q7
Module:Format TemplateData/config
828
1131
9271
2026-07-30T13:47:38Z
en>RogueScholar
0
Remove 'cssParWrap' table containing negative inline margin values to match default TemplateData table presentation
9271
Scribunto
text/plain
--[=[
Configuration for [[Module:Format TemplateData]] on enwiki
mw.loadData()
]=]
local Serial = "2026-01-25"
return {
catProblem = "Templates with TemplateData errors",
classMultiColumns = "column-multiple",
classNoNumTOC = "nonumtoc",
classTable = {
"wikitable",
"templatedata-params"
},
cssParams = {
["border"] = "thin solid var(--background-color-progressive-subtle, #b3b7ff)",
["margin-left"] = "auto",
["margin-right"] = "auto"
},
docpageCreate = "%s/doc",
docpageDetect = "/doc$",
failsafe = Serial,
helpAliases = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#aliases",
helpBoolean = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#boolean",
helpContent = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#Content",
helpDate = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#date",
helpDefault = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#default",
helpFile = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-file-name",
helpFormat = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#format",
helpLine = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#line",
helpNumber = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#number",
helpPage = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-page-name",
helpString = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#string",
helpTemplate = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-template-name",
helpURL = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#url",
helpUser = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-user-name",
msgDescMiss = "missing <code>description</code>",
permit = {
boole = {
[true] = {
css = {
["color"] = "var(--color-content-added, #050)",
["font-weight"] = "700"
},
lead = false,
show = "True"
},
[false] = {
css = {
["color"] = "var(--color-content-removed, #610)",
["font-weight"] = "700"
},
lead = false,
show = "False"
}
},
css = {
bg = {},
deprecated = {
["background-color"] = "var(--background-color-destructive-subtle, #fdd)",
["border-left"] = "3px dotted var(--color-error, red)",
["color"] = "var(--color-base, #000)"
},
fg = {},
optional = {
["border-left"] = "3px solid #ccc",
["color"] = "var(--color-base, #000)"
},
required = {
["border-left"] = "3px solid #000",
["color"] = "var(--color-base, #000)"
},
suggested = {
["border-left"] = "3px solid var(--border-color-subtle, #888)",
["color"] = "var(--color-base, #000)"
},
tableheadbg = {
["background-color"] = "var(--background-color-progressive-subtle, #b3b7ff)",
["color"] = "var(--color-base, #000)"
}
}
},
serial = Serial,
tStylesMultiColumns = "column-multiple",
tStylesTOCnum = "TOC nonum"
}
n89gwq7t3gsq9p5a5i3eevisuxrxfab
9272
9271
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Format_TemplateData/config]]
9271
Scribunto
text/plain
--[=[
Configuration for [[Module:Format TemplateData]] on enwiki
mw.loadData()
]=]
local Serial = "2026-01-25"
return {
catProblem = "Templates with TemplateData errors",
classMultiColumns = "column-multiple",
classNoNumTOC = "nonumtoc",
classTable = {
"wikitable",
"templatedata-params"
},
cssParams = {
["border"] = "thin solid var(--background-color-progressive-subtle, #b3b7ff)",
["margin-left"] = "auto",
["margin-right"] = "auto"
},
docpageCreate = "%s/doc",
docpageDetect = "/doc$",
failsafe = Serial,
helpAliases = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#aliases",
helpBoolean = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#boolean",
helpContent = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#Content",
helpDate = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#date",
helpDefault = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#default",
helpFile = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-file-name",
helpFormat = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#format",
helpLine = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#line",
helpNumber = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#number",
helpPage = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-page-name",
helpString = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#string",
helpTemplate = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-template-name",
helpURL = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#url",
helpUser = "mediawikiwiki:Special:MyLanguage/Help:TemplateData#wiki-user-name",
msgDescMiss = "missing <code>description</code>",
permit = {
boole = {
[true] = {
css = {
["color"] = "var(--color-content-added, #050)",
["font-weight"] = "700"
},
lead = false,
show = "True"
},
[false] = {
css = {
["color"] = "var(--color-content-removed, #610)",
["font-weight"] = "700"
},
lead = false,
show = "False"
}
},
css = {
bg = {},
deprecated = {
["background-color"] = "var(--background-color-destructive-subtle, #fdd)",
["border-left"] = "3px dotted var(--color-error, red)",
["color"] = "var(--color-base, #000)"
},
fg = {},
optional = {
["border-left"] = "3px solid #ccc",
["color"] = "var(--color-base, #000)"
},
required = {
["border-left"] = "3px solid #000",
["color"] = "var(--color-base, #000)"
},
suggested = {
["border-left"] = "3px solid var(--border-color-subtle, #888)",
["color"] = "var(--color-base, #000)"
},
tableheadbg = {
["background-color"] = "var(--background-color-progressive-subtle, #b3b7ff)",
["color"] = "var(--color-base, #000)"
}
}
},
serial = Serial,
tStylesMultiColumns = "column-multiple",
tStylesTOCnum = "TOC nonum"
}
n89gwq7t3gsq9p5a5i3eevisuxrxfab
Module:Multilingual
828
1132
9273
2022-08-09T00:07:40Z
en>Sdrqaz
0
Protected "[[Module:Multilingual]]": [[WP:High-risk templates|High-risk Lua module]]: [[Special:Diff/1103230387/1103232518|Requested by Pppery at RfPP]]. Used in [[Module:Format TemplateData]], which is semi-protected and has 516 transclusions ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9273
Scribunto
text/plain
local Multilingual = { suite = "Multilingual",
serial = "2020-12-10",
item = 47541920,
globals = { ISO15924 = 71584769,
WLink = 19363224 }
}
--[=[
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
* fair()
* fallback()
* findCode()
* fix()
* format()
* getBase()
* getLang()
* getName()
* i18n()
* int()
* isLang()
* isLangWiki()
* isMinusculable()
* isRTL()
* message()
* sitelink()
* tabData()
* userLang()
* userLangCode()
* wikibase()
* failsafe()
loadData: Multilingual/config Multilingual/names
]=]
local Failsafe = Multilingual
local GlobalMod = Multilingual
local GlobalData = Multilingual
local User = { sniffer = "showpreview" }
Multilingual.globals.Multilingual = Multilingual.item
Multilingual.exotic = { simple = true,
no = true }
Multilingual.prefer = { cs = true,
de = true,
en = true,
es = true,
fr = true,
it = true,
nl = true,
pt = true,
ru = true,
sv = true }
local foreignModule = function ( access, advanced, append, alt, alert )
-- Fetch global module
-- Precondition:
-- access -- string, with name of base module
-- advanced -- true, for require(); else mw.loadData()
-- append -- string, with subpage part, if any; or false
-- alt -- number, of wikidata item of root; or false
-- alert -- true, for throwing error on data problem
-- Postcondition:
-- Returns whatever, probably table
-- 2020-01-01
local storage = access
local finer = function ()
if append then
storage = string.format( "%s/%s",
storage,
append )
end
end
local fun, lucky, r, suited
if advanced then
fun = require
else
fun = mw.loadData
end
GlobalMod.globalModules = GlobalMod.globalModules or { }
suited = GlobalMod.globalModules[ access ]
if not suited then
finer()
lucky, r = pcall( fun, "Module:" .. storage )
end
if not lucky then
if not suited and
type( alt ) == "number" and
alt > 0 then
suited = string.format( "Q%d", alt )
suited = mw.wikibase.getSitelink( suited )
GlobalMod.globalModules[ access ] = suited or true
end
if type( suited ) == "string" then
storage = suited
finer()
lucky, r = pcall( fun, storage )
end
if not lucky and alert then
error( "Missing or invalid page: " .. storage )
end
end
return r
end -- foreignModule()
local fetchData = function ( access )
-- Retrieve translated keyword from commons:Data:****.tab
-- Precondition:
-- access -- string, with page identification on Commons
-- Returns table, with data, or string, with error message
-- 2019-12-05
local storage = access
local r
if type( storage ) == "string" then
local s
storage = mw.text.trim( storage )
s = storage:lower()
if s:sub( 1, 2 ) == "c:" then
storage = mw.text.trim( storage:sub( 3 ) )
s = storage:lower()
elseif s:sub( 1, 8 ) == "commons:" then
storage = mw.text.trim( storage:sub( 9 ) )
s = storage:lower()
end
if s:sub( 1, 5 ) == "data:" then
storage = mw.text.trim( storage:sub( 6 ) )
s = storage:lower()
end
if s == "" or s == ".tab" then
storage = false
elseif s:sub( -4 ) == ".tab" then
storage = storage:sub( 1, -5 ) .. ".tab"
else
storage = storage .. ".tab"
end
end
if type( storage ) == "string" then
local data
if type( GlobalData.TabDATA ) ~= "table" then
GlobalData.TabDATA = { }
end
data = GlobalData.TabDATA[ storage ]
if data then
r = data
else
local lucky
lucky, data = pcall( mw.ext.data.get, storage, "_" )
if type( data ) == "table" then
data = data.data
if type( data ) == "table" then
GlobalData.TabDATA[ storage ] = data
else
r = string.format( "%s [[%s%s]]",
"INVALID Data:*.tab",
"commons:Data:",
storage )
end
else
r = "BAD PAGE Data:*.tab – commons:" .. storage
end
if r then
GlobalData.TabDATA[ storage ] = r
data = false
else
r = data
end
end
else
r = "BAD PAGE commons:Data:*.tab"
end
return r
end -- fetchData()
local favorites = function ()
-- Provide fallback codes
-- Postcondition:
-- Returns table with sequence of preferred languages
-- * ahead elements
-- * user (not yet accessible)
-- * page content language (not yet accessible)
-- * page name subpage
-- * project
-- * en
local r = Multilingual.polyglott
if not r then
local self = mw.language.getContentLanguage():getCode():lower()
local sub = mw.title.getCurrentTitle().subpageText
local f = function ( add )
local s = add
for i = 1, #r do
if r[ i ] == s then
s = false
break -- for i
end
end -- for i
if s then
table.insert( r, s )
end
end
r = { }
if sub:find( "/", 2, true ) then
sub = sub:match( "/(%l%l%l?)$" )
if sub then
table.insert( r, sub )
end
elseif sub:find( "^%l%l%l?%-?%a?%a?%a?%a?$" ) and
mw.language.isSupportedLanguage( sub ) then
table.insert( r, sub )
end
f( self )
f( "en" )
Multilingual.polyglott = r
end
return r
end -- favorites()
local feasible = function ( ask, accept )
-- Is ask to be supported by application?
-- Precondition:
-- ask -- lowercase code
-- accept -- sequence table, with offered lowercase codes
-- Postcondition:
-- nil, or true
local r
for i = 1, #accept do
if accept[ i ] == ask then
r = true
break -- for i
end
end -- for i
return r
end -- feasible()
local fetch = function ( access, append )
-- Attach config or library module
-- Precondition:
-- access -- module title
-- append -- string, with subpage part of this; or false
-- Postcondition:
-- Returns: table, with library, or false
local got, sign
if append then
sign = string.format( "%s/%s", access, append )
else
sign = access
end
if type( Multilingual.ext ) ~= "table" then
Multilingual.ext = { }
end
got = Multilingual.ext[ sign ]
if not got and got ~= false then
local global = Multilingual.globals[ access ]
local lib = ( not append or append == "config" )
got = foreignModule( access, lib, append, global )
if type( got ) == "table" then
if lib then
local startup = got[ access ]
if type( startup ) == "function" then
got = startup()
end
end
else
got = false
end
Multilingual.ext[ sign ] = got
end
return got
end -- fetch()
local fetchISO639 = function ( access )
-- Retrieve table from commons:Data:ISO639/***.tab
-- Precondition:
-- access -- string, with subpage identification
-- Postcondition:
-- Returns table, with data, even empty
local r
if type( Multilingual.iso639 ) ~= "table" then
Multilingual.iso639 = { }
end
r = Multilingual.iso639[ access ]
if type( r ) == "nil" then
local raw = fetchData( "ISO639/" .. access )
if type( raw ) == "table" then
local t
r = { }
for i = 1, #raw do
t = raw[ i ]
if type( t ) == "table" and
type( t[ 1 ] ) == "string" and
type( t[ 2 ] ) == "string" then
r[ t[ 1 ] ] = t[ 2 ]
else
break -- for i
end
end -- for i
else
r = false
end
Multilingual.iso639[ access ] = r
end
return r or { }
end -- fetchISO639()
local fill = function ( access, alien, frame )
-- Expand language name template
-- Precondition:
-- access -- string, with language code
-- alien -- language code for which to be generated
-- frame -- frame, if available
-- Postcondition:
-- Returns string
local template = Multilingual.tmplLang
local r
if type( template ) ~= "table" then
local cnf = fetch( "Multilingual", "config" )
if cnf then
template = cnf.tmplLang
end
end
if type( template ) == "table" then
local source = template.title
local f, lucky, s
Multilingual.tmplLang = template
if type( source ) ~= "string" and
type( template.namePat ) == "string" and
template.namePat:find( "%s", 1, true ) then
source = string.format( template.namePat, access )
end
if type( source ) == "string" then
if not Multilingual.frame then
if frame then
Multilingual.frame = frame
else
Multilingual.frame = mw.getCurrentFrame()
end
end
f = function ( a )
return Multilingual.frame:expandTemplate{ title = a }
end
lucky, s = pcall( f, source )
if lucky then
r = s
end
end
end
return r
end -- fill()
local find = function ( ask, alien )
-- Derive language code from name
-- Precondition:
-- ask -- language name, downcased
-- alien -- language code of ask
-- Postcondition:
-- nil, or string
local codes = mw.language.fetchLanguageNames( alien, "all" )
local r
for k, v in pairs( codes ) do
if mw.ustring.lower( v ) == ask then
r = k
break -- for k, v
end
end -- for k, v
if not r then
r = Multilingual.fair( ask )
end
return r
end -- find()
local fold = function ( frame )
-- Merge template and #invoke arglist
-- Precondition:
-- frame -- template frame
-- Postcondition:
-- table, with combined arglist
local r = { }
local f = function ( apply )
if type( apply ) == "table" and
type( apply.args ) == "table" then
for k, v in pairs( apply.args ) do
v = mw.text.trim( v )
if v ~= "" then
r[ tostring( k ) ] = v
end
end -- for k, v
end
end -- f()
f( frame:getParent() )
f( frame )
return r
end -- fold()
User.favorize = function ( accept, frame )
-- Guess user language
-- Precondition:
-- accept -- sequence table, with offered ISO 639 etc. codes
-- frame -- frame, if available
-- Postcondition:
-- Returns string with best code, or nil
if not ( User.self or User.langs ) then
if not User.trials then
User.tell = mw.message.new( User.sniffer )
if User.tell:exists() then
User.trials = { }
if not Multilingual.frame then
if frame then
Multilingual.frame = frame
else
Multilingual.frame = mw.getCurrentFrame()
end
end
User.sin = Multilingual.frame:callParserFunction( "int",
User.sniffer )
else
User.langs = true
end
end
if User.sin then
local order = { }
local post = { }
local three = { }
local unfold = { }
local s, sin
for i = 1, #accept do
s = accept[ i ]
if not User.trials[ s ] then
if #s > 2 then
if s:find( "-", 3, true ) then
table.insert( unfold, s )
else
table.insert( three, s )
end
else
if Multilingual.prefer[ s ] then
table.insert( order, s )
else
table.insert( post, s )
end
end
end
end -- for i
for i = 1, #post do
table.insert( order, post[ i ] )
end -- for i
for i = 1, #three do
table.insert( order, three[ i ] )
end -- for i
for i = 1, #unfold do
table.insert( order, unfold[ i ] )
end -- for i
for i = 1, #order do
s = order[ i ]
sin = User.tell:inLanguage( s ):plain()
if sin == User.sin then
User.self = s
break -- for i
else
User.trials[ s ] = true
end
end -- for i
end
end
return User.self
end -- User.favorize()
Multilingual.fair = function ( ask )
-- Format language specification according to RFC 5646 etc.
-- Precondition:
-- ask -- string or table, as created by .getLang()
-- Postcondition:
-- Returns string, or false
local s = type( ask )
local q, r
if s == "table" then
q = ask
elseif s == "string" then
q = Multilingual.getLang( ask )
end
if q and
q.legal and
mw.language.isKnownLanguageTag( q.base ) then
r = q.base
if q.n > 1 then
local order = { "extlang",
"script",
"region",
"other",
"extension" }
for i = 1, #order do
s = q[ order[ i ] ]
if s then
r = string.format( "%s-%s", r, s )
end
end -- for i
end
end
return r or false
end -- Multilingual.fair()
Multilingual.fallback = function ( able, another )
-- Is another language suitable as replacement?
-- Precondition:
-- able -- language version specifier to be supported
-- another -- language specifier of a possible replacement,
-- or not to retrieve a fallback table
-- Postcondition:
-- Returns boolean, or table with fallback codes
local r
if type( able ) == "string" and #able > 0 then
if type( another ) == "string" and #another > 0 then
if able == another then
r = true
else
local s = Multilingual.getBase( able )
if s == another then
r = true
else
local others = mw.language.getFallbacksFor( s )
r = feasible( another, others )
end
end
else
local s = Multilingual.getBase( able )
if s then
r = mw.language.getFallbacksFor( s )
if r[ 1 ] == "en" then
local d = fetchISO639( "fallback" )
if type( d ) == "table" and
type( d[ s ] ) == "string" then
r = mw.text.split( d[ s ], "|" )
table.insert( r, "en" )
end
end
end
end
end
return r or false
end -- Multilingual.fallback()
Multilingual.findCode = function ( ask )
-- Retrieve code of local (current project or English) language name
-- Precondition:
-- ask -- string, with presumable language name
-- A code itself will be identified, too.
-- Postcondition:
-- Returns string, or false
local seek = mw.text.trim( ask )
local r = false
if #seek > 1 then
if seek:find( "[", 1, true ) then
local wlink = fetch( "WLink" )
if wlink and
type( wlink.getPlain ) == "function" then
seek = wlink.getPlain( seek )
end
end
seek = mw.ustring.lower( seek )
if Multilingual.isLang( seek ) then
r = Multilingual.fair( seek )
else
local collection = favorites()
for i = 1, #collection do
r = find( seek, collection[ i ] )
if r then
break -- for i
end
end -- for i
end
end
return r
end -- Multilingual.findCode()
Multilingual.fix = function ( attempt )
-- Fix frequently mistaken language code
-- Precondition:
-- attempt -- string, with presumable language code
-- Postcondition:
-- Returns string with correction, or false if no problem known
local r = fetchISO639( "correction" )[ attempt:lower() ]
return r or false
end -- Multilingual.fix()
Multilingual.format = function ( apply, alien, alter, active, alert,
frame, assembly, adjacent, ahead )
-- Format one or more languages
-- Precondition:
-- apply -- string with language list or item
-- alien -- language of the answer
-- -- nil, false, "*": native
-- -- "!": current project
-- -- "#": code, downcased, space separated
-- -- "-": code, mixcase, space separated
-- -- any valid code
-- alter -- capitalize, if "c"; downcase all, if "d"
-- capitalize first item only, if "f"
-- downcase every first word only, if "m"
-- active -- link items, if true
-- alert -- string with category title in case of error
-- frame -- if available
-- assembly -- string with split pattern, if list expected
-- adjacent -- string with list separator, else assembly
-- ahead -- string to prepend first element, if any
-- Postcondition:
-- Returns string, or false if apply empty
local r = false
if apply then
local slang
if assembly then
local bucket = mw.text.split( apply, assembly )
local shift = alter
local separator
if adjacent then
separator = adjacent
elseif alien == "#" or alien == "-" then
separator = " "
else
separator = assembly
end
for k, v in pairs( bucket ) do
slang = Multilingual.format( v, alien, shift, active,
alert )
if slang then
if r then
r = string.format( "%s%s%s",
r, separator, slang )
else
r = slang
if shift == "f" then
shift = "d"
end
end
end
end -- for k, v
if r and ahead then
r = ahead .. r
end
else
local single = mw.text.trim( apply )
if single == "" then
r = false
else
local lapsus, slot
slang = Multilingual.findCode( single )
if slang then
if alien == "-" then
r = slang
elseif alien == "#" then
r = slang:lower()
else
r = Multilingual.getName( slang, alien )
if active then
slot = fill( slang, false, frame )
if slot then
local wlink = fetch( "WLink" )
if wlink and
type( wlink.getTarget )
== "function" then
slot = wlink.getTarget( slot )
end
else
lapsus = alert
end
end
end
else
r = single
if active then
local title = mw.title.makeTitle( 0, single )
if title.exists then
slot = single
end
end
lapsus = alert
end
if not r then
r = single
elseif alter == "c" or alter == "f" then
r = mw.ustring.upper( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
elseif alter == "d" then
if Multilingual.isMinusculable( slang, r ) then
r = mw.ustring.lower( r )
end
elseif alter == "m" then
if Multilingual.isMinusculable( slang, r ) then
r = mw.ustring.lower( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
end
end
if slot then
if r == slot then
r = string.format( "[[%s]]", r )
else
r = string.format( "[[%s|%s]]", slot, r )
end
end
if lapsus and alert then
r = string.format( "%s[[Category:%s]]", r, alert )
end
end
end
end
return r
end -- Multilingual.format()
Multilingual.getBase = function ( ask )
-- Retrieve base language from possibly combined ISO language code
-- Precondition:
-- ask -- language code
-- Postcondition:
-- Returns string, or false
local r
if ask then
local slang = ask:match( "^%s*(%a%a%a?)-?%a*%s*$" )
if slang then
r = slang:lower()
else
r = false
end
else
r = false
end
return r
end -- Multilingual.getBase()
Multilingual.getLang = function ( ask )
-- Retrieve components of a RFC 5646 language code
-- Precondition:
-- ask -- language code with subtags
-- Postcondition:
-- Returns table with formatted subtags
-- .base
-- .region
-- .script
-- .suggest
-- .year
-- .extension
-- .other
-- .n
local tags = mw.text.split( ask, "-" )
local s = tags[ 1 ]
local r
if s:match( "^%a%a%a?$" ) then
r = { base = s:lower(),
legal = true,
n = #tags }
for i = 2, r.n do
s = tags[ i ]
if #s == 2 then
if r.region or not s:match( "%a%a" ) then
r.legal = false
else
r.region = s:upper()
end
elseif #s == 4 then
if s:match( "%a%a%a%a" ) then
r.legal = ( not r.script )
r.script = s:sub( 1, 1 ):upper() ..
s:sub( 2 ):lower()
elseif s:match( "20%d%d" ) or
s:match( "1%d%d%d" ) then
r.legal = ( not r.year )
r.year = s
else
r.legal = false
end
elseif #s == 3 then
if r.extlang or not s:match( "%a%a%a" ) then
r.legal = false
else
r.extlang = s:lower()
end
elseif #s == 1 then
s = s:lower()
if s:match( "[tux]" ) then
r.extension = s
for k = i + 1, r.n do
s = tags[ k ]
if s:match( "^%w+$" ) then
r.extension = string.format( "%s-%s",
r.extension, s )
else
r.legal = false
end
end -- for k
else
r.legal = false
end
break -- for i
else
r.legal = ( not r.other ) and
s:match( "%a%a%a" )
r.other = s:lower()
end
if not r.legal then
break -- for i
end
end -- for i
if r.legal then
r.suggest = Multilingual.fix( r.base )
if r.suggest then
r.legal = false
end
end
else
r = { legal = false }
end
if not r.legal then
local cnf = fetch( "Multilingual", "config" )
if cnf and type( cnf.scream ) == "string" then
r.scream = cnf.scream
end
end
return r
end -- Multilingual.getLang()
Multilingual.getName = function ( ask, alien )
-- Which name is assigned to this language code?
-- Precondition:
-- ask -- language code
-- alien -- language of the answer
-- -- nil, false, "*": native
-- -- "!": current project
-- -- any valid code
-- Postcondition:
-- Returns string, or false
local r
if ask then
local slang = alien
local tLang
if slang then
if slang == "*" then
slang = Multilingual.fair( ask )
elseif slang == "!" then
slang = favorites()[ 1 ]
else
slang = Multilingual.fair( slang )
end
else
slang = Multilingual.fair( ask )
end
if not slang then
slang = ask or "?????"
end
slang = slang:lower()
tLang = fetch( "Multilingual", "names" )
if tLang then
tLang = tLang[ slang ]
if tLang then
r = tLang[ ask ]
end
end
if not r then
if not Multilingual.ext.tMW then
Multilingual.ext.tMW = { }
end
tLang = Multilingual.ext.tMW[ slang ]
if tLang == nil then
tLang = mw.language.fetchLanguageNames( slang )
if tLang then
Multilingual.ext.tMW[ slang ] = tLang
else
Multilingual.ext.tMW[ slang ] = false
end
end
if tLang then
r = tLang[ ask ]
end
end
if not r then
r = mw.language.fetchLanguageName( ask:lower(), slang )
if r == "" then
r = false
end
end
else
r = false
end
return r
end -- Multilingual.getName()
Multilingual.i18n = function ( available, alt, frame )
-- Select translatable message
-- Precondition:
-- available -- table, with mapping language code ./. text
-- alt -- string|nil|false, with fallback text
-- frame -- frame, if available
-- Returns
-- 1. string|nil|false, with selected message
-- 2. string|nil|false, with language code
local r1, r2
if type( available ) == "table" then
local codes = { }
local trsl = { }
local slang
for k, v in pairs( available ) do
if type( k ) == "string" and
type( v ) == "string" then
slang = mw.text.trim( k:lower() )
table.insert( codes, slang )
trsl[ slang ] = v
end
end -- for k, v
slang = Multilingual.userLang( codes, frame )
if slang and trsl[ slang ] then
r1 = mw.text.trim( trsl[ slang ] )
if r1 == "" then
r1 = false
else
r2 = slang
end
end
end
if not r1 and type( alt ) == "string" then
r1 = mw.text.trim( alt )
if r1 == "" then
r1 = false
end
end
return r1, r2
end -- Multilingual.i18n()
Multilingual.int = function ( access, alien, apply )
-- Translated system message
-- Precondition:
-- access -- message ID
-- alien -- language code
-- apply -- nil, or sequence table with parameters $1, $2, ...
-- Postcondition:
-- Returns string, or false
local o = mw.message.new( access )
local r
if o:exists() then
if type( alien ) == "string" then
o:inLanguage( alien:lower() )
end
if type( apply ) == "table" then
o:params( apply )
end
r = o:plain()
end
return r or false
end -- Multilingual.int()
Multilingual.isLang = function ( ask, additional )
-- Could this be an ISO language code?
-- Precondition:
-- ask -- language code
-- additional -- true, if Wiki codes like "simple" permitted
-- Postcondition:
-- Returns boolean
local r, s
if additional then
s = ask
else
s = Multilingual.getBase( ask )
end
if s then
r = mw.language.isKnownLanguageTag( s )
if r then
r = not Multilingual.fix( s )
elseif additional then
r = Multilingual.exotic[ s ] or false
end
else
r = false
end
return r
end -- Multilingual.isLang()
Multilingual.isLangWiki = function ( ask )
-- Could this be a Wiki language version?
-- Precondition:
-- ask -- language version specifier
-- Postcondition:
-- Returns boolean
local r
local s = Multilingual.getBase( ask )
if s then
r = mw.language.isSupportedLanguage( s ) or
Multilingual.exotic[ ask ]
else
r = false
end
return r
end -- Multilingual.isLangWiki()
Multilingual.isMinusculable = function ( ask, assigned )
-- Could this language name become downcased?
-- Precondition:
-- ask -- language code, or nil
-- assigned -- language name, or nil
-- Postcondition:
-- Returns boolean
local r = true
if ask then
local cnf = fetch( "Multilingual", "config" )
if cnf then
local s = string.format( " %s ", ask:lower() )
if type( cnf.stopMinusculization ) == "string"
and cnf.stopMinusculization:find( s, 1, true ) then
r = false
end
if r and assigned
and type( cnf.seekMinusculization ) == "string"
and cnf.seekMinusculization:find( s, 1, true )
and type( cnf.scanMinusculization ) == "string" then
local scan = assigned:gsub( "[%(%)]", " " ) .. " "
if not scan:find( cnf.scanMinusculization ) then
r = false
end
end
end
end
return r
end -- Multilingual.isMinusculable()
Multilingual.isRTL = function ( ask )
-- Check whether language is written right-to-left
-- Precondition:
-- ask -- string, with language (or script) code
-- Returns true, if right-to-left
local r
Multilingual.rtl = Multilingual.rtl or { }
r = Multilingual.rtl[ ask ]
if type( r ) ~= "boolean" then
local bib = fetch( "ISO15924" )
if type( bib ) == "table" and
type( bib.isRTL ) == "function" then
r = bib.isRTL( ask )
else
r = mw.language.new( ask ):isRTL()
end
Multilingual.rtl[ ask ] = r
end
return r
end -- Multilingual.isRTL()
Multilingual.message = function ( arglist, frame )
-- Show text in best match of user language like system message
-- Precondition:
-- arglist -- template arguments
-- frame -- frame, if available
-- Postcondition:
-- Returns string with appropriate text
local r
if type( arglist ) == "table" then
local t = { }
local m, p, save
for k, v in pairs( arglist ) do
if type( k ) == "string" and
type( v ) == "string" then
v = mw.text.trim( v )
if v ~= "" then
if k:match( "^%l%l" ) then
t[ k ] = v
elseif k:match( "^%$%d$" ) and k ~= "$0" then
p = p or { }
k = tonumber( k:match( "^%$(%d)$" ) )
p[ k ] = v
if not m or k > m then
m = k
end
end
end
end
end -- for k, v
if type( arglist[ "-" ] ) == "string" then
save = arglist[ arglist[ "-" ] ]
end
r = Multilingual.i18n( t, save, frame )
if p and r and r:find( "$", 1, true ) then
t = { }
for i = 1, m do
t[ i ] = p[ i ] or ""
end -- for i
r = mw.message.newRawMessage( r, t ):plain()
end
end
return r or ""
end -- Multilingual.message()
Multilingual.sitelink = function ( all, frame )
-- Make link at local or other site with optimal linktext translation
-- Precondition:
-- all -- string or table or number, item ID or entity
-- frame -- frame, if available
-- Postcondition:
-- Returns string with any helpful internal link, or plain text
local s = type( all )
local object, r
if s == "table" then
object = all
elseif s == "string" then
object = mw.wikibase.getEntity( all )
elseif s == "number" then
object = mw.wikibase.getEntity( string.format( "Q%d", all ) )
end
if type( object ) == "table" then
local collection = object.sitelinks
local entry
s = false
if type( collection ) == "table" then
Multilingual.site = Multilingual.site or
mw.wikibase.getGlobalSiteId()
entry = collection[ Multilingual.site ]
if entry then
s = ":" .. entry.title
elseif collection.enwiki then
s = "w:en:" .. collection.enwiki.title
end
end
r = Multilingual.wikibase( object, "labels", frame )
if s then
if s == ":" .. r then
r = string.format( "[[%s]]", s )
else
r = string.format( "[[%s|%s]]", s, r )
end
end
end
return r or ""
end -- Multilingual.sitelink()
Multilingual.tabData = function ( access, at, alt, frame )
-- Retrieve translated keyword from commons:Data:****.tab
-- Precondition:
-- access -- string, with page identification on Commons
-- at -- string, with keyword
-- alt -- string|nil|false, with fallback text
-- frame -- frame, if available
-- Returns
-- 1. string|nil|false, with selected message
-- 2. language code, or "error"
local data = fetchData( access )
local r1, r2
if type( data ) == "table" then
if type( at ) == "string" then
local seek = mw.text.trim( at )
if seek == "" then
r1 = "EMPTY Multilingual.tabData key"
else
local e, poly
for i = 1, #data do
e = data[ i ]
if type( e ) == "table" then
if e[ 1 ] == seek then
if type( e[ 2 ] ) == "table" then
poly = e[ 2 ]
else
r1 = "INVALID Multilingual.tabData bad #"
.. tostring( i )
end
break -- for i
end
else
break -- for i
end
end -- for i
if poly then
data = poly
else
r1 = "UNKNOWN Multilingual.tabData key: " .. seek
end
end
else
r1 = "INVALID Multilingual.tabData key"
end
else
r1 = data
end
if r1 then
r2 = "error"
elseif data then
r1, r2 = Multilingual.i18n( data, alt, frame )
r2 = r2 or "error"
end
return r1, r2
end -- Multilingual.tabData()
Multilingual.userLang = function ( accept, frame )
-- Try to support user language by application
-- Precondition:
-- accept -- string or table
-- space separated list of available ISO 639 codes
-- Default: project language, or English
-- frame -- frame, if available
-- Postcondition:
-- Returns string with appropriate code
local s = type( accept )
local codes, r, slang
if s == "string" then
codes = mw.text.split( accept:lower(), "%s+" )
elseif s == "table" then
codes = { }
for i = 1, #accept do
s = accept[ i ]
if type( s ) == "string" and
s ~= "" then
table.insert( codes, s:lower() )
end
end -- for i
end
slang = User.favorize( codes, frame )
if slang then
if feasible( slang, codes ) then
r = slang
elseif slang:find( "-", 1, true ) then
slang = Multilingual.getBase( slang )
if feasible( slang, codes ) then
r = slang
end
end
if not r then
local others = mw.language.getFallbacksFor( slang )
for i = 1, #others do
slang = others[ i ]
if feasible( slang, codes ) then
r = slang
break -- for i
end
end -- for i
end
end
if not r then
local back = favorites()
for i = 1, #back do
slang = back[ i ]
if feasible( slang, codes ) then
r = slang
break -- for i
end
end -- for i
if not r and codes[ 1 ] then
r = codes[ 1 ]
end
end
return r or favorites()[ 1 ]
end -- Multilingual.userLang()
Multilingual.userLangCode = function ()
-- Guess a user language code
-- Postcondition:
-- Returns code of current best guess
return User.self or favorites()[ 1 ]
end -- Multilingual.userLangCode()
Multilingual.wikibase = function ( all, about, attempt, frame )
-- Optimal translation of wikibase component
-- Precondition:
-- all -- string or table, object ID or entity
-- about -- boolean, true "descriptions" or false "labels"
-- attempt -- string or not, code of preferred language
-- frame -- frame, if available
-- Postcondition:
-- Returns
-- 1. string, with selected message
-- 2. string, with language code, or not
local s = type( all )
local object, r, r2
if s == "table" then
object = all
elseif s == "string" then
object = mw.wikibase.getEntity( all )
end
if type( object ) == "table" then
if about and about ~= "labels" then
s = "descriptions"
else
s = "labels"
end
object = object[ s ]
if type( object ) == "table" then
if object[ attempt ] then
r = object[ attempt ].value
r2 = attempt
else
local poly
for k, v in pairs( object ) do
poly = poly or { }
poly[ k ] = v.value
end -- for k, v
if poly then
r, r2 = Multilingual.i18n( poly, nil, frame )
end
end
end
end
return r or "", r2
end -- Multilingual.wikibase()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2020-08-17
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
if type( entity ) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
p.fair = function ( frame )
-- Format language code
-- 1 -- language code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.fair( s ) or ""
end -- p.fair
p.fallback = function ( frame )
-- Is another language suitable as replacement?
-- 1 -- language version specifier to be supported
-- 2 -- language specifier of a possible replacement
local s1 = mw.text.trim( frame.args[ 1 ] or "" )
local s2 = mw.text.trim( frame.args[ 2 ] or "" )
local r = Multilingual.fallback( s1, s2 )
if type( r ) == "table" then
r = r[ 1 ]
else
r = r and "1" or ""
end
return r
end -- p.fallback
p.findCode = function ( frame )
-- Retrieve language code from language name
-- 1 -- name in current project language
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.findCode( s ) or ""
end -- p.findCode
p.fix = function ( frame )
local r = frame.args[ 1 ]
if r then
r = Multilingual.fix( mw.text.trim( r ) )
end
return r or ""
end -- p.fix
p.format = function ( frame )
-- Format one or more languages
-- 1 -- language list or item
-- slang -- language of the answer, if not native
-- * -- native
-- ! -- current project
-- any valid code
-- shift -- capitalize, if "c"; downcase, if "d"
-- capitalize first item only, if "f"
-- link -- 1 -- link items
-- scream -- category title in case of error
-- split -- split pattern, if list expected
-- separator -- list separator, else split
-- start -- prepend first element, if any
local r
local link
if frame.args.link == "1" then
link = true
end
r = Multilingual.format( frame.args[ 1 ],
frame.args.slang,
frame.args.shift,
link,
frame.args.scream,
frame,
frame.args.split,
frame.args.separator,
frame.args.start )
return r or ""
end -- p.format
p.getBase = function ( frame )
-- Retrieve base language from possibly combined ISO language code
-- 1 -- code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.getBase( s ) or ""
end -- p.getBase
p.getName = function ( frame )
-- Retrieve language name from ISO language code
-- 1 -- code
-- 2 -- language to be used for the answer, if not native
-- ! -- current project
-- * -- native
-- any valid code
local s = mw.text.trim( frame.args[ 1 ] or "" )
local slang = frame.args[ 2 ]
local r
Multilingual.frame = frame
if slang then
slang = mw.text.trim( slang )
end
r = Multilingual.getName( s, slang )
return r or ""
end -- p.getName
p.int = function ( frame )
-- Translated system message
-- 1 -- message ID
-- lang -- language code
-- $1, $2, ... -- parameters
local sysMsg = frame.args[ 1 ]
local r
if sysMsg then
sysMsg = mw.text.trim( sysMsg )
if sysMsg ~= "" then
local n = 0
local slang = frame.args.lang
local i, params, s
if slang == "" then
slang = false
end
for k, v in pairs( frame.args ) do
if type( k ) == "string" then
s = k:match( "^%$(%d+)$" )
if s then
i = tonumber( s )
if i > n then
n = i
end
end
end
end -- for k, v
if n > 0 then
local s
params = { }
for i = 1, n do
s = frame.args[ "$" .. tostring( i ) ] or ""
table.insert( params, s )
end -- for i
end
r = Multilingual.int( sysMsg, slang, params )
end
end
return r or ""
end -- p.int
p.isLang = function ( frame )
-- Could this be an ISO language code?
-- 1 -- code
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLang, s )
return r and "1" or ""
end -- p.isLang
p.isLangWiki = function ( frame )
-- Could this be a Wiki language version?
-- 1 -- code
-- Returns non-empty, if possibly language version
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLangWiki, s )
return r and "1" or ""
end -- p.isLangWiki
p.isRTL = function ( frame )
-- Check whether language is written right-to-left
-- 1 -- string, with language code
-- Returns non-empty, if right-to-left
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.isRTL( s ) and "1" or ""
end -- p.isRTL()
p.message = function ( frame )
-- Translation of text element
return Multilingual.message( fold( frame ), frame )
end -- p.message
p.sitelink = function ( frame )
-- Make link at local or other site with optimal linktext translation
-- 1 -- item ID
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s:match( "^%d+$") then
r = tonumber( s )
elseif s:match( "^Q%d+$") then
r = s
end
if r then
r = Multilingual.sitelink( r, frame )
end
return r or s
end -- p.sitelink
p.tabData = function ( frame )
-- Retrieve best message text from Commons Data
-- 1 -- page identification on Commons
-- 2 -- keyword
-- alt -- fallback text
local suite = frame.args[ 1 ]
local seek = frame.args[ 2 ]
local salt = frame.args.alt
local r = Multilingual.tabData( suite, seek, salt, frame )
return r
end -- p.tabData
p.userLang = function ( frame )
-- Which language does the current user prefer?
-- 1 -- space separated list of available ISO 639 codes
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.userLang( s, frame )
end -- p.userLang
p.wikibase = function ( frame )
-- Optimal translation of wikibase component
-- 1 -- object ID
-- 2 -- 1 for "descriptions", 0 for "labels".
-- or either "descriptions" or "labels"
local r
local s = mw.text.trim( frame.args[ 1 ] or "" )
if s ~= "" then
local s2 = mw.text.trim( frame.args[ 2 ] or "0" )
local slang = mw.text.trim( frame.args.lang or "" )
local large = ( s2 ~= "" and s2 ~= "0" )
if slang == "" then
slang = false
end
r = Multilingual.wikibase( s, large, slang, frame )
end
return r or ""
end -- p.wikibase
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
p.Multilingual = function ()
return Multilingual
end -- p.Multilingual
return p
d1zm42sep4ytfi0dl3dok26gecqprzg
9274
9273
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Multilingual]]
9273
Scribunto
text/plain
local Multilingual = { suite = "Multilingual",
serial = "2020-12-10",
item = 47541920,
globals = { ISO15924 = 71584769,
WLink = 19363224 }
}
--[=[
Utilities for multilingual texts and ISO 639 (BCP47) issues etc.
* fair()
* fallback()
* findCode()
* fix()
* format()
* getBase()
* getLang()
* getName()
* i18n()
* int()
* isLang()
* isLangWiki()
* isMinusculable()
* isRTL()
* message()
* sitelink()
* tabData()
* userLang()
* userLangCode()
* wikibase()
* failsafe()
loadData: Multilingual/config Multilingual/names
]=]
local Failsafe = Multilingual
local GlobalMod = Multilingual
local GlobalData = Multilingual
local User = { sniffer = "showpreview" }
Multilingual.globals.Multilingual = Multilingual.item
Multilingual.exotic = { simple = true,
no = true }
Multilingual.prefer = { cs = true,
de = true,
en = true,
es = true,
fr = true,
it = true,
nl = true,
pt = true,
ru = true,
sv = true }
local foreignModule = function ( access, advanced, append, alt, alert )
-- Fetch global module
-- Precondition:
-- access -- string, with name of base module
-- advanced -- true, for require(); else mw.loadData()
-- append -- string, with subpage part, if any; or false
-- alt -- number, of wikidata item of root; or false
-- alert -- true, for throwing error on data problem
-- Postcondition:
-- Returns whatever, probably table
-- 2020-01-01
local storage = access
local finer = function ()
if append then
storage = string.format( "%s/%s",
storage,
append )
end
end
local fun, lucky, r, suited
if advanced then
fun = require
else
fun = mw.loadData
end
GlobalMod.globalModules = GlobalMod.globalModules or { }
suited = GlobalMod.globalModules[ access ]
if not suited then
finer()
lucky, r = pcall( fun, "Module:" .. storage )
end
if not lucky then
if not suited and
type( alt ) == "number" and
alt > 0 then
suited = string.format( "Q%d", alt )
suited = mw.wikibase.getSitelink( suited )
GlobalMod.globalModules[ access ] = suited or true
end
if type( suited ) == "string" then
storage = suited
finer()
lucky, r = pcall( fun, storage )
end
if not lucky and alert then
error( "Missing or invalid page: " .. storage )
end
end
return r
end -- foreignModule()
local fetchData = function ( access )
-- Retrieve translated keyword from commons:Data:****.tab
-- Precondition:
-- access -- string, with page identification on Commons
-- Returns table, with data, or string, with error message
-- 2019-12-05
local storage = access
local r
if type( storage ) == "string" then
local s
storage = mw.text.trim( storage )
s = storage:lower()
if s:sub( 1, 2 ) == "c:" then
storage = mw.text.trim( storage:sub( 3 ) )
s = storage:lower()
elseif s:sub( 1, 8 ) == "commons:" then
storage = mw.text.trim( storage:sub( 9 ) )
s = storage:lower()
end
if s:sub( 1, 5 ) == "data:" then
storage = mw.text.trim( storage:sub( 6 ) )
s = storage:lower()
end
if s == "" or s == ".tab" then
storage = false
elseif s:sub( -4 ) == ".tab" then
storage = storage:sub( 1, -5 ) .. ".tab"
else
storage = storage .. ".tab"
end
end
if type( storage ) == "string" then
local data
if type( GlobalData.TabDATA ) ~= "table" then
GlobalData.TabDATA = { }
end
data = GlobalData.TabDATA[ storage ]
if data then
r = data
else
local lucky
lucky, data = pcall( mw.ext.data.get, storage, "_" )
if type( data ) == "table" then
data = data.data
if type( data ) == "table" then
GlobalData.TabDATA[ storage ] = data
else
r = string.format( "%s [[%s%s]]",
"INVALID Data:*.tab",
"commons:Data:",
storage )
end
else
r = "BAD PAGE Data:*.tab – commons:" .. storage
end
if r then
GlobalData.TabDATA[ storage ] = r
data = false
else
r = data
end
end
else
r = "BAD PAGE commons:Data:*.tab"
end
return r
end -- fetchData()
local favorites = function ()
-- Provide fallback codes
-- Postcondition:
-- Returns table with sequence of preferred languages
-- * ahead elements
-- * user (not yet accessible)
-- * page content language (not yet accessible)
-- * page name subpage
-- * project
-- * en
local r = Multilingual.polyglott
if not r then
local self = mw.language.getContentLanguage():getCode():lower()
local sub = mw.title.getCurrentTitle().subpageText
local f = function ( add )
local s = add
for i = 1, #r do
if r[ i ] == s then
s = false
break -- for i
end
end -- for i
if s then
table.insert( r, s )
end
end
r = { }
if sub:find( "/", 2, true ) then
sub = sub:match( "/(%l%l%l?)$" )
if sub then
table.insert( r, sub )
end
elseif sub:find( "^%l%l%l?%-?%a?%a?%a?%a?$" ) and
mw.language.isSupportedLanguage( sub ) then
table.insert( r, sub )
end
f( self )
f( "en" )
Multilingual.polyglott = r
end
return r
end -- favorites()
local feasible = function ( ask, accept )
-- Is ask to be supported by application?
-- Precondition:
-- ask -- lowercase code
-- accept -- sequence table, with offered lowercase codes
-- Postcondition:
-- nil, or true
local r
for i = 1, #accept do
if accept[ i ] == ask then
r = true
break -- for i
end
end -- for i
return r
end -- feasible()
local fetch = function ( access, append )
-- Attach config or library module
-- Precondition:
-- access -- module title
-- append -- string, with subpage part of this; or false
-- Postcondition:
-- Returns: table, with library, or false
local got, sign
if append then
sign = string.format( "%s/%s", access, append )
else
sign = access
end
if type( Multilingual.ext ) ~= "table" then
Multilingual.ext = { }
end
got = Multilingual.ext[ sign ]
if not got and got ~= false then
local global = Multilingual.globals[ access ]
local lib = ( not append or append == "config" )
got = foreignModule( access, lib, append, global )
if type( got ) == "table" then
if lib then
local startup = got[ access ]
if type( startup ) == "function" then
got = startup()
end
end
else
got = false
end
Multilingual.ext[ sign ] = got
end
return got
end -- fetch()
local fetchISO639 = function ( access )
-- Retrieve table from commons:Data:ISO639/***.tab
-- Precondition:
-- access -- string, with subpage identification
-- Postcondition:
-- Returns table, with data, even empty
local r
if type( Multilingual.iso639 ) ~= "table" then
Multilingual.iso639 = { }
end
r = Multilingual.iso639[ access ]
if type( r ) == "nil" then
local raw = fetchData( "ISO639/" .. access )
if type( raw ) == "table" then
local t
r = { }
for i = 1, #raw do
t = raw[ i ]
if type( t ) == "table" and
type( t[ 1 ] ) == "string" and
type( t[ 2 ] ) == "string" then
r[ t[ 1 ] ] = t[ 2 ]
else
break -- for i
end
end -- for i
else
r = false
end
Multilingual.iso639[ access ] = r
end
return r or { }
end -- fetchISO639()
local fill = function ( access, alien, frame )
-- Expand language name template
-- Precondition:
-- access -- string, with language code
-- alien -- language code for which to be generated
-- frame -- frame, if available
-- Postcondition:
-- Returns string
local template = Multilingual.tmplLang
local r
if type( template ) ~= "table" then
local cnf = fetch( "Multilingual", "config" )
if cnf then
template = cnf.tmplLang
end
end
if type( template ) == "table" then
local source = template.title
local f, lucky, s
Multilingual.tmplLang = template
if type( source ) ~= "string" and
type( template.namePat ) == "string" and
template.namePat:find( "%s", 1, true ) then
source = string.format( template.namePat, access )
end
if type( source ) == "string" then
if not Multilingual.frame then
if frame then
Multilingual.frame = frame
else
Multilingual.frame = mw.getCurrentFrame()
end
end
f = function ( a )
return Multilingual.frame:expandTemplate{ title = a }
end
lucky, s = pcall( f, source )
if lucky then
r = s
end
end
end
return r
end -- fill()
local find = function ( ask, alien )
-- Derive language code from name
-- Precondition:
-- ask -- language name, downcased
-- alien -- language code of ask
-- Postcondition:
-- nil, or string
local codes = mw.language.fetchLanguageNames( alien, "all" )
local r
for k, v in pairs( codes ) do
if mw.ustring.lower( v ) == ask then
r = k
break -- for k, v
end
end -- for k, v
if not r then
r = Multilingual.fair( ask )
end
return r
end -- find()
local fold = function ( frame )
-- Merge template and #invoke arglist
-- Precondition:
-- frame -- template frame
-- Postcondition:
-- table, with combined arglist
local r = { }
local f = function ( apply )
if type( apply ) == "table" and
type( apply.args ) == "table" then
for k, v in pairs( apply.args ) do
v = mw.text.trim( v )
if v ~= "" then
r[ tostring( k ) ] = v
end
end -- for k, v
end
end -- f()
f( frame:getParent() )
f( frame )
return r
end -- fold()
User.favorize = function ( accept, frame )
-- Guess user language
-- Precondition:
-- accept -- sequence table, with offered ISO 639 etc. codes
-- frame -- frame, if available
-- Postcondition:
-- Returns string with best code, or nil
if not ( User.self or User.langs ) then
if not User.trials then
User.tell = mw.message.new( User.sniffer )
if User.tell:exists() then
User.trials = { }
if not Multilingual.frame then
if frame then
Multilingual.frame = frame
else
Multilingual.frame = mw.getCurrentFrame()
end
end
User.sin = Multilingual.frame:callParserFunction( "int",
User.sniffer )
else
User.langs = true
end
end
if User.sin then
local order = { }
local post = { }
local three = { }
local unfold = { }
local s, sin
for i = 1, #accept do
s = accept[ i ]
if not User.trials[ s ] then
if #s > 2 then
if s:find( "-", 3, true ) then
table.insert( unfold, s )
else
table.insert( three, s )
end
else
if Multilingual.prefer[ s ] then
table.insert( order, s )
else
table.insert( post, s )
end
end
end
end -- for i
for i = 1, #post do
table.insert( order, post[ i ] )
end -- for i
for i = 1, #three do
table.insert( order, three[ i ] )
end -- for i
for i = 1, #unfold do
table.insert( order, unfold[ i ] )
end -- for i
for i = 1, #order do
s = order[ i ]
sin = User.tell:inLanguage( s ):plain()
if sin == User.sin then
User.self = s
break -- for i
else
User.trials[ s ] = true
end
end -- for i
end
end
return User.self
end -- User.favorize()
Multilingual.fair = function ( ask )
-- Format language specification according to RFC 5646 etc.
-- Precondition:
-- ask -- string or table, as created by .getLang()
-- Postcondition:
-- Returns string, or false
local s = type( ask )
local q, r
if s == "table" then
q = ask
elseif s == "string" then
q = Multilingual.getLang( ask )
end
if q and
q.legal and
mw.language.isKnownLanguageTag( q.base ) then
r = q.base
if q.n > 1 then
local order = { "extlang",
"script",
"region",
"other",
"extension" }
for i = 1, #order do
s = q[ order[ i ] ]
if s then
r = string.format( "%s-%s", r, s )
end
end -- for i
end
end
return r or false
end -- Multilingual.fair()
Multilingual.fallback = function ( able, another )
-- Is another language suitable as replacement?
-- Precondition:
-- able -- language version specifier to be supported
-- another -- language specifier of a possible replacement,
-- or not to retrieve a fallback table
-- Postcondition:
-- Returns boolean, or table with fallback codes
local r
if type( able ) == "string" and #able > 0 then
if type( another ) == "string" and #another > 0 then
if able == another then
r = true
else
local s = Multilingual.getBase( able )
if s == another then
r = true
else
local others = mw.language.getFallbacksFor( s )
r = feasible( another, others )
end
end
else
local s = Multilingual.getBase( able )
if s then
r = mw.language.getFallbacksFor( s )
if r[ 1 ] == "en" then
local d = fetchISO639( "fallback" )
if type( d ) == "table" and
type( d[ s ] ) == "string" then
r = mw.text.split( d[ s ], "|" )
table.insert( r, "en" )
end
end
end
end
end
return r or false
end -- Multilingual.fallback()
Multilingual.findCode = function ( ask )
-- Retrieve code of local (current project or English) language name
-- Precondition:
-- ask -- string, with presumable language name
-- A code itself will be identified, too.
-- Postcondition:
-- Returns string, or false
local seek = mw.text.trim( ask )
local r = false
if #seek > 1 then
if seek:find( "[", 1, true ) then
local wlink = fetch( "WLink" )
if wlink and
type( wlink.getPlain ) == "function" then
seek = wlink.getPlain( seek )
end
end
seek = mw.ustring.lower( seek )
if Multilingual.isLang( seek ) then
r = Multilingual.fair( seek )
else
local collection = favorites()
for i = 1, #collection do
r = find( seek, collection[ i ] )
if r then
break -- for i
end
end -- for i
end
end
return r
end -- Multilingual.findCode()
Multilingual.fix = function ( attempt )
-- Fix frequently mistaken language code
-- Precondition:
-- attempt -- string, with presumable language code
-- Postcondition:
-- Returns string with correction, or false if no problem known
local r = fetchISO639( "correction" )[ attempt:lower() ]
return r or false
end -- Multilingual.fix()
Multilingual.format = function ( apply, alien, alter, active, alert,
frame, assembly, adjacent, ahead )
-- Format one or more languages
-- Precondition:
-- apply -- string with language list or item
-- alien -- language of the answer
-- -- nil, false, "*": native
-- -- "!": current project
-- -- "#": code, downcased, space separated
-- -- "-": code, mixcase, space separated
-- -- any valid code
-- alter -- capitalize, if "c"; downcase all, if "d"
-- capitalize first item only, if "f"
-- downcase every first word only, if "m"
-- active -- link items, if true
-- alert -- string with category title in case of error
-- frame -- if available
-- assembly -- string with split pattern, if list expected
-- adjacent -- string with list separator, else assembly
-- ahead -- string to prepend first element, if any
-- Postcondition:
-- Returns string, or false if apply empty
local r = false
if apply then
local slang
if assembly then
local bucket = mw.text.split( apply, assembly )
local shift = alter
local separator
if adjacent then
separator = adjacent
elseif alien == "#" or alien == "-" then
separator = " "
else
separator = assembly
end
for k, v in pairs( bucket ) do
slang = Multilingual.format( v, alien, shift, active,
alert )
if slang then
if r then
r = string.format( "%s%s%s",
r, separator, slang )
else
r = slang
if shift == "f" then
shift = "d"
end
end
end
end -- for k, v
if r and ahead then
r = ahead .. r
end
else
local single = mw.text.trim( apply )
if single == "" then
r = false
else
local lapsus, slot
slang = Multilingual.findCode( single )
if slang then
if alien == "-" then
r = slang
elseif alien == "#" then
r = slang:lower()
else
r = Multilingual.getName( slang, alien )
if active then
slot = fill( slang, false, frame )
if slot then
local wlink = fetch( "WLink" )
if wlink and
type( wlink.getTarget )
== "function" then
slot = wlink.getTarget( slot )
end
else
lapsus = alert
end
end
end
else
r = single
if active then
local title = mw.title.makeTitle( 0, single )
if title.exists then
slot = single
end
end
lapsus = alert
end
if not r then
r = single
elseif alter == "c" or alter == "f" then
r = mw.ustring.upper( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
elseif alter == "d" then
if Multilingual.isMinusculable( slang, r ) then
r = mw.ustring.lower( r )
end
elseif alter == "m" then
if Multilingual.isMinusculable( slang, r ) then
r = mw.ustring.lower( mw.ustring.sub( r, 1, 1 ) )
.. mw.ustring.sub( r, 2 )
end
end
if slot then
if r == slot then
r = string.format( "[[%s]]", r )
else
r = string.format( "[[%s|%s]]", slot, r )
end
end
if lapsus and alert then
r = string.format( "%s[[Category:%s]]", r, alert )
end
end
end
end
return r
end -- Multilingual.format()
Multilingual.getBase = function ( ask )
-- Retrieve base language from possibly combined ISO language code
-- Precondition:
-- ask -- language code
-- Postcondition:
-- Returns string, or false
local r
if ask then
local slang = ask:match( "^%s*(%a%a%a?)-?%a*%s*$" )
if slang then
r = slang:lower()
else
r = false
end
else
r = false
end
return r
end -- Multilingual.getBase()
Multilingual.getLang = function ( ask )
-- Retrieve components of a RFC 5646 language code
-- Precondition:
-- ask -- language code with subtags
-- Postcondition:
-- Returns table with formatted subtags
-- .base
-- .region
-- .script
-- .suggest
-- .year
-- .extension
-- .other
-- .n
local tags = mw.text.split( ask, "-" )
local s = tags[ 1 ]
local r
if s:match( "^%a%a%a?$" ) then
r = { base = s:lower(),
legal = true,
n = #tags }
for i = 2, r.n do
s = tags[ i ]
if #s == 2 then
if r.region or not s:match( "%a%a" ) then
r.legal = false
else
r.region = s:upper()
end
elseif #s == 4 then
if s:match( "%a%a%a%a" ) then
r.legal = ( not r.script )
r.script = s:sub( 1, 1 ):upper() ..
s:sub( 2 ):lower()
elseif s:match( "20%d%d" ) or
s:match( "1%d%d%d" ) then
r.legal = ( not r.year )
r.year = s
else
r.legal = false
end
elseif #s == 3 then
if r.extlang or not s:match( "%a%a%a" ) then
r.legal = false
else
r.extlang = s:lower()
end
elseif #s == 1 then
s = s:lower()
if s:match( "[tux]" ) then
r.extension = s
for k = i + 1, r.n do
s = tags[ k ]
if s:match( "^%w+$" ) then
r.extension = string.format( "%s-%s",
r.extension, s )
else
r.legal = false
end
end -- for k
else
r.legal = false
end
break -- for i
else
r.legal = ( not r.other ) and
s:match( "%a%a%a" )
r.other = s:lower()
end
if not r.legal then
break -- for i
end
end -- for i
if r.legal then
r.suggest = Multilingual.fix( r.base )
if r.suggest then
r.legal = false
end
end
else
r = { legal = false }
end
if not r.legal then
local cnf = fetch( "Multilingual", "config" )
if cnf and type( cnf.scream ) == "string" then
r.scream = cnf.scream
end
end
return r
end -- Multilingual.getLang()
Multilingual.getName = function ( ask, alien )
-- Which name is assigned to this language code?
-- Precondition:
-- ask -- language code
-- alien -- language of the answer
-- -- nil, false, "*": native
-- -- "!": current project
-- -- any valid code
-- Postcondition:
-- Returns string, or false
local r
if ask then
local slang = alien
local tLang
if slang then
if slang == "*" then
slang = Multilingual.fair( ask )
elseif slang == "!" then
slang = favorites()[ 1 ]
else
slang = Multilingual.fair( slang )
end
else
slang = Multilingual.fair( ask )
end
if not slang then
slang = ask or "?????"
end
slang = slang:lower()
tLang = fetch( "Multilingual", "names" )
if tLang then
tLang = tLang[ slang ]
if tLang then
r = tLang[ ask ]
end
end
if not r then
if not Multilingual.ext.tMW then
Multilingual.ext.tMW = { }
end
tLang = Multilingual.ext.tMW[ slang ]
if tLang == nil then
tLang = mw.language.fetchLanguageNames( slang )
if tLang then
Multilingual.ext.tMW[ slang ] = tLang
else
Multilingual.ext.tMW[ slang ] = false
end
end
if tLang then
r = tLang[ ask ]
end
end
if not r then
r = mw.language.fetchLanguageName( ask:lower(), slang )
if r == "" then
r = false
end
end
else
r = false
end
return r
end -- Multilingual.getName()
Multilingual.i18n = function ( available, alt, frame )
-- Select translatable message
-- Precondition:
-- available -- table, with mapping language code ./. text
-- alt -- string|nil|false, with fallback text
-- frame -- frame, if available
-- Returns
-- 1. string|nil|false, with selected message
-- 2. string|nil|false, with language code
local r1, r2
if type( available ) == "table" then
local codes = { }
local trsl = { }
local slang
for k, v in pairs( available ) do
if type( k ) == "string" and
type( v ) == "string" then
slang = mw.text.trim( k:lower() )
table.insert( codes, slang )
trsl[ slang ] = v
end
end -- for k, v
slang = Multilingual.userLang( codes, frame )
if slang and trsl[ slang ] then
r1 = mw.text.trim( trsl[ slang ] )
if r1 == "" then
r1 = false
else
r2 = slang
end
end
end
if not r1 and type( alt ) == "string" then
r1 = mw.text.trim( alt )
if r1 == "" then
r1 = false
end
end
return r1, r2
end -- Multilingual.i18n()
Multilingual.int = function ( access, alien, apply )
-- Translated system message
-- Precondition:
-- access -- message ID
-- alien -- language code
-- apply -- nil, or sequence table with parameters $1, $2, ...
-- Postcondition:
-- Returns string, or false
local o = mw.message.new( access )
local r
if o:exists() then
if type( alien ) == "string" then
o:inLanguage( alien:lower() )
end
if type( apply ) == "table" then
o:params( apply )
end
r = o:plain()
end
return r or false
end -- Multilingual.int()
Multilingual.isLang = function ( ask, additional )
-- Could this be an ISO language code?
-- Precondition:
-- ask -- language code
-- additional -- true, if Wiki codes like "simple" permitted
-- Postcondition:
-- Returns boolean
local r, s
if additional then
s = ask
else
s = Multilingual.getBase( ask )
end
if s then
r = mw.language.isKnownLanguageTag( s )
if r then
r = not Multilingual.fix( s )
elseif additional then
r = Multilingual.exotic[ s ] or false
end
else
r = false
end
return r
end -- Multilingual.isLang()
Multilingual.isLangWiki = function ( ask )
-- Could this be a Wiki language version?
-- Precondition:
-- ask -- language version specifier
-- Postcondition:
-- Returns boolean
local r
local s = Multilingual.getBase( ask )
if s then
r = mw.language.isSupportedLanguage( s ) or
Multilingual.exotic[ ask ]
else
r = false
end
return r
end -- Multilingual.isLangWiki()
Multilingual.isMinusculable = function ( ask, assigned )
-- Could this language name become downcased?
-- Precondition:
-- ask -- language code, or nil
-- assigned -- language name, or nil
-- Postcondition:
-- Returns boolean
local r = true
if ask then
local cnf = fetch( "Multilingual", "config" )
if cnf then
local s = string.format( " %s ", ask:lower() )
if type( cnf.stopMinusculization ) == "string"
and cnf.stopMinusculization:find( s, 1, true ) then
r = false
end
if r and assigned
and type( cnf.seekMinusculization ) == "string"
and cnf.seekMinusculization:find( s, 1, true )
and type( cnf.scanMinusculization ) == "string" then
local scan = assigned:gsub( "[%(%)]", " " ) .. " "
if not scan:find( cnf.scanMinusculization ) then
r = false
end
end
end
end
return r
end -- Multilingual.isMinusculable()
Multilingual.isRTL = function ( ask )
-- Check whether language is written right-to-left
-- Precondition:
-- ask -- string, with language (or script) code
-- Returns true, if right-to-left
local r
Multilingual.rtl = Multilingual.rtl or { }
r = Multilingual.rtl[ ask ]
if type( r ) ~= "boolean" then
local bib = fetch( "ISO15924" )
if type( bib ) == "table" and
type( bib.isRTL ) == "function" then
r = bib.isRTL( ask )
else
r = mw.language.new( ask ):isRTL()
end
Multilingual.rtl[ ask ] = r
end
return r
end -- Multilingual.isRTL()
Multilingual.message = function ( arglist, frame )
-- Show text in best match of user language like system message
-- Precondition:
-- arglist -- template arguments
-- frame -- frame, if available
-- Postcondition:
-- Returns string with appropriate text
local r
if type( arglist ) == "table" then
local t = { }
local m, p, save
for k, v in pairs( arglist ) do
if type( k ) == "string" and
type( v ) == "string" then
v = mw.text.trim( v )
if v ~= "" then
if k:match( "^%l%l" ) then
t[ k ] = v
elseif k:match( "^%$%d$" ) and k ~= "$0" then
p = p or { }
k = tonumber( k:match( "^%$(%d)$" ) )
p[ k ] = v
if not m or k > m then
m = k
end
end
end
end
end -- for k, v
if type( arglist[ "-" ] ) == "string" then
save = arglist[ arglist[ "-" ] ]
end
r = Multilingual.i18n( t, save, frame )
if p and r and r:find( "$", 1, true ) then
t = { }
for i = 1, m do
t[ i ] = p[ i ] or ""
end -- for i
r = mw.message.newRawMessage( r, t ):plain()
end
end
return r or ""
end -- Multilingual.message()
Multilingual.sitelink = function ( all, frame )
-- Make link at local or other site with optimal linktext translation
-- Precondition:
-- all -- string or table or number, item ID or entity
-- frame -- frame, if available
-- Postcondition:
-- Returns string with any helpful internal link, or plain text
local s = type( all )
local object, r
if s == "table" then
object = all
elseif s == "string" then
object = mw.wikibase.getEntity( all )
elseif s == "number" then
object = mw.wikibase.getEntity( string.format( "Q%d", all ) )
end
if type( object ) == "table" then
local collection = object.sitelinks
local entry
s = false
if type( collection ) == "table" then
Multilingual.site = Multilingual.site or
mw.wikibase.getGlobalSiteId()
entry = collection[ Multilingual.site ]
if entry then
s = ":" .. entry.title
elseif collection.enwiki then
s = "w:en:" .. collection.enwiki.title
end
end
r = Multilingual.wikibase( object, "labels", frame )
if s then
if s == ":" .. r then
r = string.format( "[[%s]]", s )
else
r = string.format( "[[%s|%s]]", s, r )
end
end
end
return r or ""
end -- Multilingual.sitelink()
Multilingual.tabData = function ( access, at, alt, frame )
-- Retrieve translated keyword from commons:Data:****.tab
-- Precondition:
-- access -- string, with page identification on Commons
-- at -- string, with keyword
-- alt -- string|nil|false, with fallback text
-- frame -- frame, if available
-- Returns
-- 1. string|nil|false, with selected message
-- 2. language code, or "error"
local data = fetchData( access )
local r1, r2
if type( data ) == "table" then
if type( at ) == "string" then
local seek = mw.text.trim( at )
if seek == "" then
r1 = "EMPTY Multilingual.tabData key"
else
local e, poly
for i = 1, #data do
e = data[ i ]
if type( e ) == "table" then
if e[ 1 ] == seek then
if type( e[ 2 ] ) == "table" then
poly = e[ 2 ]
else
r1 = "INVALID Multilingual.tabData bad #"
.. tostring( i )
end
break -- for i
end
else
break -- for i
end
end -- for i
if poly then
data = poly
else
r1 = "UNKNOWN Multilingual.tabData key: " .. seek
end
end
else
r1 = "INVALID Multilingual.tabData key"
end
else
r1 = data
end
if r1 then
r2 = "error"
elseif data then
r1, r2 = Multilingual.i18n( data, alt, frame )
r2 = r2 or "error"
end
return r1, r2
end -- Multilingual.tabData()
Multilingual.userLang = function ( accept, frame )
-- Try to support user language by application
-- Precondition:
-- accept -- string or table
-- space separated list of available ISO 639 codes
-- Default: project language, or English
-- frame -- frame, if available
-- Postcondition:
-- Returns string with appropriate code
local s = type( accept )
local codes, r, slang
if s == "string" then
codes = mw.text.split( accept:lower(), "%s+" )
elseif s == "table" then
codes = { }
for i = 1, #accept do
s = accept[ i ]
if type( s ) == "string" and
s ~= "" then
table.insert( codes, s:lower() )
end
end -- for i
end
slang = User.favorize( codes, frame )
if slang then
if feasible( slang, codes ) then
r = slang
elseif slang:find( "-", 1, true ) then
slang = Multilingual.getBase( slang )
if feasible( slang, codes ) then
r = slang
end
end
if not r then
local others = mw.language.getFallbacksFor( slang )
for i = 1, #others do
slang = others[ i ]
if feasible( slang, codes ) then
r = slang
break -- for i
end
end -- for i
end
end
if not r then
local back = favorites()
for i = 1, #back do
slang = back[ i ]
if feasible( slang, codes ) then
r = slang
break -- for i
end
end -- for i
if not r and codes[ 1 ] then
r = codes[ 1 ]
end
end
return r or favorites()[ 1 ]
end -- Multilingual.userLang()
Multilingual.userLangCode = function ()
-- Guess a user language code
-- Postcondition:
-- Returns code of current best guess
return User.self or favorites()[ 1 ]
end -- Multilingual.userLangCode()
Multilingual.wikibase = function ( all, about, attempt, frame )
-- Optimal translation of wikibase component
-- Precondition:
-- all -- string or table, object ID or entity
-- about -- boolean, true "descriptions" or false "labels"
-- attempt -- string or not, code of preferred language
-- frame -- frame, if available
-- Postcondition:
-- Returns
-- 1. string, with selected message
-- 2. string, with language code, or not
local s = type( all )
local object, r, r2
if s == "table" then
object = all
elseif s == "string" then
object = mw.wikibase.getEntity( all )
end
if type( object ) == "table" then
if about and about ~= "labels" then
s = "descriptions"
else
s = "labels"
end
object = object[ s ]
if type( object ) == "table" then
if object[ attempt ] then
r = object[ attempt ].value
r2 = attempt
else
local poly
for k, v in pairs( object ) do
poly = poly or { }
poly[ k ] = v.value
end -- for k, v
if poly then
r, r2 = Multilingual.i18n( poly, nil, frame )
end
end
end
end
return r or "", r2
end -- Multilingual.wikibase()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2020-08-17
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
if type( entity ) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
p.fair = function ( frame )
-- Format language code
-- 1 -- language code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.fair( s ) or ""
end -- p.fair
p.fallback = function ( frame )
-- Is another language suitable as replacement?
-- 1 -- language version specifier to be supported
-- 2 -- language specifier of a possible replacement
local s1 = mw.text.trim( frame.args[ 1 ] or "" )
local s2 = mw.text.trim( frame.args[ 2 ] or "" )
local r = Multilingual.fallback( s1, s2 )
if type( r ) == "table" then
r = r[ 1 ]
else
r = r and "1" or ""
end
return r
end -- p.fallback
p.findCode = function ( frame )
-- Retrieve language code from language name
-- 1 -- name in current project language
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.findCode( s ) or ""
end -- p.findCode
p.fix = function ( frame )
local r = frame.args[ 1 ]
if r then
r = Multilingual.fix( mw.text.trim( r ) )
end
return r or ""
end -- p.fix
p.format = function ( frame )
-- Format one or more languages
-- 1 -- language list or item
-- slang -- language of the answer, if not native
-- * -- native
-- ! -- current project
-- any valid code
-- shift -- capitalize, if "c"; downcase, if "d"
-- capitalize first item only, if "f"
-- link -- 1 -- link items
-- scream -- category title in case of error
-- split -- split pattern, if list expected
-- separator -- list separator, else split
-- start -- prepend first element, if any
local r
local link
if frame.args.link == "1" then
link = true
end
r = Multilingual.format( frame.args[ 1 ],
frame.args.slang,
frame.args.shift,
link,
frame.args.scream,
frame,
frame.args.split,
frame.args.separator,
frame.args.start )
return r or ""
end -- p.format
p.getBase = function ( frame )
-- Retrieve base language from possibly combined ISO language code
-- 1 -- code
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.getBase( s ) or ""
end -- p.getBase
p.getName = function ( frame )
-- Retrieve language name from ISO language code
-- 1 -- code
-- 2 -- language to be used for the answer, if not native
-- ! -- current project
-- * -- native
-- any valid code
local s = mw.text.trim( frame.args[ 1 ] or "" )
local slang = frame.args[ 2 ]
local r
Multilingual.frame = frame
if slang then
slang = mw.text.trim( slang )
end
r = Multilingual.getName( s, slang )
return r or ""
end -- p.getName
p.int = function ( frame )
-- Translated system message
-- 1 -- message ID
-- lang -- language code
-- $1, $2, ... -- parameters
local sysMsg = frame.args[ 1 ]
local r
if sysMsg then
sysMsg = mw.text.trim( sysMsg )
if sysMsg ~= "" then
local n = 0
local slang = frame.args.lang
local i, params, s
if slang == "" then
slang = false
end
for k, v in pairs( frame.args ) do
if type( k ) == "string" then
s = k:match( "^%$(%d+)$" )
if s then
i = tonumber( s )
if i > n then
n = i
end
end
end
end -- for k, v
if n > 0 then
local s
params = { }
for i = 1, n do
s = frame.args[ "$" .. tostring( i ) ] or ""
table.insert( params, s )
end -- for i
end
r = Multilingual.int( sysMsg, slang, params )
end
end
return r or ""
end -- p.int
p.isLang = function ( frame )
-- Could this be an ISO language code?
-- 1 -- code
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLang, s )
return r and "1" or ""
end -- p.isLang
p.isLangWiki = function ( frame )
-- Could this be a Wiki language version?
-- 1 -- code
-- Returns non-empty, if possibly language version
local s = mw.text.trim( frame.args[ 1 ] or "" )
local lucky, r = pcall( Multilingual.isLangWiki, s )
return r and "1" or ""
end -- p.isLangWiki
p.isRTL = function ( frame )
-- Check whether language is written right-to-left
-- 1 -- string, with language code
-- Returns non-empty, if right-to-left
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.isRTL( s ) and "1" or ""
end -- p.isRTL()
p.message = function ( frame )
-- Translation of text element
return Multilingual.message( fold( frame ), frame )
end -- p.message
p.sitelink = function ( frame )
-- Make link at local or other site with optimal linktext translation
-- 1 -- item ID
local s = mw.text.trim( frame.args[ 1 ] or "" )
local r
if s:match( "^%d+$") then
r = tonumber( s )
elseif s:match( "^Q%d+$") then
r = s
end
if r then
r = Multilingual.sitelink( r, frame )
end
return r or s
end -- p.sitelink
p.tabData = function ( frame )
-- Retrieve best message text from Commons Data
-- 1 -- page identification on Commons
-- 2 -- keyword
-- alt -- fallback text
local suite = frame.args[ 1 ]
local seek = frame.args[ 2 ]
local salt = frame.args.alt
local r = Multilingual.tabData( suite, seek, salt, frame )
return r
end -- p.tabData
p.userLang = function ( frame )
-- Which language does the current user prefer?
-- 1 -- space separated list of available ISO 639 codes
local s = mw.text.trim( frame.args[ 1 ] or "" )
return Multilingual.userLang( s, frame )
end -- p.userLang
p.wikibase = function ( frame )
-- Optimal translation of wikibase component
-- 1 -- object ID
-- 2 -- 1 for "descriptions", 0 for "labels".
-- or either "descriptions" or "labels"
local r
local s = mw.text.trim( frame.args[ 1 ] or "" )
if s ~= "" then
local s2 = mw.text.trim( frame.args[ 2 ] or "0" )
local slang = mw.text.trim( frame.args.lang or "" )
local large = ( s2 ~= "" and s2 ~= "0" )
if slang == "" then
slang = false
end
r = Multilingual.wikibase( s, large, slang, frame )
end
return r or ""
end -- p.wikibase
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe()
p.Multilingual = function ()
return Multilingual
end -- p.Multilingual
return p
d1zm42sep4ytfi0dl3dok26gecqprzg
Tempilet:Template link no redirect
10
1133
9275
2022-09-09T17:59:39Z
en>MusikBot II
0
Protected "[[Template:Template link no redirect]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 61213 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9275
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|Template:{{{1}}}}}
| <span class="plainlinks">{{[{{{{{|safesubst:}}}fullurl:Template:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]}}</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|{{[[:{{{{{|safesubst:}}}Template:FULLPAGENAME:{{{1}}}}}|{{{2}}}]]}}|{{[[:{{{{{|safesubst:}}}FULLPAGENAME:Template:{{{1}}}}}|{{{1}}}]]}}}}
}}<noinclude>
{{documentation}}
</noinclude>
50p95ruqsind3drddlv0lkso4oxi8e3
9276
9275
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Template_link_no_redirect]]
9275
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|Template:{{{1}}}}}
| <span class="plainlinks">{{[{{{{{|safesubst:}}}fullurl:Template:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]}}</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|{{[[:{{{{{|safesubst:}}}Template:FULLPAGENAME:{{{1}}}}}|{{{2}}}]]}}|{{[[:{{{{{|safesubst:}}}FULLPAGENAME:Template:{{{1}}}}}|{{{1}}}]]}}}}
}}<noinclude>
{{documentation}}
</noinclude>
50p95ruqsind3drddlv0lkso4oxi8e3
Tempilet:Tl-r
10
1134
9277
2022-09-09T17:59:40Z
en>MusikBot II
0
Protected "[[Template:Tl-r]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 61213 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9277
wikitext
text/x-wiki
#REDIRECT [[Template:Template link no redirect]]
fwrhppxq5zgj058i2w44hvpcv8nryx0
9278
9277
2026-08-23T03:37:40Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tl-r]]
9277
wikitext
text/x-wiki
#REDIRECT [[Template:Template link no redirect]]
fwrhppxq5zgj058i2w44hvpcv8nryx0
Tempilet:Shortcut mini
10
1135
9279
2026-01-11T17:18:54Z
en>Newslinger
0
Support shortcuts with spaces by using [[:mw:Help:Magic words#fullurl|fullurl]] magic word, per [[Template talk:Shortcut mini#Shortcuts with spaces]]
9279
wikitext
text/x-wiki
<onlyinclude><includeonly><br/><span class="wp-rsp-sc"><span class="plainlinks">[{{fullurl:{{{1|}}}|redirect=no}} {{{1|}}}]</span><span style="display: none">[[:{{{1}}}]]</span> 📌</span></includeonly></onlyinclude>{{Documentation}}<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
a0hb418thaukpgdg0vrg9eecyq6ltx9
9280
9279
2026-08-23T03:37:41Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Shortcut_mini]]
9279
wikitext
text/x-wiki
<onlyinclude><includeonly><br/><span class="wp-rsp-sc"><span class="plainlinks">[{{fullurl:{{{1|}}}|redirect=no}} {{{1|}}}]</span><span style="display: none">[[:{{{1}}}]]</span> 📌</span></includeonly></onlyinclude>{{Documentation}}<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
a0hb418thaukpgdg0vrg9eecyq6ltx9
Tempilet:Shortcut templates
10
1136
9281
2026-06-18T18:40:58Z
en>FaviFake
0
9281
wikitext
text/x-wiki
<noinclude>==See also ==
</noinclude>
{| class="wikitable" style=float:right
|- style="font-size:85%"
|+[[Wikipedia:Shortcut|Shortcut]] templates
!Template
!Shortcut
!Result
|-
|<small>{{Template link|Shortcut}}</small>
|<small>{{Tlc|Sh}}</small>
|<small>{{Shortcut|WP:THIS}}</small>
|-
|<small>{{Template link|Shortcut compact}}</small>
|<small>{{Tlc|Hsh}}</small>
|<small>{{Shortcut compact|WP:THIS}}</small>
|-
|<small>{{Template link|Shortcut mini}}</small>
|<small>{{Tlc|Msh}}</small>
|<small>{{Shortcut mini|WP:THIS}}</small>
|-
|<small>{{Template link|Template shortcut}}</small>
|<small>{{Tlc|Tsh}}</small>
|<small>{{Template shortcut|This}}</small>
|-
|<small>{{Template link|Template redirect}}</small>
|<small>{{Tlc|Tlr}}</small>
|<small>{{Template redirect|This}}</small>
|-
|<small>{{Template link|Short URL box}}</small>
|<small>{{Tlc|Urlb}}</small>
|<small>{{Short URL box|4Q7}}</small>
|-
|<small>{{Template link|Shortcut-style further links}}</small>
|<small>{{Tlc|Msh}}</small>
|<small>{{Shortcut-style further links|WP:THIS}}</small>
|}
* {{T|Anchor}} – Creates an HTML anchor that can be linked to
** {{T|Visible anchor}} – Highlights {{Va|the linked text}}, [[#the linked text|like this]].
* {{T|Section link}} – Link to an anchor or section
* {{T|R for convenience}} – For placement on the redirect page
** {{T|R from shortcut}} – For shortcut boxes
** {{T|R to redirect template}} – For template redirects<noinclude>
{{documentation
|content=
{{No documentation}}
Used to compare the appearance and functions of the many shortcut templates, usually transcluded in relevant pages such as {{Tl|Shortcut/doc}} and [[Wikipedia:Shortcut]].
[[Category:Shortcut templates| ]]
}}
</noinclude>
sz2ji1rq4o6rsqrhdbw1re6eygy2zui
9282
9281
2026-08-23T03:37:41Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Shortcut_templates]]
9281
wikitext
text/x-wiki
<noinclude>==See also ==
</noinclude>
{| class="wikitable" style=float:right
|- style="font-size:85%"
|+[[Wikipedia:Shortcut|Shortcut]] templates
!Template
!Shortcut
!Result
|-
|<small>{{Template link|Shortcut}}</small>
|<small>{{Tlc|Sh}}</small>
|<small>{{Shortcut|WP:THIS}}</small>
|-
|<small>{{Template link|Shortcut compact}}</small>
|<small>{{Tlc|Hsh}}</small>
|<small>{{Shortcut compact|WP:THIS}}</small>
|-
|<small>{{Template link|Shortcut mini}}</small>
|<small>{{Tlc|Msh}}</small>
|<small>{{Shortcut mini|WP:THIS}}</small>
|-
|<small>{{Template link|Template shortcut}}</small>
|<small>{{Tlc|Tsh}}</small>
|<small>{{Template shortcut|This}}</small>
|-
|<small>{{Template link|Template redirect}}</small>
|<small>{{Tlc|Tlr}}</small>
|<small>{{Template redirect|This}}</small>
|-
|<small>{{Template link|Short URL box}}</small>
|<small>{{Tlc|Urlb}}</small>
|<small>{{Short URL box|4Q7}}</small>
|-
|<small>{{Template link|Shortcut-style further links}}</small>
|<small>{{Tlc|Msh}}</small>
|<small>{{Shortcut-style further links|WP:THIS}}</small>
|}
* {{T|Anchor}} – Creates an HTML anchor that can be linked to
** {{T|Visible anchor}} – Highlights {{Va|the linked text}}, [[#the linked text|like this]].
* {{T|Section link}} – Link to an anchor or section
* {{T|R for convenience}} – For placement on the redirect page
** {{T|R from shortcut}} – For shortcut boxes
** {{T|R to redirect template}} – For template redirects<noinclude>
{{documentation
|content=
{{No documentation}}
Used to compare the appearance and functions of the many shortcut templates, usually transcluded in relevant pages such as {{Tl|Shortcut/doc}} and [[Wikipedia:Shortcut]].
[[Category:Shortcut templates| ]]
}}
</noinclude>
sz2ji1rq4o6rsqrhdbw1re6eygy2zui
MediaWiki:Mainpage
8
1137
9293
2026-08-23T04:40:42Z
RAPTOR7762
18
/* */
9293
wikitext
text/x-wiki
Peji In Siri
p88s4racytu2jcgfqili9ix4n3ql1te
Peji Unsiri
0
1138
9295
2026-08-23T04:41:31Z
RAPTOR7762
18
RAPTOR7762 moved page [[Peji Unsiri]] to [[Peji In Siri]]
9295
wikitext
text/x-wiki
#REDIRECT [[Peji In Siri]]
57zatl8ujw45dsxqsu7nfpz3oiqmy2e
Mossa:Peji Unsiri
1
1139
9297
2026-08-23T04:41:31Z
RAPTOR7762
18
RAPTOR7762 moved page [[Mossa:Peji Unsiri]] to [[Mossa:Peji In Siri]]
9297
wikitext
text/x-wiki
#REDIRECT [[Mossa:Peji In Siri]]
ggn507vyayhbi87m4nypqlgt7ca68iz
Tempilet:Pagetype
10
1140
9299
2014-07-09T08:29:38Z
Callanecc
315
Changed protection level of Template:Pagetype: [[WP:High-risk templates|Highly visible template]]: With more than 5.5 million transclusions and cascade protections this should be full protected as well ([Edit=Allow only administrators] (indefinite) [Move=
9299
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:pagetype|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
lljnsh3xa96oyrio8us1qbonct9sq7b
9300
9299
2026-08-23T08:16:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pagetype]]
9299
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:pagetype|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
lljnsh3xa96oyrio8us1qbonct9sq7b
9357
9300
2026-08-23T08:19:24Z
RAPTOR7762
18
Protected "[[Tempilet:Pagetype]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
9299
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:pagetype|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
lljnsh3xa96oyrio8us1qbonct9sq7b
Module:Pagetype
828
1141
9303
2024-05-21T17:35:20Z
MSGJ
321
fix for files and interface messages which do exist but are not stored locally
9303
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- This meta-module which automatically detects namespaces, and allows --
-- for a great deal of customisation. It can easily be ported to other --
-- wikis by changing the values in the [[Module:Pagetype/config]]. --
-- --
--------------------------------------------------------------------------------
-- Load config.
local cfg = mw.loadData('Module:Pagetype/config')
-- Load required modules.
local yesno = require('Module:Yesno')
local p = {}
-- Look up a namespace argument in the args table.
local function lookUpNamespaceArg(args, key)
local arg = args[key]
-- Convert "yes", "1" etc. to true, "no", "0" etc. to false, and leave
-- other values the same.
return yesno(arg, arg)
end
-- Append multiple values to an array
local function appendMultiple(target, source)
for _, value in ipairs(source) do
table.insert(target, value)
end
end
-- Get argument keys for a title's namespace
local function getNamespaceArgKeys(title)
local nsInfo = mw.site.namespaces[title.namespace]
local customAliases = cfg.customNamespaceAliases[title.namespace] or {}
local keys = {}
if nsInfo.name ~= '' then
table.insert(keys, nsInfo.name)
end
if nsInfo.canonicalName ~= nsInfo.name and nsInfo.canonicalName ~= '' then
table.insert(keys, nsInfo.canonicalName)
end
appendMultiple(keys, nsInfo.aliases)
appendMultiple(keys, customAliases)
return keys
end
-- Get the argument for a title's namespace, if it was specified in the args table.
local function getNamespaceArg(title, args)
if title.isTalkPage then
return lookUpNamespaceArg(args, cfg.talk)
end
for _, key in ipairs(getNamespaceArgKeys(title)) do
local arg = lookUpNamespaceArg(args, mw.ustring.lower(key))
if arg ~= nil then
return arg
end
end
return nil
end
-- Look up a page type specific to the title's namespace
local function getExplicitPageType(title)
if title.isTalkPage then
return cfg.talkDefault
else
return cfg.pagetypes[title.namespace]
end
end
-- Get a default page type that is not specific to the title's namespace
local function getDefaultPageType(args)
local other = lookUpNamespaceArg(args, cfg.other)
if type(other) == 'string' then
return other
else
return cfg.otherDefault
end
end
local function detectRedirects(title, args)
local redirect = lookUpNamespaceArg(args, cfg.redirect)
if redirect == false then
-- Don't detect redirects if they have been specifically disallowed.
return nil
end
-- Allow custom values for redirects.
if not title.isRedirect then
return nil
elseif type(redirect) == 'string' then
return redirect
else
return cfg.redirectDefault
end
end
local function capitalize(pageType)
local first = mw.ustring.sub(pageType, 1, 1)
local rest = mw.ustring.sub(pageType, 2)
return mw.ustring.upper(first) .. rest
end
local function pluralize(pageType)
if cfg.irregularPlurals[pageType] then
return cfg.irregularPlurals[pageType]
else
return pageType .. cfg.plural -- often 's'
end
end
local function parseContent(title, args, optionsList)
if title.namespace==828 and title.subpageText~='doc' -- don't detect modules
or not title.exists -- can't check unless page exists
then
return nil
end
local content = title:getContent()
if content == nil then
return nil
end
local templates -- lazily evaluated
for _, options in next, optionsList do
local list, parameter, default, articleOnly = unpack(options, 1, 4)
if not articleOnly or title.namespace==0 then -- only check for templates if we should...
local out = lookUpNamespaceArg(args, parameter)
if type(out) == "string" or (out ~= false and default) then -- ...and if we actually have anything to say about them
if not templates then
templates = {} -- do our delayed evaluation now that we are required to
content = require('Module:Wikitext Parsing').PrepareText(content) -- disregard templates which do not have any affect
for template in string.gmatch(content, "{{%s*([^|}]-)%s*[|}]") do
templates[#templates+1] = capitalize(template)
end
end
local wantedTemplates = mw.loadData('Module:Pagetype/' .. list)
local templateFound = false
for _, template in next, templates do
if wantedTemplates[template] then
templateFound = true
break
end
end
if templateFound then
if type(out)=='string' then
return out
elseif out ~= false and default then
return default
end
end
end
end
end
end
-- Find pages which do not exist
local function nonExistent(title, args)
local arg = lookUpNamespaceArg(args, cfg.ne)
if arg == false then
return nil
end
local exists = false
if title.exists then -- not an article if it does not exist
exists = true
elseif title.namespace==8 and mw.message.new(title.text):exists() then
exists = true
elseif title.namespace==6 and title.fileExists then
exists = true
end
if not exists then
if type(arg) == 'string' then
return arg
else
return cfg.naDefault
end
end
end
-- Get page types for mainspaces pages with an explicit class specified
local function getMainNamespaceClassPageType(title, args)
local class = args[1]
if type(class) == 'string' then -- Put in lower case so e.g. "na" and "NA" will both match
class = mw.ustring.lower(class)
end
local arg = lookUpNamespaceArg(args, cfg.na)
if arg == false then -- don't check for this class if it is specifically disallowed
return nil
end
if cfg.naAliases[class] then
if type(arg) == 'string' then
return arg
else
return cfg.naDefault
end
else
return nil
end
end
-- Get page type specified by an explicit namespace argument.
local function getNamespaceArgPageType(title, args)
local namespaceArg = getNamespaceArg(title, args)
if namespaceArg == true then
-- Namespace has been explicitly enabled, so return the default for
-- this namespace
return getExplicitPageType(title)
elseif namespaceArg == false then
-- Namespace has been explicitly disabled
return getDefaultPageType(args)
elseif namespaceArg then
-- This namespaces uses custom text
return namespaceArg
else
return nil
end
end
-- Get page type not specified or detected by other means
local function getOtherPageType(title, args)
-- Whether the title is in the set of default active namespaces which are looked up in cfg.pagetypes.
local isInDefaultActiveNamespace = false
local defaultNamespacesKey = args[cfg.defaultns]
if defaultNamespacesKey == cfg.defaultnsAll then
isInDefaultActiveNamespace = true
else
local defaultNamespaces
if defaultNamespacesKey == cfg.defaultnsExtended then
defaultNamespaces = cfg.extendedNamespaces
elseif defaultNamespacesKey == cfg.defaultnsNone then
defaultNamespaces = {}
else
defaultNamespaces = cfg.defaultNamespaces
end
isInDefaultActiveNamespace = defaultNamespaces[title.namespace]
end
if isInDefaultActiveNamespace then
return getExplicitPageType(title)
else
return getDefaultPageType(args)
end
end
function p._main(args)
local title
if args.page then
title = mw.title.new(args.page)
else
title = mw.title.getCurrentTitle()
end
if title and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then
title = title.subjectPageTitle
end
local pageType = detectRedirects(title, args)
or nonExistent(title, args)
or parseContent(title, args, {
{'softredirect', cfg.softRedirect, cfg.softRedirectDefault},
{'setindex', cfg.sia, cfg.siaDefault, true},
{'disambiguation', cfg.dab, cfg.dabDefault, true},
{'rfd', cfg.rfd, cfg.rfdDefault},
})
or (title.namespace == 0 and getMainNamespaceClassPageType(title, args))
or getNamespaceArgPageType(title, args)
or getOtherPageType(title, args)
if yesno(args.plural, false) then
pageType = pluralize(pageType)
end
if yesno(args.caps, false) then
pageType = capitalize(pageType)
end
return pageType
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame)
return p._main(args)
end
return p
nqu0kvn2uc9jqptetkmoluzmahcxzzp
9304
9303
2026-08-23T08:17:05Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype]]
9303
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- This meta-module which automatically detects namespaces, and allows --
-- for a great deal of customisation. It can easily be ported to other --
-- wikis by changing the values in the [[Module:Pagetype/config]]. --
-- --
--------------------------------------------------------------------------------
-- Load config.
local cfg = mw.loadData('Module:Pagetype/config')
-- Load required modules.
local yesno = require('Module:Yesno')
local p = {}
-- Look up a namespace argument in the args table.
local function lookUpNamespaceArg(args, key)
local arg = args[key]
-- Convert "yes", "1" etc. to true, "no", "0" etc. to false, and leave
-- other values the same.
return yesno(arg, arg)
end
-- Append multiple values to an array
local function appendMultiple(target, source)
for _, value in ipairs(source) do
table.insert(target, value)
end
end
-- Get argument keys for a title's namespace
local function getNamespaceArgKeys(title)
local nsInfo = mw.site.namespaces[title.namespace]
local customAliases = cfg.customNamespaceAliases[title.namespace] or {}
local keys = {}
if nsInfo.name ~= '' then
table.insert(keys, nsInfo.name)
end
if nsInfo.canonicalName ~= nsInfo.name and nsInfo.canonicalName ~= '' then
table.insert(keys, nsInfo.canonicalName)
end
appendMultiple(keys, nsInfo.aliases)
appendMultiple(keys, customAliases)
return keys
end
-- Get the argument for a title's namespace, if it was specified in the args table.
local function getNamespaceArg(title, args)
if title.isTalkPage then
return lookUpNamespaceArg(args, cfg.talk)
end
for _, key in ipairs(getNamespaceArgKeys(title)) do
local arg = lookUpNamespaceArg(args, mw.ustring.lower(key))
if arg ~= nil then
return arg
end
end
return nil
end
-- Look up a page type specific to the title's namespace
local function getExplicitPageType(title)
if title.isTalkPage then
return cfg.talkDefault
else
return cfg.pagetypes[title.namespace]
end
end
-- Get a default page type that is not specific to the title's namespace
local function getDefaultPageType(args)
local other = lookUpNamespaceArg(args, cfg.other)
if type(other) == 'string' then
return other
else
return cfg.otherDefault
end
end
local function detectRedirects(title, args)
local redirect = lookUpNamespaceArg(args, cfg.redirect)
if redirect == false then
-- Don't detect redirects if they have been specifically disallowed.
return nil
end
-- Allow custom values for redirects.
if not title.isRedirect then
return nil
elseif type(redirect) == 'string' then
return redirect
else
return cfg.redirectDefault
end
end
local function capitalize(pageType)
local first = mw.ustring.sub(pageType, 1, 1)
local rest = mw.ustring.sub(pageType, 2)
return mw.ustring.upper(first) .. rest
end
local function pluralize(pageType)
if cfg.irregularPlurals[pageType] then
return cfg.irregularPlurals[pageType]
else
return pageType .. cfg.plural -- often 's'
end
end
local function parseContent(title, args, optionsList)
if title.namespace==828 and title.subpageText~='doc' -- don't detect modules
or not title.exists -- can't check unless page exists
then
return nil
end
local content = title:getContent()
if content == nil then
return nil
end
local templates -- lazily evaluated
for _, options in next, optionsList do
local list, parameter, default, articleOnly = unpack(options, 1, 4)
if not articleOnly or title.namespace==0 then -- only check for templates if we should...
local out = lookUpNamespaceArg(args, parameter)
if type(out) == "string" or (out ~= false and default) then -- ...and if we actually have anything to say about them
if not templates then
templates = {} -- do our delayed evaluation now that we are required to
content = require('Module:Wikitext Parsing').PrepareText(content) -- disregard templates which do not have any affect
for template in string.gmatch(content, "{{%s*([^|}]-)%s*[|}]") do
templates[#templates+1] = capitalize(template)
end
end
local wantedTemplates = mw.loadData('Module:Pagetype/' .. list)
local templateFound = false
for _, template in next, templates do
if wantedTemplates[template] then
templateFound = true
break
end
end
if templateFound then
if type(out)=='string' then
return out
elseif out ~= false and default then
return default
end
end
end
end
end
end
-- Find pages which do not exist
local function nonExistent(title, args)
local arg = lookUpNamespaceArg(args, cfg.ne)
if arg == false then
return nil
end
local exists = false
if title.exists then -- not an article if it does not exist
exists = true
elseif title.namespace==8 and mw.message.new(title.text):exists() then
exists = true
elseif title.namespace==6 and title.fileExists then
exists = true
end
if not exists then
if type(arg) == 'string' then
return arg
else
return cfg.naDefault
end
end
end
-- Get page types for mainspaces pages with an explicit class specified
local function getMainNamespaceClassPageType(title, args)
local class = args[1]
if type(class) == 'string' then -- Put in lower case so e.g. "na" and "NA" will both match
class = mw.ustring.lower(class)
end
local arg = lookUpNamespaceArg(args, cfg.na)
if arg == false then -- don't check for this class if it is specifically disallowed
return nil
end
if cfg.naAliases[class] then
if type(arg) == 'string' then
return arg
else
return cfg.naDefault
end
else
return nil
end
end
-- Get page type specified by an explicit namespace argument.
local function getNamespaceArgPageType(title, args)
local namespaceArg = getNamespaceArg(title, args)
if namespaceArg == true then
-- Namespace has been explicitly enabled, so return the default for
-- this namespace
return getExplicitPageType(title)
elseif namespaceArg == false then
-- Namespace has been explicitly disabled
return getDefaultPageType(args)
elseif namespaceArg then
-- This namespaces uses custom text
return namespaceArg
else
return nil
end
end
-- Get page type not specified or detected by other means
local function getOtherPageType(title, args)
-- Whether the title is in the set of default active namespaces which are looked up in cfg.pagetypes.
local isInDefaultActiveNamespace = false
local defaultNamespacesKey = args[cfg.defaultns]
if defaultNamespacesKey == cfg.defaultnsAll then
isInDefaultActiveNamespace = true
else
local defaultNamespaces
if defaultNamespacesKey == cfg.defaultnsExtended then
defaultNamespaces = cfg.extendedNamespaces
elseif defaultNamespacesKey == cfg.defaultnsNone then
defaultNamespaces = {}
else
defaultNamespaces = cfg.defaultNamespaces
end
isInDefaultActiveNamespace = defaultNamespaces[title.namespace]
end
if isInDefaultActiveNamespace then
return getExplicitPageType(title)
else
return getDefaultPageType(args)
end
end
function p._main(args)
local title
if args.page then
title = mw.title.new(args.page)
else
title = mw.title.getCurrentTitle()
end
if title and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then
title = title.subjectPageTitle
end
local pageType = detectRedirects(title, args)
or nonExistent(title, args)
or parseContent(title, args, {
{'softredirect', cfg.softRedirect, cfg.softRedirectDefault},
{'setindex', cfg.sia, cfg.siaDefault, true},
{'disambiguation', cfg.dab, cfg.dabDefault, true},
{'rfd', cfg.rfd, cfg.rfdDefault},
})
or (title.namespace == 0 and getMainNamespaceClassPageType(title, args))
or getNamespaceArgPageType(title, args)
or getOtherPageType(title, args)
if yesno(args.plural, false) then
pageType = pluralize(pageType)
end
if yesno(args.caps, false) then
pageType = capitalize(pageType)
end
return pageType
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame)
return p._main(args)
end
return p
nqu0kvn2uc9jqptetkmoluzmahcxzzp
Module:Pagetype/config
828
1142
9305
2026-04-25T00:17:56Z
Anomie
322
+ MOS and Event namespaces
9305
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Pagetype configuration data --
-- This page holds localisation and configuration data for Module:Pagetype. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
-- This table holds the default page types for each namespace. Keys to this
-- table should be integers that can be used as keys to mw.site.namespaces.
cfg.pagetypes = {
[0] = 'article', -- Main namespace
[2] = 'user page',
[4] = 'project page',
[6] = 'file',
[8] = 'interface page', -- MediaWiki namespace
[10] = 'template',
[12] = 'help page',
[14] = 'category',
[100] = 'portal',
[118] = 'draft',
[126] = 'MOS page',
[710] = 'Timed Text page',
[828] = 'module',
[1728] = 'event page',
[2300] = 'gadget',
[2302] = 'gadget definition',
[-1] = 'special page',
[-2] = 'file', -- Media namespace
}
-- This table holds the namespaces to be looked up from cfg.pagetypes by
-- default.
cfg.defaultNamespaces = {
[0] = true, -- main
[6] = true, -- file
[10] = true, -- template
[14] = true, -- category
[828] = true, -- module
}
-- This table holds the namespaces to be looked up from cfg.pagetypes if
-- cfg.defaultnsExtended is set.
cfg.extendedNamespaces = {
[0] = true, -- main
[2] = true, -- user
[4] = true, -- project
[6] = true, -- file
[8] = true, -- mediawiki
[10] = true, -- template
[12] = true, -- help
[14] = true, -- category
[100] = true, -- portal
[118] = true, -- draft
[828] = true, -- module
}
-- This table holds custom aliases for each namespace.
cfg.customNamespaceAliases = {
[0] = {'main'},
}
-- The parameter name to set which default namespace values to be looked up from
-- cfg.pagetypes.
cfg.defaultns = 'defaultns'
-- The value of cfg.defaultns to set all namespaces, including talk.
cfg.defaultnsAll = 'all'
-- The value of cfg.defaultns to set the namespaces listed in
-- cfg.extendedNamespaces
cfg.defaultnsExtended = 'extended'
-- The value of cfg.defaultns to set no default namespaces.
cfg.defaultnsNone = 'none'
-- The parameter name to use for talk pages.
cfg.talk = 'talk'
-- The default value for talk pages.
cfg.talkDefault = 'talk page'
-- The parameter name to use for disambiguation pages page.
cfg.dab = 'dab'
-- The parameter name to use for non-existent pages.
cfg.ne = 'nonexistent'
cfg.neDefault = 'page'
cfg.softRedirect = 'soft_redirect'
cfg.softRedirectDefault = 'redirect'
cfg.sia = 'sia'
cfg.siaDefault = 'article'
cfg.rfd = 'redirect'
cfg.rfdDefault = 'redirect'
-- This table holds the different possible aliases for disambiguation-class
-- pages. These should be lower-case.
cfg.dabAliases = {
['disambiguation'] = true,
['disambig'] = true,
['disamb'] = true,
['dab'] = true,
}
-- The default value for disambiguation pages.
cfg.dabDefault = 'page'
-- The parameter name to use for N/A-class page.
cfg.na = 'na'
-- This table holds the different possible aliases for N/A-class pages. These
-- should be lower-case.
cfg.naAliases = {
['na'] = true,
['n/a'] = true,
}
-- The default value for N/A-class pages.
cfg.naDefault = 'page'
-- The parameter name to use for redirects.
cfg.redirect = 'redirect'
-- The default value to use for redirects.
cfg.redirectDefault = 'redirect'
-- The parameter name for undefined namespaces.
cfg.other = 'other'
-- The value used if the module detects an undefined namespace.
cfg.otherDefault = 'page'
-- The usual suffix denoting a plural.
cfg.plural = 's'
-- This table holds plurals not formed by a simple suffix.
cfg.irregularPlurals = {
["category"] = "categories"
}
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line
dbot8rq8sjl2bypo7kiymiyo4gxz08i
9306
9305
2026-08-23T08:17:07Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype/config]]
9305
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Pagetype configuration data --
-- This page holds localisation and configuration data for Module:Pagetype. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
-- This table holds the default page types for each namespace. Keys to this
-- table should be integers that can be used as keys to mw.site.namespaces.
cfg.pagetypes = {
[0] = 'article', -- Main namespace
[2] = 'user page',
[4] = 'project page',
[6] = 'file',
[8] = 'interface page', -- MediaWiki namespace
[10] = 'template',
[12] = 'help page',
[14] = 'category',
[100] = 'portal',
[118] = 'draft',
[126] = 'MOS page',
[710] = 'Timed Text page',
[828] = 'module',
[1728] = 'event page',
[2300] = 'gadget',
[2302] = 'gadget definition',
[-1] = 'special page',
[-2] = 'file', -- Media namespace
}
-- This table holds the namespaces to be looked up from cfg.pagetypes by
-- default.
cfg.defaultNamespaces = {
[0] = true, -- main
[6] = true, -- file
[10] = true, -- template
[14] = true, -- category
[828] = true, -- module
}
-- This table holds the namespaces to be looked up from cfg.pagetypes if
-- cfg.defaultnsExtended is set.
cfg.extendedNamespaces = {
[0] = true, -- main
[2] = true, -- user
[4] = true, -- project
[6] = true, -- file
[8] = true, -- mediawiki
[10] = true, -- template
[12] = true, -- help
[14] = true, -- category
[100] = true, -- portal
[118] = true, -- draft
[828] = true, -- module
}
-- This table holds custom aliases for each namespace.
cfg.customNamespaceAliases = {
[0] = {'main'},
}
-- The parameter name to set which default namespace values to be looked up from
-- cfg.pagetypes.
cfg.defaultns = 'defaultns'
-- The value of cfg.defaultns to set all namespaces, including talk.
cfg.defaultnsAll = 'all'
-- The value of cfg.defaultns to set the namespaces listed in
-- cfg.extendedNamespaces
cfg.defaultnsExtended = 'extended'
-- The value of cfg.defaultns to set no default namespaces.
cfg.defaultnsNone = 'none'
-- The parameter name to use for talk pages.
cfg.talk = 'talk'
-- The default value for talk pages.
cfg.talkDefault = 'talk page'
-- The parameter name to use for disambiguation pages page.
cfg.dab = 'dab'
-- The parameter name to use for non-existent pages.
cfg.ne = 'nonexistent'
cfg.neDefault = 'page'
cfg.softRedirect = 'soft_redirect'
cfg.softRedirectDefault = 'redirect'
cfg.sia = 'sia'
cfg.siaDefault = 'article'
cfg.rfd = 'redirect'
cfg.rfdDefault = 'redirect'
-- This table holds the different possible aliases for disambiguation-class
-- pages. These should be lower-case.
cfg.dabAliases = {
['disambiguation'] = true,
['disambig'] = true,
['disamb'] = true,
['dab'] = true,
}
-- The default value for disambiguation pages.
cfg.dabDefault = 'page'
-- The parameter name to use for N/A-class page.
cfg.na = 'na'
-- This table holds the different possible aliases for N/A-class pages. These
-- should be lower-case.
cfg.naAliases = {
['na'] = true,
['n/a'] = true,
}
-- The default value for N/A-class pages.
cfg.naDefault = 'page'
-- The parameter name to use for redirects.
cfg.redirect = 'redirect'
-- The default value to use for redirects.
cfg.redirectDefault = 'redirect'
-- The parameter name for undefined namespaces.
cfg.other = 'other'
-- The value used if the module detects an undefined namespace.
cfg.otherDefault = 'page'
-- The usual suffix denoting a plural.
cfg.plural = 's'
-- This table holds plurals not formed by a simple suffix.
cfg.irregularPlurals = {
["category"] = "categories"
}
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line
dbot8rq8sjl2bypo7kiymiyo4gxz08i
Tempilet:Str number/trim
10
1143
9307
2024-01-16T16:33:34Z
Xaosflux
324
Changed protection settings for "[[Template:Str number/trim]]": [[WP:High-risk templates|High-risk template or module]] ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9307
wikitext
text/x-wiki
{{#invoke:String|match|s={{{1}}}|^%d*|ignore_errors=true}}<noinclude>
{{Documentation}}</noinclude>
6uvyf0id6y3oxzmtxrw3akau6ajubki
9308
9307
2026-08-23T08:17:10Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Str_number/trim]]
9307
wikitext
text/x-wiki
{{#invoke:String|match|s={{{1}}}|^%d*|ignore_errors=true}}<noinclude>
{{Documentation}}</noinclude>
6uvyf0id6y3oxzmtxrw3akau6ajubki
Tempilet:Tick
10
1144
9309
2023-06-27T05:39:15Z
Jonesey95
328
Fix [[Special:LintErrors|Linter]] errors. (bogus image options). strip trailing "px" off size parameter if present
9309
wikitext
text/x-wiki
[[{{ safesubst:<noinclude/>#switch:{{ safesubst:<noinclude/>lc:{{{color|{{{colour|}}}}}} }}
|green |grn |gn =File:Yes check.svg
|lightgreen |lgreen |lgrn |lgn =File:Light green check.svg
|red |rd |r =File:Red check.svg
|darkred |dkred |drd |dr =File:Check-188-25-49-red.svg
|pink |pnk |pk =File:Pink check.svg
|orange |or |o =File:Check.svg
|yellow |yel |y =File:Yellow check.svg
|black |blk |k =File:Black check.svg
|blue |blu |u =File:Check-blue.svg
|lightblue |lblue |lblu |lb =File:Cornflower blue check.svg
|cyan |cy |c =File:B-check.svg
|purple |pur |pu =File:Purple check.svg
|grey |gray |gry |gy =File:SemiTransBlack v.svg
|brown |brn |bn =File:Brown check.svg
<!--default--> |File:Yes check.svg
}}|{{ safesubst:<noinclude/>#if:{{{1|}}}|{{Str number/trim|{{{1}}}}}|20}}px|link=|alt={{#if:{{{alt|}}}|{{{alt}}}|check}}]]<span style="display:none">Y</span><!--template:tick--><noinclude>
{{documentation}}
</noinclude>
4y5n5eof1r959mn4xf1un5kmer0dn4j
9310
9309
2026-08-23T08:17:11Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Tick]]
9309
wikitext
text/x-wiki
[[{{ safesubst:<noinclude/>#switch:{{ safesubst:<noinclude/>lc:{{{color|{{{colour|}}}}}} }}
|green |grn |gn =File:Yes check.svg
|lightgreen |lgreen |lgrn |lgn =File:Light green check.svg
|red |rd |r =File:Red check.svg
|darkred |dkred |drd |dr =File:Check-188-25-49-red.svg
|pink |pnk |pk =File:Pink check.svg
|orange |or |o =File:Check.svg
|yellow |yel |y =File:Yellow check.svg
|black |blk |k =File:Black check.svg
|blue |blu |u =File:Check-blue.svg
|lightblue |lblue |lblu |lb =File:Cornflower blue check.svg
|cyan |cy |c =File:B-check.svg
|purple |pur |pu =File:Purple check.svg
|grey |gray |gry |gy =File:SemiTransBlack v.svg
|brown |brn |bn =File:Brown check.svg
<!--default--> |File:Yes check.svg
}}|{{ safesubst:<noinclude/>#if:{{{1|}}}|{{Str number/trim|{{{1}}}}}|20}}px|link=|alt={{#if:{{{alt|}}}|{{{alt}}}|check}}]]<span style="display:none">Y</span><!--template:tick--><noinclude>
{{documentation}}
</noinclude>
4y5n5eof1r959mn4xf1un5kmer0dn4j
Tempilet:Cross
10
1145
9315
2026-07-03T03:08:44Z
Paine Ellsworth
330
add [[WP:RCAT|rcat template]]s
9315
wikitext
text/x-wiki
#REDIRECT [[Template:Xmark]]
{{Redirect category shell|
{{R with Wikidata item}}
{{R from move}}
{{R from alternative name}}
{{R from template shortcut}}
}}
pzx1ocemkeqxqshel014w7dtfhp17vz
9316
9315
2026-08-23T08:17:16Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cross]]
9315
wikitext
text/x-wiki
#REDIRECT [[Template:Xmark]]
{{Redirect category shell|
{{R with Wikidata item}}
{{R from move}}
{{R from alternative name}}
{{R from template shortcut}}
}}
pzx1ocemkeqxqshel014w7dtfhp17vz
Tempilet:Xmark
10
1146
9317
2026-08-15T14:49:09Z
Paine Ellsworth
330
per edit request on talk page - include light brown
9317
wikitext
text/x-wiki
[[{{ {{{|safesubst:}}}#switch:{{ {{{|safesubst:}}}lc:{{{color|{{{colour|}}}}}} }}
|red |rd |r =File:X mark.svg
|darkred |dkred |drd |dr =File:Dark red x.svg
|orange |or |o =File:Orange x.svg
|yellow |yel |y =File:Dark yellow x.svg
|lightbrown |lbr |lb =File:Light brown x.svg
|black |blk |k =File:Black x.svg
|grey |gray |gry |gy =File:SemiTransBlack x.svg
<!--default--> |File:X mark.svg
}}|{{Str number/trim|{{ {{{|safesubst:}}}#if:{{{1|}}}|{{{1}}}|20}}}}px|link=|alt=X mark]]<span style="display:none">N</span><!--template:Xmark--><noinclude>
{{documentation}}
</noinclude>
qf2x6lw33ss2o1dll4p07cpm84wxnk9
9318
9317
2026-08-23T08:17:16Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Xmark]]
9317
wikitext
text/x-wiki
[[{{ {{{|safesubst:}}}#switch:{{ {{{|safesubst:}}}lc:{{{color|{{{colour|}}}}}} }}
|red |rd |r =File:X mark.svg
|darkred |dkred |drd |dr =File:Dark red x.svg
|orange |or |o =File:Orange x.svg
|yellow |yel |y =File:Dark yellow x.svg
|lightbrown |lbr |lb =File:Light brown x.svg
|black |blk |k =File:Black x.svg
|grey |gray |gry |gy =File:SemiTransBlack x.svg
<!--default--> |File:X mark.svg
}}|{{Str number/trim|{{ {{{|safesubst:}}}#if:{{{1|}}}|{{{1}}}|20}}}}px|link=|alt=X mark]]<span style="display:none">N</span><!--template:Xmark--><noinclude>
{{documentation}}
</noinclude>
qf2x6lw33ss2o1dll4p07cpm84wxnk9
Mercury
0
1148
9321
2026-07-31T15:30:21Z
AnandaBliss
337
Improved country descriptions.
9321
wikitext
text/x-wiki
{{wiktionary|Mercury|mercury}}
'''Mercury''' most commonly refers to:
* [[Mercury (planet)]], the closest planet to the Sun
* [[Mercury (element)]], a chemical element
* [[Mercury (mythology)]], a Roman deity
'''Mercury''' or '''The Mercury''' may also refer to:
{{tocright}}
== Companies ==
* [[Mercury (toy manufacturer)]], a brand of diecast toy cars manufactured in Italy
* [[Mercury Communications]], a British telecommunications firm set up in the 1980s
* [[Mercury Corporation]], an American aircraft manufacturer
* [[Mercury Cyclecar Company]], a defunct American car company
* [[Mercury Drug]], a Philippine pharmacy chain
* [[Mercury Energy]], an electricity generation and retail company in New Zealand
* [[Mercury Filmworks]], a Canadian independent animation studio
* [[Mercury General]], a multiple-line American insurance organization
* [[Mercury Interactive]], a software testing tools vendor
* [[Mercury Marine]], a manufacturer of marine engines, particularly outboard motors
* [[Mercury Technologies]], a financial technology company
* [[Mercury Truck & Tractor Company]], a defunct English manufacturer of industrial vehicles
* Shenzhen Mercury Communication Technology Co., Ltd., a Chinese market subsidiary of [[TP-Link]]
== Computing ==
* [[Mercury (programming language)]], a functional logic programming language
* [[Mercury (metadata search system)]], a data search system for earth science research
* [[Ferranti Mercury]], an early 1950s commercial computer
* [[Mercury Browser]], a freeware mobile browser
* [[Mercury Mail Transport System]], an email server
== Film and television==
* [[Mercury (film)|''Mercury'' (film)]], a 2018 Indian silent horror thriller by Karthik Subbaraj
* [[Mercury (TV series)|''Mercury'' (TV series)]], an Australian television series
* [[List of RWBY characters#Mercury Black|Mercury Black]], a character in the ''RWBY'' web series
* [[Sailor Mercury]], a character in the ''Sailor Moon'' manga and anime franchise
==Literature==
===Comics===
* [[Mercury (Marvel Comics)]], a character who can turn herself into a mercurial substance
* [[Makkari (character)]] or Mercury, an Eternal, a Marvel Comics race of superhumans
* Mercury, a member of the [[Metal Men]], a DC Comics team
* Mercury, a member of [[Cerebro's X-Men]]
* Mercury, an [[List of Amalgam Comics characters#JLX #1|Amalgam Comics character]]
===Magazines===
* [[Mercury (magazine)|''Mercury'' (magazine)]], an astronomy magazine
* ''[[The American Mercury]]'', originally a literary and later political magazine
===<span class="anchor" id="papers"></span>Newspapers===
<!--Only ones whose full title is "Mercury" or "The Mercury"-->
* [[The Mercury (Hobart)|''The Mercury'' (Hobart)]], Hobart, Tasmania, Australia
* [[The Mercury (South Africa)|''The Mercury'' (South Africa)]], Durban, South Africa
* [[The Mercury (Pennsylvania)|''The Mercury'' (Pennsylvania)]], Pottstown, Pennsylvania
* [[Newport Mercury|''Newport Mercury'']], a defunct newspaper, Newport, Rhode Island
* ''The Mercury'', former name of the now-defunct ''[[Reading Mercury]]'', Reading, Berkshire, England
* ''[[The Mercury News]]'', San Jose, California
* [[List of newspapers named Mercury|List of newspapers named ''Mercury'']], for newspapers with titles including the word "Mercury"
===Novels===
* [[Mercury (Bova novel)|''Mercury'' (Bova novel)]], a novel by Ben Bova
* [[Mercury (Livesey novel)|''Mercury'' (Livesey novel)]], a novel by Margot Livesey
* ''Mercury'', a novel by [[Anna Kavan]]
==Music==
* [[Freddie Mercury]]
* [[Mercury Nashville]], a record label
* [[Mercury Records]], a record label
* [[Mercury Prize]], an annual music prize awarded for the best album from the United Kingdom
* "[[Mercury, the Winged Messenger]]", a movement in Gustav Holst's ''The Planets''
===Albums===
* [[Mercury (American Music Club album)|''Mercury'' (American Music Club album)]] (1993)
* [[Mercury (Longview album)|''Mercury'' (Longview album)]] (2003)
* [[Mercury (Madder Mortem album)|''Mercury'' (Madder Mortem album)]] (1999)
* ''[[Mercury – Act 1]]'' (2021), by Imagine Dragons
* ''[[Mercury – Act 2|Mercury – Acts 1 & 2]]'' (2022), by Imagine Dragons
===Songs===
* [[Mercury (song)|"Mercury" (song)]], a 2008 song by Bloc Party
* "Mercury", a song by Counting Crows from ''[[Recovering the Satellites]]''
* "Mercury", a song by Kathleen Edwards from ''[[Failer]]''
* "Mercury", a song by Sufjan Stevens, Bryce Dessner, Nico Muhly and James McAlister from ''[[Planetarium (album)|Planetarium]]''
* "Mercury", a song by Steve Lacy from ''[[Gemini Rights]]''
==Military==
* [[Operation Mercury]], codename for the German invasion of Crete during World War II
* [[Boeing E-6 Mercury]], an American aircraft used as an airborne command post and communications relay
* [[Miles Mercury]], a British aircraft designed during the Second World War
* {{HMS|Mercury}}, various vessels or shore establishments of that name
* {{USS|Mercury}}, seven vessels of that name
* {{ship|Russian brig|Mercury}}, an 1820 warship
* [[Mercury (pigeon)]], honored for bravery during World War II
==Places==
* [[Mercury, Savoie]], a commune in southeastern France
* [[Mercury Bay]], New Zealand
* Mercury, a [[List of places in Alabama: I–M#M|place in Alabama]]
* [[Mercury, Nevada]], a closed city within the Nevada Test Site
* [[Mercury, Texas]]
== Plants ==
* [[Mercury (plant)]], members of the plant genus ''Mercurialis''
* [[Annual mercury]] (''Mercurialis annua''), a species of flowering plant
* [[English Mercury|English mercury]], or mercury goosefoot (''Blitum bonus-henricus''), a species of goosefoot
== Radio ==
* [[Mercury FM]], a radio station in Surrey, United Kingdom
* [[Mercury 96.6]] or Heart Hertfordshire, a radio station in Hertfordshire, United Kingdom
==Sports==
* [[Edmonton Mercurys]], a Canadian 1940s and 1950s intermediate ice hockey team
* [[Fujita Soccer Club Mercury]], a Japanese women's football team active from 1989 to 1999
* [[Memphis Mercury]], American women's soccer team
* [[Phoenix Mercury]], a Women's National Basketball Association team from Arizona
* [[Toledo Mercurys]], a defunct International Hockey League franchise from Ohio
==Theatres==
* [[Mercury Cinema]], a theatre in Adelaide, Australia
* [[Mercury Theatre (disambiguation)]], a list of Mercury theatres
==Vehicles==
===Air===
* [[Blackburn Mercury]], a British aircraft from 1911
* [[Bristol Mercury]], a nine-cylinder aircraft engine
===Land===
* [[Mercury (automobile)]], brand of automobiles produced by the Ford Motor Company from 1938 to 2011
:*[[List of Mercury vehicles]]
* [[Mercury (cyclecar)]], an American cyclecar from 1914
* [[Mercury (train)|''Mercury'' (train)]], a family of New York Central streamliner passenger trains (1936–1958)
===Sea===
* {{ship||Mercury|ship}}, several ships of that name
* [[Cape Cod Mercury 15]], an American sailboat design
* [[Mercury 18]], an American sailboat design
===Space===
* [[Project Mercury]], a United States human spaceflight program, 1958–1963
* [[Mercury (satellite)]], a series of American spy satellites
==Locations==
* [[Mercury Boulevard]] in Virginia, United States
* [[The Mercury Mall]], a shopping centre in Romford, England
== Other uses ==
* ''[[Archer Maclean's Mercury]]'', a 2005 PlayStation Portable video game
* [[Mercury (cipher machine)]], a 1950s British cipher machine
* [[Shuttle America]]'s callsign
* [[Mercury (name)]], including a list of people with that surname or given name
==See also==
{{Commons|mercury}}
* {{look from}}
* ''[[The American Mercury]]'', an American magazine published from 1924 to 1981
* [[Mercure (disambiguation)]]
* [[Mercuri]], a surname and list of people with the surname
* [[Mercurius (disambiguation)]]
* [[Mercury 1 (disambiguation)]]
* [[Mercury 2 (disambiguation)]]
* [[Mercury 3 (disambiguation)]]
* [[Mercury 4 (disambiguation)]]
* [[Mercury 5 (disambiguation)]]
* [[Mercury 6 (disambiguation)]]
* [[Mercury 7 (disambiguation)]]
* [[Mercury 8 (disambiguation)]]
* [[Mercury City (disambiguation)]]
* [[Mercury FM (disambiguation)]]
* [[Mercury House (disambiguation)]]
* [[Mercury mission (disambiguation)]]
* [[Mercury program (disambiguation)]]
* [[Mercury project (disambiguation)]]
* {{in title|Mercury}}
{{disambiguation|geo}}
lth47e19l81wilt0fmmgontqkpb4mme
9322
9321
2026-08-23T08:17:35Z
RAPTOR7762
18
1 revision imported from [[:en:Mercury]]
9321
wikitext
text/x-wiki
{{wiktionary|Mercury|mercury}}
'''Mercury''' most commonly refers to:
* [[Mercury (planet)]], the closest planet to the Sun
* [[Mercury (element)]], a chemical element
* [[Mercury (mythology)]], a Roman deity
'''Mercury''' or '''The Mercury''' may also refer to:
{{tocright}}
== Companies ==
* [[Mercury (toy manufacturer)]], a brand of diecast toy cars manufactured in Italy
* [[Mercury Communications]], a British telecommunications firm set up in the 1980s
* [[Mercury Corporation]], an American aircraft manufacturer
* [[Mercury Cyclecar Company]], a defunct American car company
* [[Mercury Drug]], a Philippine pharmacy chain
* [[Mercury Energy]], an electricity generation and retail company in New Zealand
* [[Mercury Filmworks]], a Canadian independent animation studio
* [[Mercury General]], a multiple-line American insurance organization
* [[Mercury Interactive]], a software testing tools vendor
* [[Mercury Marine]], a manufacturer of marine engines, particularly outboard motors
* [[Mercury Technologies]], a financial technology company
* [[Mercury Truck & Tractor Company]], a defunct English manufacturer of industrial vehicles
* Shenzhen Mercury Communication Technology Co., Ltd., a Chinese market subsidiary of [[TP-Link]]
== Computing ==
* [[Mercury (programming language)]], a functional logic programming language
* [[Mercury (metadata search system)]], a data search system for earth science research
* [[Ferranti Mercury]], an early 1950s commercial computer
* [[Mercury Browser]], a freeware mobile browser
* [[Mercury Mail Transport System]], an email server
== Film and television==
* [[Mercury (film)|''Mercury'' (film)]], a 2018 Indian silent horror thriller by Karthik Subbaraj
* [[Mercury (TV series)|''Mercury'' (TV series)]], an Australian television series
* [[List of RWBY characters#Mercury Black|Mercury Black]], a character in the ''RWBY'' web series
* [[Sailor Mercury]], a character in the ''Sailor Moon'' manga and anime franchise
==Literature==
===Comics===
* [[Mercury (Marvel Comics)]], a character who can turn herself into a mercurial substance
* [[Makkari (character)]] or Mercury, an Eternal, a Marvel Comics race of superhumans
* Mercury, a member of the [[Metal Men]], a DC Comics team
* Mercury, a member of [[Cerebro's X-Men]]
* Mercury, an [[List of Amalgam Comics characters#JLX #1|Amalgam Comics character]]
===Magazines===
* [[Mercury (magazine)|''Mercury'' (magazine)]], an astronomy magazine
* ''[[The American Mercury]]'', originally a literary and later political magazine
===<span class="anchor" id="papers"></span>Newspapers===
<!--Only ones whose full title is "Mercury" or "The Mercury"-->
* [[The Mercury (Hobart)|''The Mercury'' (Hobart)]], Hobart, Tasmania, Australia
* [[The Mercury (South Africa)|''The Mercury'' (South Africa)]], Durban, South Africa
* [[The Mercury (Pennsylvania)|''The Mercury'' (Pennsylvania)]], Pottstown, Pennsylvania
* [[Newport Mercury|''Newport Mercury'']], a defunct newspaper, Newport, Rhode Island
* ''The Mercury'', former name of the now-defunct ''[[Reading Mercury]]'', Reading, Berkshire, England
* ''[[The Mercury News]]'', San Jose, California
* [[List of newspapers named Mercury|List of newspapers named ''Mercury'']], for newspapers with titles including the word "Mercury"
===Novels===
* [[Mercury (Bova novel)|''Mercury'' (Bova novel)]], a novel by Ben Bova
* [[Mercury (Livesey novel)|''Mercury'' (Livesey novel)]], a novel by Margot Livesey
* ''Mercury'', a novel by [[Anna Kavan]]
==Music==
* [[Freddie Mercury]]
* [[Mercury Nashville]], a record label
* [[Mercury Records]], a record label
* [[Mercury Prize]], an annual music prize awarded for the best album from the United Kingdom
* "[[Mercury, the Winged Messenger]]", a movement in Gustav Holst's ''The Planets''
===Albums===
* [[Mercury (American Music Club album)|''Mercury'' (American Music Club album)]] (1993)
* [[Mercury (Longview album)|''Mercury'' (Longview album)]] (2003)
* [[Mercury (Madder Mortem album)|''Mercury'' (Madder Mortem album)]] (1999)
* ''[[Mercury – Act 1]]'' (2021), by Imagine Dragons
* ''[[Mercury – Act 2|Mercury – Acts 1 & 2]]'' (2022), by Imagine Dragons
===Songs===
* [[Mercury (song)|"Mercury" (song)]], a 2008 song by Bloc Party
* "Mercury", a song by Counting Crows from ''[[Recovering the Satellites]]''
* "Mercury", a song by Kathleen Edwards from ''[[Failer]]''
* "Mercury", a song by Sufjan Stevens, Bryce Dessner, Nico Muhly and James McAlister from ''[[Planetarium (album)|Planetarium]]''
* "Mercury", a song by Steve Lacy from ''[[Gemini Rights]]''
==Military==
* [[Operation Mercury]], codename for the German invasion of Crete during World War II
* [[Boeing E-6 Mercury]], an American aircraft used as an airborne command post and communications relay
* [[Miles Mercury]], a British aircraft designed during the Second World War
* {{HMS|Mercury}}, various vessels or shore establishments of that name
* {{USS|Mercury}}, seven vessels of that name
* {{ship|Russian brig|Mercury}}, an 1820 warship
* [[Mercury (pigeon)]], honored for bravery during World War II
==Places==
* [[Mercury, Savoie]], a commune in southeastern France
* [[Mercury Bay]], New Zealand
* Mercury, a [[List of places in Alabama: I–M#M|place in Alabama]]
* [[Mercury, Nevada]], a closed city within the Nevada Test Site
* [[Mercury, Texas]]
== Plants ==
* [[Mercury (plant)]], members of the plant genus ''Mercurialis''
* [[Annual mercury]] (''Mercurialis annua''), a species of flowering plant
* [[English Mercury|English mercury]], or mercury goosefoot (''Blitum bonus-henricus''), a species of goosefoot
== Radio ==
* [[Mercury FM]], a radio station in Surrey, United Kingdom
* [[Mercury 96.6]] or Heart Hertfordshire, a radio station in Hertfordshire, United Kingdom
==Sports==
* [[Edmonton Mercurys]], a Canadian 1940s and 1950s intermediate ice hockey team
* [[Fujita Soccer Club Mercury]], a Japanese women's football team active from 1989 to 1999
* [[Memphis Mercury]], American women's soccer team
* [[Phoenix Mercury]], a Women's National Basketball Association team from Arizona
* [[Toledo Mercurys]], a defunct International Hockey League franchise from Ohio
==Theatres==
* [[Mercury Cinema]], a theatre in Adelaide, Australia
* [[Mercury Theatre (disambiguation)]], a list of Mercury theatres
==Vehicles==
===Air===
* [[Blackburn Mercury]], a British aircraft from 1911
* [[Bristol Mercury]], a nine-cylinder aircraft engine
===Land===
* [[Mercury (automobile)]], brand of automobiles produced by the Ford Motor Company from 1938 to 2011
:*[[List of Mercury vehicles]]
* [[Mercury (cyclecar)]], an American cyclecar from 1914
* [[Mercury (train)|''Mercury'' (train)]], a family of New York Central streamliner passenger trains (1936–1958)
===Sea===
* {{ship||Mercury|ship}}, several ships of that name
* [[Cape Cod Mercury 15]], an American sailboat design
* [[Mercury 18]], an American sailboat design
===Space===
* [[Project Mercury]], a United States human spaceflight program, 1958–1963
* [[Mercury (satellite)]], a series of American spy satellites
==Locations==
* [[Mercury Boulevard]] in Virginia, United States
* [[The Mercury Mall]], a shopping centre in Romford, England
== Other uses ==
* ''[[Archer Maclean's Mercury]]'', a 2005 PlayStation Portable video game
* [[Mercury (cipher machine)]], a 1950s British cipher machine
* [[Shuttle America]]'s callsign
* [[Mercury (name)]], including a list of people with that surname or given name
==See also==
{{Commons|mercury}}
* {{look from}}
* ''[[The American Mercury]]'', an American magazine published from 1924 to 1981
* [[Mercure (disambiguation)]]
* [[Mercuri]], a surname and list of people with the surname
* [[Mercurius (disambiguation)]]
* [[Mercury 1 (disambiguation)]]
* [[Mercury 2 (disambiguation)]]
* [[Mercury 3 (disambiguation)]]
* [[Mercury 4 (disambiguation)]]
* [[Mercury 5 (disambiguation)]]
* [[Mercury 6 (disambiguation)]]
* [[Mercury 7 (disambiguation)]]
* [[Mercury 8 (disambiguation)]]
* [[Mercury City (disambiguation)]]
* [[Mercury FM (disambiguation)]]
* [[Mercury House (disambiguation)]]
* [[Mercury mission (disambiguation)]]
* [[Mercury program (disambiguation)]]
* [[Mercury project (disambiguation)]]
* {{in title|Mercury}}
{{disambiguation|geo}}
lth47e19l81wilt0fmmgontqkpb4mme
UK
0
1149
9323
2026-05-05T17:46:07Z
Lijil
338
Reverted edits by [[Special:Contribs/~2026-27308-47|~2026-27308-47]] ([[User talk:~2026-27308-47|talk]]): vandalism ([[:en:WP:WikiShield|WS]])
9323
wikitext
text/x-wiki
#REDIRECT [[United Kingdom]]
{{Redirect category shell|1=
{{R from initialism}}
{{R mentioned in a hatnote}}
{{R printworthy}}
}}
0idoh74ren3deto9c1iaypnb7r104rv
9324
9323
2026-08-23T08:17:36Z
RAPTOR7762
18
1 revision imported from [[:en:UK]]
9323
wikitext
text/x-wiki
#REDIRECT [[United Kingdom]]
{{Redirect category shell|1=
{{R from initialism}}
{{R mentioned in a hatnote}}
{{R printworthy}}
}}
0idoh74ren3deto9c1iaypnb7r104rv
Mossa:United Kingdom
1
1150
9325
2026-08-22T12:17:12Z
Lowercase sigmabot III
339
Archiving 2 discussion(s) to [[Talk:United Kingdom/Archive 40]]) (bot
9325
wikitext
text/x-wiki
{{Skip to talk}}
{{Talk header}}
{{FAQ|collapsed=no}}
{{British English|date=September 2010}}
{{Article history
|action1=PR
|action1date=06:34, 3 May 2006
|action1link=Wikipedia:Peer review/United Kingdom/archive1
|action1result=reviewed
|action1oldid=51316003
|action2=GAN
|action2date=22:20, 22 July 2006
|action2link=Talk:United Kingdom/Archive 6#Good Article
|action2result=listed
|action2oldid=65278328
|action3=FAC
|action3date=15:46, 30 September 2006
|action3link=Wikipedia:Featured article candidates/United Kingdom/archive1
|action3result=not promoted
|action3oldid=78670594
|action4=FAC
|action4date=00:11, 11 February 2007
|action4link=Wikipedia:Featured article candidates/United Kingdom/archive2
|action4result=not promoted
|action4oldid=107189748
|action5=GAR
|action5link=Talk:United Kingdom/GA1
|action5date=19:51, 3 October 2008 (UTC)
|action5result=delisted
|action5oldid=242810269
|action6=GAN
|action6link=Talk:United Kingdom/GA2
|action6date=22 January 2010
|action6result=not listed
|action6oldid=339258206
|action7=GAN
|action7link=Talk:United Kingdom/GA3
|action7date=6 March 2015
|action7result=not listed
|action7oldid=650163344
|action8=GAN
|action8link=Talk:United Kingdom/GA4
|action8date=18:52, 24 September 2018 (UTC)
|action8result=not listed
|action8oldid=861034594
|topic=geography
|currentstatus=DGA
}}
{{WikiProject banner shell|class=B|collapsed=yes|vital=yes|blp=No|1=
{{WikiProject Countries}}
{{WikiProject Europe|importance=Top}}
{{WikiProject Guild of Copy Editors||user=Chaosdruid|date=17 May 2011}}
{{WikiProject Politics of the United Kingdom| importance = Top}}
{{WikiProject UK geography|importance=Top}}
{{WikiProject United Kingdom|importance=Top}}
}}
{{Press|date=August 17, 2009 |url= http://www.telegraph.co.uk/technology/wikipedia/6043534/The-50-most-viewed-Wikipedia-articles-in-2009-and-2008.html |title=The 50 most-viewed Wikipedia articles in 2009 and 2008 |org=[[The Daily Telegraph]] }}
{{Other banners|collapsed=yes|
{{Annual report|[[Wikipedia:2007 Top 50 Report|2007]], [[Wikipedia:2008 Top 50 Report|2008]], [[Wikipedia:2009 Top 50 Report|2009]], [[Wikipedia:2010 Top 50 Report|2010]], [[Wikipedia:2011 Top 50 Report|2011]], [[Wikipedia:2012 Top 50 Report|2012]], [[Wikipedia:2013 Top 50 Report|2013]], [[Wikipedia:2014 Top 50 Report|2014]], [[Wikipedia:Top 25 Report/2016|2016]], [[Wikipedia:2021 Top 50 Report|2021]], and [[Wikipedia:2022 Top 50 Report|2022]]}}
}}
{{section sizes}}
{{Talk:United Kingdom/archivebox}}
{{User:MiszaBot/config
|archiveheader = {{Automatic archive navigator}}
|maxarchivesize = 150K
|counter = 40
|algo = old(60d)
|archive = Talk:United Kingdom/Archive %(counter)d
}}{{User:HBC Archive Indexerbot/OptIn
|target=Talk:United Kingdom/Archive index
|mask1=Talk:United Kingdom/Archive <#>
|mask2=Talk:United_Kingdom/Country, Kingdom or State Archive <#>
|mask3=Talk:United_Kingdom/Terminology archive<#>
|mask4=Talk:United_Kingdom/Subdivision name archive<#>
|leading_zeros=0
|indexhere=yes}}
== Extended-confirmed-protected edit request on 6 July 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Change this line:
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the creation of the [[National Health Service]] (NHS) in 1949 is the primary healthcare provider in the United Kingdom.
To this:
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the establishment of the [[National Health Service]] (NHS), which began operating in 1948<ref>{{cite web |title=The foundation of the NHS |url=https://www.nationalarchives.gov.uk/explore-the-collection/stories/the-foundation-of-the-nhs/ |publisher=The National Archives |access-date=6 July 2026}}</ref> as the primary healthcare provider.
Reason:
Grammar fix, the current sentence is malformed ("...in 1949 is the primary healthcare provider..."). Year correction 1949→1948, sourced to The National Archives: the NHS began operating on 5 July 1948 (the "appointed day"). Wording changed from "creation of the NHS in 1949" to "establishment of the NHS, which began operating in 1948" because the NHS was created by separate acts across the UK (England and Wales: National Health Service Act 1946; Scotland: National Health Service (Scotland) Act 1947; Northern Ireland: Health Services Act (Northern Ireland) 1948) but launched UK-wide in 1948, so "establishment" plus the 1948 operating date avoids tying creation to a single year. Also removed the redundant second mention of "United Kingdom" at the end of the sentence. [[User:Dannyjamescarter|Dannyjamescarter]] ([[User talk:Dannyjamescarter|talk]]) 15:59, 6 July 2026 (UTC)
:{{done}}<!-- Template:EEp --> [[wp:solidarity|In solidarity]], [[User:Brynn Who Likes Editing|<span style="color: #04A">Brynn Who Likes Editing</span>]] <span style="color: #A59">'''|'''</span> [[User talk:Brynn Who Likes Editing|<span style="color:#E07">talk ''w''/ me!</span>]] 10:18, 19 August 2026 (UTC)
[[User:Lam312321321|Quack!]] [[User:Mutt Lunker|Mutt Lunker]] ([[User talk:Mutt Lunker|talk]]) 16:20, 6 July 2026 (UTC)
:Hi Mutt Lunker, I understand that the "Quack!" implies I'm a returning blocked user. I'm not. This is my only account, I have no connection to any blocked or banned editor, and I've built an ordinary editing history over my time here. I'd ask that the request be judged on its substance rather than on an assumption about who I am: it's a sourced correction (the NHS began operating on 5 July 1948, per The National Archives) and a fix to a grammatically broken sentence. If anyone genuinely believes otherwise about the account, the formal process exists for that. I've said my piece here and won't belabour it further. [[User:Dannyjamescarter|Dannyjamescarter]] ([[User talk:Dannyjamescarter|talk]]) 16:50, 6 July 2026 (UTC)
:[[User:Dannyjamescarter|Dannyjamescarter]] is neither listed in the confirmed sock puppets nor the suspected sock puppets of the ''Quack!'' account you linked to. Please do not create insinuations that an account is a sock puppet without evidence, as this can have a chilling effect. [[wp:solidarity|In solidarity]], [[User:Brynn Who Likes Editing|<span style="color: #04A">Brynn Who Likes Editing</span>]] <span style="color: #A59">'''|'''</span> [[User talk:Brynn Who Likes Editing|<span style="color:#E07">talk ''w''/ me!</span>]] 10:03, 19 August 2026 (UTC)
{{talk reflist}}
== costal =coastal ==
Article locked so cannot change.[[Special:Contributions/~2026-32542-29|~2026-32542-29]] ([[User talk:~2026-32542-29|talk]]) 03:35, 8 July 2026 (UTC)
:{{fixed}} I verified that the reference it's in misspelled the name of the publisher. –[[User:LaundryPizza03|<b style="color:#77b">Laundry</b><b style="color:#fb0">Pizza</b><b style="color:#b00">03</b>]] ([[User talk:LaundryPizza03|<span style="color:#0d0">d</span>]][[Special:Contribs/LaundryPizza03|<span style="color:#0bf">c̄</span>]]) 03:51, 8 July 2026 (UTC)
== Extended-confirmed-protected edit request on 12 July 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Instead of "country", The United Kingdom should be called a "sovereign state" because it is a political entity made up of multiple countries and represents multiple countries in the international stage. [[User:TheCountriesoftheWorld|TheCountriesoftheWorld]] ([[User talk:TheCountriesoftheWorld|talk]]) 02:14, 12 July 2026 (UTC)
:{{not done}} pls see [[Talk:United_Kingdom/Archive_30#sovereign_state,_not_country| a discussion that links to many other discussions]].<span style="display:inline-flex;rotate:-15deg;color:darkblue">'''[[User:Moxy|Moxy]]'''</span><span style="display:inline-flex;rotate:15deg;color:darkblue">[[User talk:Moxy|🍁]]</span> 02:31, 12 July 2026 (UTC)
== Government seat ==
{{ping|Bazza 7}} Usually when the seat of government is different to the capital city, infoboxes show that (e.g. see [[Kingdom of the Netherlands]]). I considered adding a "government seat" field but thought that would be [[WP:UNDUE]] emphasis for a very recent change when most government work is still done from London, which is why I added a footnote instead. [[User:Chessrat|<b style="color: #c90; font-family: comic sans ms">Chessrat</b>]] <sup>([[User talk:Chessrat|<span style="color:green">talk</span>]], [[Special:Contribs/Chessrat|<span style="color:#f78">contributions</span>]])</sup> 11:19, 24 July 2026 (UTC)
:I'm not sure that's a solid analogy. The Netherlands presents an unusual problem, in that while the ordinarily meaning of "capital city" is "place from which an entity is governed", Amsterdam, the ''official'' capital, outright fails to be the capital in the ordinary sense of the term. It seems to me that the situation with Manchester is better compared to the United States, where (a) there's an official presidential retreat in Camp David, Maryland, where many presidents have held official meetings, (b) the current president treats his estate in Palm Beach, Florida, as a secondary White House, and (c) the Department of Defense is in Arlington, Virginia. But the [[United States]] article makes no mention of either Camp David or Palm Beach, and mentions Arlington only in the caption under a photo of the Pentagon. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 11:41, 24 July 2026 (UTC)
::That's reasonable enough. Thanks for your thoughts. [[User:Chessrat|<b style="color: #c90; font-family: comic sans ms">Chessrat</b>]] <sup>([[User talk:Chessrat|<span style="color:green">talk</span>]], [[Special:Contribs/Chessrat|<span style="color:#f78">contributions</span>]])</sup> 12:54, 24 July 2026 (UTC)
:@[[User:Chessrat|Chessrat]]: Thanks for starting this discussion.
:As always, whatever is stated requires sourcing. So [https://www.bbc.co.uk/news/world-europe-18023389] (last updated 2024) plainly states the capital of the UK is London. So does [https://openfactbook.org/countries/united-kingdom/]. So that's what should be in the article (of which [[MOS:INFOBOXPURPOSE|the infobox is a summary]]). In the surprising absence of any referenced statement about the capital, I've added one in {{section link|United_Kingdom|Demographics}} (which location might seem odd but I couldn't figure anywhere else to put it). If someone finds reliable sources which state that London is usually the capital but Manchester takes over sometimes, then that can be added at the appropriate place.
:If the government of the day chooses to [https://www.bbc.co.uk/news/articles/ckgvyr76973o work elsewhere on Fridays], then that might be appropriate for the {{section link|United Kingdom|Government and politics}}, although I note that there is nothing about location in that section, which is probably as it should be; there is, though, at {{Section link|Government_of_the_United_Kingdom|Location}} so that may be the best place to add more sourced information to.
:I'll also note that I'm not a fan of placing facts which should be in article text inside notes: they're fine for clarifying a word or phrase, but not for carrying information. The MOS [[MOS:NOTES|obliquely implies that this might be an allowed use of notes]], but my own opinion is that if it's worth saying, then say it in the text of the appropriate article. [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 12:22, 24 July 2026 (UTC)
== Britain is not an accurate name ==
Might it be worth noting in the opening paragraph that although it is commonly referred to as Britain this is not the correct name. [[User:Dwnsdp|Dwnsdp]] ([[User talk:Dwnsdp|talk]]) 09:45, 14 August 2026 (UTC)
:What, for you, distinguishes between whether a commonly used name is correct or incorrect? Can you give separate examples of commonly used alternate names for things that are correct and that aren't correct? What I'm getting at here is that correctness doesn't apply and we aren't here to scold people for referring to it by a name commonly used to refer to it. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 11:30, 14 August 2026 (UTC)
::@[[User:Largoplazo|Largoplazo]] Referring to the UK as Britain is incorrect not because it is ''technically'' incorrect - as I agree we should not scold people for - but because as a name it directly excluded one of four kingdoms. A lot of people call the UK "England" due to a misunderstanding, which is not mentioned as an alternative name as it is not correct. What separates that common name from Britain. [[User:Dwnsdp|Dwnsdp]] ([[User talk:Dwnsdp|talk]]) 11:36, 14 August 2026 (UTC)
:::Not everyone shares the view that Britain strictly refers to just [[Great Britain]]. [[User:Chipmunkdavis|CMD]] ([[User talk:Chipmunkdavis|talk]]) 12:09, 14 August 2026 (UTC)
:::@[[User:Dwnsdp|Dwnsdp]]: Who says it's "incorrect"? [https://hansard.parliament.uk/lords/1964-07-09/debates/daef6f24-989f-44ee-8f0e-62940f5d2cbd/BritainSOfficialTitle This statement], made some time ago, considered "Britain" to be acceptable. The term might be ambiguous, or casual, or not official, but it's not incorrect. Perhaps you are confusing "correct" with "official"? In which case, it's not the "official name" of the United Kingdom, but neither is [https://www.gov.uk/government/publications/country-names/country-names-the-permanent-committee-on-geographical-names-for-british-official-use#u "United Kingdom"].
:::The first sentence of the article includes a note explaining the commonly-used "Britain". The "Etymology and terminology" and terminology in the first section of the article goes to great length to explain the country's various names. [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 12:13, 14 August 2026 (UTC)
::::It is ambiguous, yes. It has two common definitions: 1) the island containing three of the four nations (England, Scotland and Wales) of the United Kingdom (aka Great Britain), 2) the United Kingdom as a whole (England, Northern Ireland, Scotland and Wales). It is similar to the America vs. United States question. This could be explained in the article.
::::Given its ambiguity and potential to confuse though, it's probably more encyclopaedic to use "United Kingdom" or "UK" in general usage in other articles. -- [[User:DeFacto|<span style="color:#3366CC;">DeFacto</span>]] ([[User Talk:DeFacto|talk]]). 13:10, 14 August 2026 (UTC)
:::::@[[User:DeFacto|DeFacto]]: The article already contains a good summary of naming, with links to two in-depth articles for those who need more.
:::::I wasn't suggesting "Britain" should be used at all, for the reasons you state. On the contrary, things would be clearer if the MOS forbad it in Wikipedia articles other than when the word is the topic of discussion (as at the start of this article) or it's being quoted. (The [https://www.bbc.co.uk/newsstyleguide/all/#b BBC has a half-hearted go], the UK government [https://guidance.publishing.service.gov.uk/writing-to-gov-uk-standards/style-guides/a-to-z-style-guide/#britain slightly more].)
:::::I can't see that happening, though. But it's wrong to label others using it as "incorrect". [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 15:42, 14 August 2026 (UTC)
::::::@[[User:Bazza 7|Bazza 7]], fair enough, and yep, I totally agree with your second sentence. -- [[User:DeFacto|<span style="color:#3366CC;">DeFacto</span>]] ([[User Talk:DeFacto|talk]]). 16:51, 14 August 2026 (UTC)
:::"City of London" excludes most of the city of London. Many online articles can be found with phrases along the lines of "10 Downing Street issued a statement" or "10 Downing Street issued an apology", but we understand that it's neither the address nor the building designated by it that did the issuing, it was human beings inside of it. The word "decimate" originally referred to the killing of one in ten of the enemy but now it's used to connote a much greater level of devastation. South Africa excludes most of the south of Africa. The standard Turkish name for Morocco is "Fas", though more specifically it refers to the city of Fez. That the use of a name doesn't adhere strictly to its origin or its ''literal'' meaning doesn't mean it's incorrect. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 12:46, 14 August 2026 (UTC)
== Extended-confirmed-protected edit request on 15 August 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Add [[Speaker of the House of Commons (United Kingdom)]], with the incumbent [[Lindsay Hoyle]] to the infobox under the monarch and prime minister. [[Special:Contributions/~2026-44665-10|~2026-44665-10]] ([[User talk:~2026-44665-10|talk]]) 12:58, 15 August 2026 (UTC)
:[[File:X mark.svg|20px|link=|alt=]] '''Not done for now:''' please establish a [[Wikipedia:Consensus|consensus]] for this alteration '''[[Wikipedia:Edit requests#Planning a request|before]]''' posting an edit request.<!-- Template:EEp --> We don't typically list the speaker on this article. — '''[[User:Czello|<i style="color:#8000FF">Czello</i>]]''' <sup>''([[User talk:Czello|<i style="color:#8000FF">music</i>]])''</sup> 13:14, 15 August 2026 (UTC)
hapgl7eeth9yhjzn1qmnyfobhn7n5cj
9326
9325
2026-08-23T08:17:36Z
RAPTOR7762
18
1 revision imported from [[:en:Talk:United_Kingdom]]
9325
wikitext
text/x-wiki
{{Skip to talk}}
{{Talk header}}
{{FAQ|collapsed=no}}
{{British English|date=September 2010}}
{{Article history
|action1=PR
|action1date=06:34, 3 May 2006
|action1link=Wikipedia:Peer review/United Kingdom/archive1
|action1result=reviewed
|action1oldid=51316003
|action2=GAN
|action2date=22:20, 22 July 2006
|action2link=Talk:United Kingdom/Archive 6#Good Article
|action2result=listed
|action2oldid=65278328
|action3=FAC
|action3date=15:46, 30 September 2006
|action3link=Wikipedia:Featured article candidates/United Kingdom/archive1
|action3result=not promoted
|action3oldid=78670594
|action4=FAC
|action4date=00:11, 11 February 2007
|action4link=Wikipedia:Featured article candidates/United Kingdom/archive2
|action4result=not promoted
|action4oldid=107189748
|action5=GAR
|action5link=Talk:United Kingdom/GA1
|action5date=19:51, 3 October 2008 (UTC)
|action5result=delisted
|action5oldid=242810269
|action6=GAN
|action6link=Talk:United Kingdom/GA2
|action6date=22 January 2010
|action6result=not listed
|action6oldid=339258206
|action7=GAN
|action7link=Talk:United Kingdom/GA3
|action7date=6 March 2015
|action7result=not listed
|action7oldid=650163344
|action8=GAN
|action8link=Talk:United Kingdom/GA4
|action8date=18:52, 24 September 2018 (UTC)
|action8result=not listed
|action8oldid=861034594
|topic=geography
|currentstatus=DGA
}}
{{WikiProject banner shell|class=B|collapsed=yes|vital=yes|blp=No|1=
{{WikiProject Countries}}
{{WikiProject Europe|importance=Top}}
{{WikiProject Guild of Copy Editors||user=Chaosdruid|date=17 May 2011}}
{{WikiProject Politics of the United Kingdom| importance = Top}}
{{WikiProject UK geography|importance=Top}}
{{WikiProject United Kingdom|importance=Top}}
}}
{{Press|date=August 17, 2009 |url= http://www.telegraph.co.uk/technology/wikipedia/6043534/The-50-most-viewed-Wikipedia-articles-in-2009-and-2008.html |title=The 50 most-viewed Wikipedia articles in 2009 and 2008 |org=[[The Daily Telegraph]] }}
{{Other banners|collapsed=yes|
{{Annual report|[[Wikipedia:2007 Top 50 Report|2007]], [[Wikipedia:2008 Top 50 Report|2008]], [[Wikipedia:2009 Top 50 Report|2009]], [[Wikipedia:2010 Top 50 Report|2010]], [[Wikipedia:2011 Top 50 Report|2011]], [[Wikipedia:2012 Top 50 Report|2012]], [[Wikipedia:2013 Top 50 Report|2013]], [[Wikipedia:2014 Top 50 Report|2014]], [[Wikipedia:Top 25 Report/2016|2016]], [[Wikipedia:2021 Top 50 Report|2021]], and [[Wikipedia:2022 Top 50 Report|2022]]}}
}}
{{section sizes}}
{{Talk:United Kingdom/archivebox}}
{{User:MiszaBot/config
|archiveheader = {{Automatic archive navigator}}
|maxarchivesize = 150K
|counter = 40
|algo = old(60d)
|archive = Talk:United Kingdom/Archive %(counter)d
}}{{User:HBC Archive Indexerbot/OptIn
|target=Talk:United Kingdom/Archive index
|mask1=Talk:United Kingdom/Archive <#>
|mask2=Talk:United_Kingdom/Country, Kingdom or State Archive <#>
|mask3=Talk:United_Kingdom/Terminology archive<#>
|mask4=Talk:United_Kingdom/Subdivision name archive<#>
|leading_zeros=0
|indexhere=yes}}
== Extended-confirmed-protected edit request on 6 July 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Change this line:
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the creation of the [[National Health Service]] (NHS) in 1949 is the primary healthcare provider in the United Kingdom.
To this:
The modern system of [[Universal service|universal]] [[Publicly funded health care|publicly funded healthcare]] in the United Kingdom has its origins in the establishment of the [[National Health Service]] (NHS), which began operating in 1948<ref>{{cite web |title=The foundation of the NHS |url=https://www.nationalarchives.gov.uk/explore-the-collection/stories/the-foundation-of-the-nhs/ |publisher=The National Archives |access-date=6 July 2026}}</ref> as the primary healthcare provider.
Reason:
Grammar fix, the current sentence is malformed ("...in 1949 is the primary healthcare provider..."). Year correction 1949→1948, sourced to The National Archives: the NHS began operating on 5 July 1948 (the "appointed day"). Wording changed from "creation of the NHS in 1949" to "establishment of the NHS, which began operating in 1948" because the NHS was created by separate acts across the UK (England and Wales: National Health Service Act 1946; Scotland: National Health Service (Scotland) Act 1947; Northern Ireland: Health Services Act (Northern Ireland) 1948) but launched UK-wide in 1948, so "establishment" plus the 1948 operating date avoids tying creation to a single year. Also removed the redundant second mention of "United Kingdom" at the end of the sentence. [[User:Dannyjamescarter|Dannyjamescarter]] ([[User talk:Dannyjamescarter|talk]]) 15:59, 6 July 2026 (UTC)
:{{done}}<!-- Template:EEp --> [[wp:solidarity|In solidarity]], [[User:Brynn Who Likes Editing|<span style="color: #04A">Brynn Who Likes Editing</span>]] <span style="color: #A59">'''|'''</span> [[User talk:Brynn Who Likes Editing|<span style="color:#E07">talk ''w''/ me!</span>]] 10:18, 19 August 2026 (UTC)
[[User:Lam312321321|Quack!]] [[User:Mutt Lunker|Mutt Lunker]] ([[User talk:Mutt Lunker|talk]]) 16:20, 6 July 2026 (UTC)
:Hi Mutt Lunker, I understand that the "Quack!" implies I'm a returning blocked user. I'm not. This is my only account, I have no connection to any blocked or banned editor, and I've built an ordinary editing history over my time here. I'd ask that the request be judged on its substance rather than on an assumption about who I am: it's a sourced correction (the NHS began operating on 5 July 1948, per The National Archives) and a fix to a grammatically broken sentence. If anyone genuinely believes otherwise about the account, the formal process exists for that. I've said my piece here and won't belabour it further. [[User:Dannyjamescarter|Dannyjamescarter]] ([[User talk:Dannyjamescarter|talk]]) 16:50, 6 July 2026 (UTC)
:[[User:Dannyjamescarter|Dannyjamescarter]] is neither listed in the confirmed sock puppets nor the suspected sock puppets of the ''Quack!'' account you linked to. Please do not create insinuations that an account is a sock puppet without evidence, as this can have a chilling effect. [[wp:solidarity|In solidarity]], [[User:Brynn Who Likes Editing|<span style="color: #04A">Brynn Who Likes Editing</span>]] <span style="color: #A59">'''|'''</span> [[User talk:Brynn Who Likes Editing|<span style="color:#E07">talk ''w''/ me!</span>]] 10:03, 19 August 2026 (UTC)
{{talk reflist}}
== costal =coastal ==
Article locked so cannot change.[[Special:Contributions/~2026-32542-29|~2026-32542-29]] ([[User talk:~2026-32542-29|talk]]) 03:35, 8 July 2026 (UTC)
:{{fixed}} I verified that the reference it's in misspelled the name of the publisher. –[[User:LaundryPizza03|<b style="color:#77b">Laundry</b><b style="color:#fb0">Pizza</b><b style="color:#b00">03</b>]] ([[User talk:LaundryPizza03|<span style="color:#0d0">d</span>]][[Special:Contribs/LaundryPizza03|<span style="color:#0bf">c̄</span>]]) 03:51, 8 July 2026 (UTC)
== Extended-confirmed-protected edit request on 12 July 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Instead of "country", The United Kingdom should be called a "sovereign state" because it is a political entity made up of multiple countries and represents multiple countries in the international stage. [[User:TheCountriesoftheWorld|TheCountriesoftheWorld]] ([[User talk:TheCountriesoftheWorld|talk]]) 02:14, 12 July 2026 (UTC)
:{{not done}} pls see [[Talk:United_Kingdom/Archive_30#sovereign_state,_not_country| a discussion that links to many other discussions]].<span style="display:inline-flex;rotate:-15deg;color:darkblue">'''[[User:Moxy|Moxy]]'''</span><span style="display:inline-flex;rotate:15deg;color:darkblue">[[User talk:Moxy|🍁]]</span> 02:31, 12 July 2026 (UTC)
== Government seat ==
{{ping|Bazza 7}} Usually when the seat of government is different to the capital city, infoboxes show that (e.g. see [[Kingdom of the Netherlands]]). I considered adding a "government seat" field but thought that would be [[WP:UNDUE]] emphasis for a very recent change when most government work is still done from London, which is why I added a footnote instead. [[User:Chessrat|<b style="color: #c90; font-family: comic sans ms">Chessrat</b>]] <sup>([[User talk:Chessrat|<span style="color:green">talk</span>]], [[Special:Contribs/Chessrat|<span style="color:#f78">contributions</span>]])</sup> 11:19, 24 July 2026 (UTC)
:I'm not sure that's a solid analogy. The Netherlands presents an unusual problem, in that while the ordinarily meaning of "capital city" is "place from which an entity is governed", Amsterdam, the ''official'' capital, outright fails to be the capital in the ordinary sense of the term. It seems to me that the situation with Manchester is better compared to the United States, where (a) there's an official presidential retreat in Camp David, Maryland, where many presidents have held official meetings, (b) the current president treats his estate in Palm Beach, Florida, as a secondary White House, and (c) the Department of Defense is in Arlington, Virginia. But the [[United States]] article makes no mention of either Camp David or Palm Beach, and mentions Arlington only in the caption under a photo of the Pentagon. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 11:41, 24 July 2026 (UTC)
::That's reasonable enough. Thanks for your thoughts. [[User:Chessrat|<b style="color: #c90; font-family: comic sans ms">Chessrat</b>]] <sup>([[User talk:Chessrat|<span style="color:green">talk</span>]], [[Special:Contribs/Chessrat|<span style="color:#f78">contributions</span>]])</sup> 12:54, 24 July 2026 (UTC)
:@[[User:Chessrat|Chessrat]]: Thanks for starting this discussion.
:As always, whatever is stated requires sourcing. So [https://www.bbc.co.uk/news/world-europe-18023389] (last updated 2024) plainly states the capital of the UK is London. So does [https://openfactbook.org/countries/united-kingdom/]. So that's what should be in the article (of which [[MOS:INFOBOXPURPOSE|the infobox is a summary]]). In the surprising absence of any referenced statement about the capital, I've added one in {{section link|United_Kingdom|Demographics}} (which location might seem odd but I couldn't figure anywhere else to put it). If someone finds reliable sources which state that London is usually the capital but Manchester takes over sometimes, then that can be added at the appropriate place.
:If the government of the day chooses to [https://www.bbc.co.uk/news/articles/ckgvyr76973o work elsewhere on Fridays], then that might be appropriate for the {{section link|United Kingdom|Government and politics}}, although I note that there is nothing about location in that section, which is probably as it should be; there is, though, at {{Section link|Government_of_the_United_Kingdom|Location}} so that may be the best place to add more sourced information to.
:I'll also note that I'm not a fan of placing facts which should be in article text inside notes: they're fine for clarifying a word or phrase, but not for carrying information. The MOS [[MOS:NOTES|obliquely implies that this might be an allowed use of notes]], but my own opinion is that if it's worth saying, then say it in the text of the appropriate article. [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 12:22, 24 July 2026 (UTC)
== Britain is not an accurate name ==
Might it be worth noting in the opening paragraph that although it is commonly referred to as Britain this is not the correct name. [[User:Dwnsdp|Dwnsdp]] ([[User talk:Dwnsdp|talk]]) 09:45, 14 August 2026 (UTC)
:What, for you, distinguishes between whether a commonly used name is correct or incorrect? Can you give separate examples of commonly used alternate names for things that are correct and that aren't correct? What I'm getting at here is that correctness doesn't apply and we aren't here to scold people for referring to it by a name commonly used to refer to it. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 11:30, 14 August 2026 (UTC)
::@[[User:Largoplazo|Largoplazo]] Referring to the UK as Britain is incorrect not because it is ''technically'' incorrect - as I agree we should not scold people for - but because as a name it directly excluded one of four kingdoms. A lot of people call the UK "England" due to a misunderstanding, which is not mentioned as an alternative name as it is not correct. What separates that common name from Britain. [[User:Dwnsdp|Dwnsdp]] ([[User talk:Dwnsdp|talk]]) 11:36, 14 August 2026 (UTC)
:::Not everyone shares the view that Britain strictly refers to just [[Great Britain]]. [[User:Chipmunkdavis|CMD]] ([[User talk:Chipmunkdavis|talk]]) 12:09, 14 August 2026 (UTC)
:::@[[User:Dwnsdp|Dwnsdp]]: Who says it's "incorrect"? [https://hansard.parliament.uk/lords/1964-07-09/debates/daef6f24-989f-44ee-8f0e-62940f5d2cbd/BritainSOfficialTitle This statement], made some time ago, considered "Britain" to be acceptable. The term might be ambiguous, or casual, or not official, but it's not incorrect. Perhaps you are confusing "correct" with "official"? In which case, it's not the "official name" of the United Kingdom, but neither is [https://www.gov.uk/government/publications/country-names/country-names-the-permanent-committee-on-geographical-names-for-british-official-use#u "United Kingdom"].
:::The first sentence of the article includes a note explaining the commonly-used "Britain". The "Etymology and terminology" and terminology in the first section of the article goes to great length to explain the country's various names. [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 12:13, 14 August 2026 (UTC)
::::It is ambiguous, yes. It has two common definitions: 1) the island containing three of the four nations (England, Scotland and Wales) of the United Kingdom (aka Great Britain), 2) the United Kingdom as a whole (England, Northern Ireland, Scotland and Wales). It is similar to the America vs. United States question. This could be explained in the article.
::::Given its ambiguity and potential to confuse though, it's probably more encyclopaedic to use "United Kingdom" or "UK" in general usage in other articles. -- [[User:DeFacto|<span style="color:#3366CC;">DeFacto</span>]] ([[User Talk:DeFacto|talk]]). 13:10, 14 August 2026 (UTC)
:::::@[[User:DeFacto|DeFacto]]: The article already contains a good summary of naming, with links to two in-depth articles for those who need more.
:::::I wasn't suggesting "Britain" should be used at all, for the reasons you state. On the contrary, things would be clearer if the MOS forbad it in Wikipedia articles other than when the word is the topic of discussion (as at the start of this article) or it's being quoted. (The [https://www.bbc.co.uk/newsstyleguide/all/#b BBC has a half-hearted go], the UK government [https://guidance.publishing.service.gov.uk/writing-to-gov-uk-standards/style-guides/a-to-z-style-guide/#britain slightly more].)
:::::I can't see that happening, though. But it's wrong to label others using it as "incorrect". [[User:Bazza_7|Bazza <span style="color:grey">7</span>]] ([[User_talk:Bazza_7|talk]]) 15:42, 14 August 2026 (UTC)
::::::@[[User:Bazza 7|Bazza 7]], fair enough, and yep, I totally agree with your second sentence. -- [[User:DeFacto|<span style="color:#3366CC;">DeFacto</span>]] ([[User Talk:DeFacto|talk]]). 16:51, 14 August 2026 (UTC)
:::"City of London" excludes most of the city of London. Many online articles can be found with phrases along the lines of "10 Downing Street issued a statement" or "10 Downing Street issued an apology", but we understand that it's neither the address nor the building designated by it that did the issuing, it was human beings inside of it. The word "decimate" originally referred to the killing of one in ten of the enemy but now it's used to connote a much greater level of devastation. South Africa excludes most of the south of Africa. The standard Turkish name for Morocco is "Fas", though more specifically it refers to the city of Fez. That the use of a name doesn't adhere strictly to its origin or its ''literal'' meaning doesn't mean it's incorrect. [[User:Largoplazo|Largoplazo]] ([[User talk:Largoplazo|talk]]) 12:46, 14 August 2026 (UTC)
== Extended-confirmed-protected edit request on 15 August 2026 ==
{{edit extended-protected|United Kingdom|answered=yes}}
Add [[Speaker of the House of Commons (United Kingdom)]], with the incumbent [[Lindsay Hoyle]] to the infobox under the monarch and prime minister. [[Special:Contributions/~2026-44665-10|~2026-44665-10]] ([[User talk:~2026-44665-10|talk]]) 12:58, 15 August 2026 (UTC)
:[[File:X mark.svg|20px|link=|alt=]] '''Not done for now:''' please establish a [[Wikipedia:Consensus|consensus]] for this alteration '''[[Wikipedia:Edit requests#Planning a request|before]]''' posting an edit request.<!-- Template:EEp --> We don't typically list the speaker on this article. — '''[[User:Czello|<i style="color:#8000FF">Czello</i>]]''' <sup>''([[User talk:Czello|<i style="color:#8000FF">music</i>]])''</sup> 13:14, 15 August 2026 (UTC)
hapgl7eeth9yhjzn1qmnyfobhn7n5cj
Tempilet:High use
10
1151
9329
2021-10-05T19:24:15Z
MusikBot II
347
Protected "[[Template:High use]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 345 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9329
wikitext
text/x-wiki
#Redirect [[Template:High-use]]
{{Redirect category shell|{{R from modification}}{{R from template shortcut}}}}
bw41vdqof5okzxgwyo9ltlzrt2hnqnm
9330
9329
2026-08-23T08:17:43Z
RAPTOR7762
18
1 revision imported from [[:en:Template:High_use]]
9329
wikitext
text/x-wiki
#Redirect [[Template:High-use]]
{{Redirect category shell|{{R from modification}}{{R from template shortcut}}}}
bw41vdqof5okzxgwyo9ltlzrt2hnqnm
Tempilet:Cascade-protected template
10
1152
9331
2026-01-15T13:09:33Z
Anomie
322
Undid 3 revisions from [[Special:Diff/1330133841|1330133841]] until [[Special:Diff/1331352231|1331352231]] - Revert recent inaccurate edits and excess verbosity. Most templates are not directly cascade-protected, only transcluded into cascade-protected pages, because direct cascade-protection will have unwanted side effects.
9331
wikitext
text/x-wiki
{{mbox
| type = protection
| image = [[File:Cascade-protection-shackle.svg|40x40px|link=|alt=]]
| text = This {{{page|template}}} can only be edited by [[Wikipedia:Administrators|administrators]] because it is [[Help:Transclusion|transcluded]] onto one or more [[Wikipedia:Protection policy#Cascading protection|cascade-protected]] pages.
}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage and interwikis in Wikidata, not here! -->
</noinclude>
mr3z6jtx488tvpg265fnq0gt90c2811
9332
9331
2026-08-23T08:17:43Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cascade-protected_template]]
9331
wikitext
text/x-wiki
{{mbox
| type = protection
| image = [[File:Cascade-protection-shackle.svg|40x40px|link=|alt=]]
| text = This {{{page|template}}} can only be edited by [[Wikipedia:Administrators|administrators]] because it is [[Help:Transclusion|transcluded]] onto one or more [[Wikipedia:Protection policy#Cascading protection|cascade-protected]] pages.
}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage and interwikis in Wikidata, not here! -->
</noinclude>
mr3z6jtx488tvpg265fnq0gt90c2811
Tempilet:Pagetype/doc
10
1153
9333
2024-08-30T18:35:48Z
2600 etc
348
9333
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Place categories where indicated at the bottom of this page and interwikis at Wikidata (see [[Wikipedia:Wikidata]]) -->
{{high use}}
{{cascade-protected template}}
{{lua|Module:Pagetype}}
This template is used to detect the page type of a given page. It detects [[WP:REDIRECT|redirect pages]] automatically and is highly customisable. It can be used on its own or as a meta-template to create other page-type-detection templates.
== Syntax ==
; Basic code
<pre>
{{pagetype}}
</pre>
; Full code
<pre>
{{pagetype
| page =
| defaultns =
| main =
| user =
| wikipedia =
| project =
| wp =
| file =
| image =
| mediawiki =
| template =
| help =
| category =
| portal =
| timedtext =
| module =
| special =
| media =
| talk =
| redirect =
| dab =
| na =
| other =
| plural =
}}
</pre>
== Basic usage ==
For simple detection of the page type of the current page, use the default settings:
{{pagetype}}
That will produce the following results, depending on the page type or the [[WP:NAMESPACE|namespace]]:
{| class="wikitable"
! Page type / namespace !! Output
|-
| Redirects (in any namespace) || <code>redirect</code>
|-
| Main namespace || <code>article</code>
|-
| File namespace || <code>file</code>
|-
| Template namespace || <code>template</code>
|-
| Category namespace || <code>category</code>
|-
| Module namespace || <code>module</code>
|-
| Other namespaces || <code>page</code>
|}
If the template is used on a talk page, it will detect the page type for the corresponding subject page.
; Example
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype}}</nowiki></code> || {{pagetype}}
|}
=== Page parameter ===
You can use the <code>page</code> parameter to make the template act as though it was called from that page.
{{pagetype|page=''page name''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=UK}}</nowiki></code> || {{pagetype|page=UK}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg}}</nowiki></code> || {{pagetype|page=File:Example.svg}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|}
== Adding and removing namespaces ==
It is possible to specify different behaviour for each namespace than that described in the [[#Basic usage|basic usage]] section. For example, you might want the template to display "user page" for pages in the user namespace, instead of the default "page". To do this, you can use the code {{para|user|yes}}. This looks up the typical name used for pages in the user namespace, in this case "user page", and uses that text when the template is used with a page in the user namespace. To use this with other namespaces, use the namespace name in lower case as a parameter:
{{pagetype
| user = ''yes''
| wikipedia = ''yes''
| project = ''yes''
| wp = ''yes''
| mediawiki = ''yes''
| help = ''yes''
| portal = ''yes''
| timedtext = ''yes''
| special = ''yes''
| media = ''yes''
}}
You can use any of the following to specify the namespace: "<code>yes</code>", "<code>y</code>", "<code>true</code>" or "<code>1</code>". They can be used in any combination of upper and lower case. (These values are defined by [[Module:Yesno]].)
The default text for these namespaces is as follows:
{| class="wikitable"
! Page type / namespace !! Output
|-
| User namespace || <code>user page</code>
|-
| Wikipedia namespace || <code>project page</code>
|-
| MediaWiki namespace || <code>interface page</code>
|-
| Help namespace || <code>help page</code>
|-
| Portal namespace || <code>portal</code>
|-
| Timed Text namespace || <code>Timed Text page</code>
|-
| Special namespace || <code>special page</code>
|-
| Media namespace || <code>file</code>
|}
You can use a similar process to remove any of the default namespace values as well. For example, if you use the code {{para|template|no}}, then the template will display "page" when used on a template page, rather than the default "template".
{{pagetype
| main = ''no''
| file = ''no''
| template = ''no''
| category = ''no''
| module = ''no''
}}
The following values will all work to remove namespace values: "<code>no</code>", "<code>n</code>", "<code>false</code>" or "<code>0</code>". They can be used in any combination of upper and lower case.
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|wikipedia=yes}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|wikipedia=yes}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|talk=y}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|talk=y}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|main=no}}</nowiki></code> || {{pagetype|page=United Kingdom|main=no}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=Yes}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=Yes}}
|}
== Default namespace sets ==
As well as adding and removing individual namespaces, it is possible to specify different sets of namespaces by using the {{para|defaultns}}. There are four different sets available: <code>all</code>, <code>extended</code>, <code>none</code> and the default set. These sets allow you to specify many namespaces at once, without having to use all of the individual namespace parameters. Namespaces are set according to the following table:
{| class="wikitable"
|-
! rowspan="2" | Namespace
! colspan="4" | Value of {{para|defaultns}}
! rowspan="2" | Output
|-
| style="width: 75px; text-align: center;" | <code>none</code>
| style="width: 75px; text-align: center;" | <code>extended</code>
| style="width: 75px; text-align: center;" | <code>all</code>
| style="width: 75px; text-align: center;" | Other values
|-
| Main
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| article
|-
| User
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| user page
|-
| Wikipedia
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| project page
|-
| File
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| file
|-
| MediaWiki
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| interface page
|-
| Template
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| template
|-
| Help
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| help page
|-
| Category
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| category
|-
| Portal
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| portal
|-
| TimedText
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| Timed Text page
|-
| Module
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| module
|-
| All talk namespaces
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| talk page
|-
| Special
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| special page
|-
| Media
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| file
|}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|defaultns=none}}</nowiki></code> || {{pagetype|page=United Kingdom|defaultns=none}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|defaultns=all}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|defaultns=all}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg}}</nowiki></code> || {{pagetype|page=File:Example.svg}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg|defaultns=none}}</nowiki></code> || {{pagetype|page=File:Example.svg|defaultns=none}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|defaultns=extended}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|defaultns=extended}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=extended}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=extended}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=all}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=all}}
|}
== Custom namespace values ==
It is possible to specify a custom value for any namespace:
{{pagetype
| main = ''custom text''
| user = ''custom text''
| wikipedia = ''custom text''
| project = ''custom text''
| wp = ''custom text''
| file = ''custom text''
| image = ''custom text''
| mediawiki = ''custom text''
| template = ''custom text''
| help = ''custom text''
| category = ''custom text''
| portal = ''custom text''
| timedtext = ''custom text''
| module = ''custom text''
| special = ''custom text''
| media = ''custom text''
}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|wikipedia=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|wikipedia=custom text}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|talk=custom text}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|talk=custom text}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|main=custom text}}</nowiki></code> || {{pagetype|page=United Kingdom|main=custom text}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=custom text}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=custom text}}
|}
== Talk parameter ==
Normally, the template will treat talk pages as if they were in the corresponding subject namespace. However, if the <code>talk</code> parameter is set, the template will treat talk pages separately from subject pages. The <code>talk</code> parameter sets values for all talk pages, i.e. pages in the Talk: namespace, pages in the User talk: namespace, pages in the Wikipedia talk: namespace, and so on.
{{pagetype|talk=''yes''}}
{{pagetype|talk=''custom text''}}
The default value for "<code>talk=''yes''</code>" is "talk page".
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|talk=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|talk=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|talk=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|talk=custom text}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=custom text}}
|}
== Main namespace classes ==
For pages in the main namespace, it is possible to add a class value in the first positional parameter:
{{pagetype|''class''}}
If the class value matches one of the values in the table below, it will produce an alternative to the default output of <code>article</code>.
{| class="wikitable"
|-
! Class !! Class values !! Output
|-
| No applicable class || <code>na</code>, <code>n/a</code> || <code>page</code>
|-
|}
You can input the class value in any combination of upper and lower case.
=== Custom main namespace classes ===
It is also possible to specify a custom value for the main namespace classes:
{{pagetype|''class''|na=''yes''}}
{{pagetype|''class''|na=''custom text''}}
This works the same way that it does for the custom namespace page types. Possible parameters are:
* '''na''': a custom value for NA-class pages. It works in the same way as the <code>dab</code> parameter. The default value for "<code>yes</code>" etc. is "page".
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|na}}</nowiki></code> || {{pagetype|page=United Kingdom|na}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|na|na=custom text}}</nowiki></code> || {{pagetype|page=United Kingdom|na|na=custom text}}
|}
== Redirects ==
By default, the template automatically detects redirects in all namespace. It is not possible to specify redirect behaviour by namespace, but you can turn redirect detection off, or use a custom value for redirect pages.
{{pagetype|redirect=''no''}}
{{pagetype|redirect=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=UK}}</nowiki></code> || {{pagetype|page=UK}}
|-
| <code><nowiki>{{pagetype|page=UK|redirect=no}}</nowiki></code> || {{pagetype|page=UK|redirect=no}}
|-
| <code><nowiki>{{pagetype|page=UK|redirect=custom text}}</nowiki></code> || {{pagetype|page=UK|redirect=custom text}}
|}
Note: redirects which are under discussion at [[Wikipedia:Redirects for discussion]], are now also detected automatically.
== Disambiguation pages ==
By default, the template uses [[Module:Disambiguation]] to detect [[WP:DAB|disambiguation pages]] in the main namespace. If you want, you can turn this detection off, or use a custom value for disambiguation pages.
{{pagetype|dab=''no''}}
{{pagetype|dab=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Mercury}}</nowiki></code> || {{pagetype|page=Mercury}}
|-
| <code><nowiki>{{pagetype|page=Mercury|dab=no}}</nowiki></code> || {{pagetype|page=Mercury|dab=no}}
|-
| <code><nowiki>{{pagetype|page=Mercury|dab=custom text}}</nowiki></code> || {{pagetype|page=Mercury|dab=custom text}}
|}
== Other namespaces ==
By default, the template produces "<code>page</code>" if used from a namespace that hasn't been specified. This value can be changed with the {{para|other}} parameter:
{{pagetype|other=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|other=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|other=custom text}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|other=custom text|wikipedia=wikipedia-space text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|other=custom text|wikipedia=wikipedia-space text}}
|}
== Plurals ==
By default the module returns the name of the namespace in the singular. Adding the parameter {{para|plural|y}} returns the plural form.
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|plural=y}}</nowiki></code> || {{pagetype|page=United Kingdom|plural=y}}
|-
| <code><nowiki>{{pagetype|page=Category:Books}}</nowiki></code> || {{pagetype|page=Category:Books}}
|-
| <code><nowiki>{{pagetype|page=Category:Books|plural=y}}</nowiki></code> || {{pagetype|page=Category:Books|plural=y}}
|}
The rules for pluralisation can be customised in [[Module:Pagetype/config]] to allow localisation.
== Capitalisation ==
By default the module returns the page type in lowercase. Adding the parameter {{para|caps|y}} returns a version with a capital letter at the start.
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|caps=y}}</nowiki></code> || {{pagetype|page=United Kingdom|caps=y}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|plural=y|caps=y}}</nowiki></code> || {{pagetype|page=United Kingdom|plural=y|caps=y}}
|}
==TemplateData==
{{Collapse top|[[Wikipedia:TemplateData|TemplateData]] documentation used by [[Wikipedia:VisualEditor|VisualEditor]] and other tools}}
{{TemplateData header|noheader=1}}
<templatedata>
{
"description": "This template Identifies the type of a given page. It is highly customisable. By default it detects redirects, articles, files, templates, categories, and modules, and other types of page are displayed as \"page\".",
"params": {
"1": {
"label": "Class",
"description": "Class is used to distinguish between different non-article pages in mainspace. 'disambig', 'disamb', 'dab', 'na' and 'n/a' give \"page\". The values can be customised with the \"dab\" and \"na\" parameters.",
"type": "string",
"required": false,
"suggestedvalues": [
"na"
]
},
"page": {
"label": "Page name",
"description": "The name of the page to detect the type of. Defaults to the current subject page, or to the current page if the \"talk\" parameter is activated.",
"type": "wiki-page-name",
"required": false,
"default": "{{SUBST:PAGENAME}}"
},
"main": {
"type": "string",
"label": "Main namespace",
"description": "When enabled, outputs \"article\" or custom text for the main namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"user": {
"type": "string",
"label": "User namespace",
"description": "When enabled, outputs \"user page\" or custom text for the User namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"wikipedia": {
"aliases": [
"project",
"wp"
],
"type": "string",
"label": "Wikipedia namespace",
"description": "When enabled, outputs \"project page\" or custom text for the Wikipedia namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"file": {
"type": "string",
"aliases": [
"image"
],
"label": "File namespace",
"description": "When enabled, outputs \"file\" or custom text for the File namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes",
"example": "custom"
},
"mediawiki": {
"type": "string",
"label": "MediaWiki namespace",
"description": "When enabled, outputs \"interface page\" or custom text for the MediaWiki namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"template": {
"type": "string",
"label": "Template namespace",
"description": "When enabled, outputs \"template\" or custom text for the Template namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes",
"example": "custom"
},
"help": {
"type": "string",
"label": "Help namespace",
"description": "When enabled, outputs \"help page\" or custom text for the Help namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"category": {
"type": "string",
"label": "Category namespace",
"description": "When enabled, outputs \"category\" or custom text for the Category namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"portal": {
"type": "string",
"label": "Portal namespace",
"description": "When enabled, outputs \"portal\" or custom text for the Portal namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"timedtext": {
"type": "string",
"label": "TimedText namespace",
"description": "When enabled, outputs \"Timed Text page\" or custom text for the TimedText namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"module": {
"type": "string",
"label": "Module namespace",
"description": "When enabled, outputs \"module\" or custom text for the Module namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"special": {
"type": "string",
"label": "Special namespace",
"description": "When enabled, outputs \"special page\" or custom text for the Special namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"media": {
"type": "string",
"label": "Media namespace",
"description": "When enabled, outputs \"file\" or custom text for the Media namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"talk": {
"type": "string",
"label": "All talk namespaces",
"description": "When enabled, outputs \"talk page\" or custom text for all talk namespaces. When disabled, uses the subject page of the specified page",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"redirect": {
"label": "Redirect page value",
"description": "When enabled, outputs \"redirect\" or custom text for redirects. When disabled, uses the destination",
"example": "custom",
"type": "string",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"dab": {
"type": "string",
"label": "Disambiguation page value",
"description": "When enabled, outputs \"disambiguation page\" or custom text for when the \"Class\" parameter has been set to \"disambiguation\", \"disamb\", or \"dab\"",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"na": {
"type": "string",
"label": "N/A page value",
"description": "When enabled, outputs \"page\" or custom text for pages in mainspace when the \"Class\" parameter has been set to \"disambiguation\", \"disamb\", or \"dab\"",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"other": {
"type": "string",
"label": "Other namespaces",
"description": "Outputs \"page\" or custom text for namespaces that have not been specified",
"default": "page"
},
"defaultns": {
"type": "line",
"label": "Set of default namespaces",
"description": "This parameter is used to specify the set of namespaces used by default. By default the template detects page types in the main, File, Template, Category, and Module namespaces. If this parameter is set to \"none\", the template doesn't detect page types in any namespaces. If it is set to \"extended\", the template detects page types in the main, User, Wikipedia, File, MediaWiki, Template, Help, Category, Portal, and Module namespaces. If it is set to \"all\", the template detects page types in all namespaces, including talk pages. The namespaces set by this parameter can be overridden by the parameters for individual namespaces.",
"suggestedvalues": [
"all",
"extended",
"none",
"default"
],
"default": "default"
},
"plural": {
"type": "boolean",
"label": "Pluralise output?",
"description": "Outputs a plural form (e.g. \"articles\" instead of \"article\").",
"default": "n"
},
"caps": {
"type": "boolean",
"label": "Capitalise output?",
"description": "Outputs a capital letter (e.g. \"Article\" instead of \"article\").",
"default": "n"
}
}
}
</templatedata>
{{Collapse bottom}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Namespace manipulation templates]]
}}</includeonly>
1mavbzulf9vx2u1or7jmpsf5m6jrd72
9334
9333
2026-08-23T08:17:43Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pagetype/doc]]
9333
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Place categories where indicated at the bottom of this page and interwikis at Wikidata (see [[Wikipedia:Wikidata]]) -->
{{high use}}
{{cascade-protected template}}
{{lua|Module:Pagetype}}
This template is used to detect the page type of a given page. It detects [[WP:REDIRECT|redirect pages]] automatically and is highly customisable. It can be used on its own or as a meta-template to create other page-type-detection templates.
== Syntax ==
; Basic code
<pre>
{{pagetype}}
</pre>
; Full code
<pre>
{{pagetype
| page =
| defaultns =
| main =
| user =
| wikipedia =
| project =
| wp =
| file =
| image =
| mediawiki =
| template =
| help =
| category =
| portal =
| timedtext =
| module =
| special =
| media =
| talk =
| redirect =
| dab =
| na =
| other =
| plural =
}}
</pre>
== Basic usage ==
For simple detection of the page type of the current page, use the default settings:
{{pagetype}}
That will produce the following results, depending on the page type or the [[WP:NAMESPACE|namespace]]:
{| class="wikitable"
! Page type / namespace !! Output
|-
| Redirects (in any namespace) || <code>redirect</code>
|-
| Main namespace || <code>article</code>
|-
| File namespace || <code>file</code>
|-
| Template namespace || <code>template</code>
|-
| Category namespace || <code>category</code>
|-
| Module namespace || <code>module</code>
|-
| Other namespaces || <code>page</code>
|}
If the template is used on a talk page, it will detect the page type for the corresponding subject page.
; Example
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype}}</nowiki></code> || {{pagetype}}
|}
=== Page parameter ===
You can use the <code>page</code> parameter to make the template act as though it was called from that page.
{{pagetype|page=''page name''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=UK}}</nowiki></code> || {{pagetype|page=UK}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg}}</nowiki></code> || {{pagetype|page=File:Example.svg}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|}
== Adding and removing namespaces ==
It is possible to specify different behaviour for each namespace than that described in the [[#Basic usage|basic usage]] section. For example, you might want the template to display "user page" for pages in the user namespace, instead of the default "page". To do this, you can use the code {{para|user|yes}}. This looks up the typical name used for pages in the user namespace, in this case "user page", and uses that text when the template is used with a page in the user namespace. To use this with other namespaces, use the namespace name in lower case as a parameter:
{{pagetype
| user = ''yes''
| wikipedia = ''yes''
| project = ''yes''
| wp = ''yes''
| mediawiki = ''yes''
| help = ''yes''
| portal = ''yes''
| timedtext = ''yes''
| special = ''yes''
| media = ''yes''
}}
You can use any of the following to specify the namespace: "<code>yes</code>", "<code>y</code>", "<code>true</code>" or "<code>1</code>". They can be used in any combination of upper and lower case. (These values are defined by [[Module:Yesno]].)
The default text for these namespaces is as follows:
{| class="wikitable"
! Page type / namespace !! Output
|-
| User namespace || <code>user page</code>
|-
| Wikipedia namespace || <code>project page</code>
|-
| MediaWiki namespace || <code>interface page</code>
|-
| Help namespace || <code>help page</code>
|-
| Portal namespace || <code>portal</code>
|-
| Timed Text namespace || <code>Timed Text page</code>
|-
| Special namespace || <code>special page</code>
|-
| Media namespace || <code>file</code>
|}
You can use a similar process to remove any of the default namespace values as well. For example, if you use the code {{para|template|no}}, then the template will display "page" when used on a template page, rather than the default "template".
{{pagetype
| main = ''no''
| file = ''no''
| template = ''no''
| category = ''no''
| module = ''no''
}}
The following values will all work to remove namespace values: "<code>no</code>", "<code>n</code>", "<code>false</code>" or "<code>0</code>". They can be used in any combination of upper and lower case.
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|wikipedia=yes}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|wikipedia=yes}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|talk=y}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|talk=y}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|main=no}}</nowiki></code> || {{pagetype|page=United Kingdom|main=no}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=Yes}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=Yes}}
|}
== Default namespace sets ==
As well as adding and removing individual namespaces, it is possible to specify different sets of namespaces by using the {{para|defaultns}}. There are four different sets available: <code>all</code>, <code>extended</code>, <code>none</code> and the default set. These sets allow you to specify many namespaces at once, without having to use all of the individual namespace parameters. Namespaces are set according to the following table:
{| class="wikitable"
|-
! rowspan="2" | Namespace
! colspan="4" | Value of {{para|defaultns}}
! rowspan="2" | Output
|-
| style="width: 75px; text-align: center;" | <code>none</code>
| style="width: 75px; text-align: center;" | <code>extended</code>
| style="width: 75px; text-align: center;" | <code>all</code>
| style="width: 75px; text-align: center;" | Other values
|-
| Main
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| article
|-
| User
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| user page
|-
| Wikipedia
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| project page
|-
| File
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| file
|-
| MediaWiki
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| interface page
|-
| Template
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| template
|-
| Help
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| help page
|-
| Category
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| category
|-
| Portal
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| portal
|-
| TimedText
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| Timed Text page
|-
| Module
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{tick}}
| module
|-
| All talk namespaces
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| talk page
|-
| Special
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| special page
|-
| Media
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{cross}}
| style="text-align: center;" | {{tick}}
| style="text-align: center;" | {{cross}}
| file
|}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|defaultns=none}}</nowiki></code> || {{pagetype|page=United Kingdom|defaultns=none}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|defaultns=all}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|defaultns=all}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg}}</nowiki></code> || {{pagetype|page=File:Example.svg}}
|-
| <code><nowiki>{{pagetype|page=File:Example.svg|defaultns=none}}</nowiki></code> || {{pagetype|page=File:Example.svg|defaultns=none}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|defaultns=extended}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|defaultns=extended}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=extended}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=extended}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=all}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|defaultns=all}}
|}
== Custom namespace values ==
It is possible to specify a custom value for any namespace:
{{pagetype
| main = ''custom text''
| user = ''custom text''
| wikipedia = ''custom text''
| project = ''custom text''
| wp = ''custom text''
| file = ''custom text''
| image = ''custom text''
| mediawiki = ''custom text''
| template = ''custom text''
| help = ''custom text''
| category = ''custom text''
| portal = ''custom text''
| timedtext = ''custom text''
| module = ''custom text''
| special = ''custom text''
| media = ''custom text''
}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|wikipedia=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|wikipedia=custom text}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=Talk:United Kingdom|talk=custom text}}</nowiki></code> || {{pagetype|page=Talk:United Kingdom|talk=custom text}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|main=custom text}}</nowiki></code> || {{pagetype|page=United Kingdom|main=custom text}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt}}
|-
| <code><nowiki>{{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=custom text}}</nowiki></code> || {{pagetype|page=TimedText:MS_Sam.ogg.en.srt|timedtext=custom text}}
|}
== Talk parameter ==
Normally, the template will treat talk pages as if they were in the corresponding subject namespace. However, if the <code>talk</code> parameter is set, the template will treat talk pages separately from subject pages. The <code>talk</code> parameter sets values for all talk pages, i.e. pages in the Talk: namespace, pages in the User talk: namespace, pages in the Wikipedia talk: namespace, and so on.
{{pagetype|talk=''yes''}}
{{pagetype|talk=''custom text''}}
The default value for "<code>talk=''yes''</code>" is "talk page".
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|talk=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|talk=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=yes}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=yes}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|talk=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|talk=custom text}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia talk:Namespace|wikipedia=yes|talk=custom text}}
|}
== Main namespace classes ==
For pages in the main namespace, it is possible to add a class value in the first positional parameter:
{{pagetype|''class''}}
If the class value matches one of the values in the table below, it will produce an alternative to the default output of <code>article</code>.
{| class="wikitable"
|-
! Class !! Class values !! Output
|-
| No applicable class || <code>na</code>, <code>n/a</code> || <code>page</code>
|-
|}
You can input the class value in any combination of upper and lower case.
=== Custom main namespace classes ===
It is also possible to specify a custom value for the main namespace classes:
{{pagetype|''class''|na=''yes''}}
{{pagetype|''class''|na=''custom text''}}
This works the same way that it does for the custom namespace page types. Possible parameters are:
* '''na''': a custom value for NA-class pages. It works in the same way as the <code>dab</code> parameter. The default value for "<code>yes</code>" etc. is "page".
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|na}}</nowiki></code> || {{pagetype|page=United Kingdom|na}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|na|na=custom text}}</nowiki></code> || {{pagetype|page=United Kingdom|na|na=custom text}}
|}
== Redirects ==
By default, the template automatically detects redirects in all namespace. It is not possible to specify redirect behaviour by namespace, but you can turn redirect detection off, or use a custom value for redirect pages.
{{pagetype|redirect=''no''}}
{{pagetype|redirect=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=UK}}</nowiki></code> || {{pagetype|page=UK}}
|-
| <code><nowiki>{{pagetype|page=UK|redirect=no}}</nowiki></code> || {{pagetype|page=UK|redirect=no}}
|-
| <code><nowiki>{{pagetype|page=UK|redirect=custom text}}</nowiki></code> || {{pagetype|page=UK|redirect=custom text}}
|}
Note: redirects which are under discussion at [[Wikipedia:Redirects for discussion]], are now also detected automatically.
== Disambiguation pages ==
By default, the template uses [[Module:Disambiguation]] to detect [[WP:DAB|disambiguation pages]] in the main namespace. If you want, you can turn this detection off, or use a custom value for disambiguation pages.
{{pagetype|dab=''no''}}
{{pagetype|dab=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Mercury}}</nowiki></code> || {{pagetype|page=Mercury}}
|-
| <code><nowiki>{{pagetype|page=Mercury|dab=no}}</nowiki></code> || {{pagetype|page=Mercury|dab=no}}
|-
| <code><nowiki>{{pagetype|page=Mercury|dab=custom text}}</nowiki></code> || {{pagetype|page=Mercury|dab=custom text}}
|}
== Other namespaces ==
By default, the template produces "<code>page</code>" if used from a namespace that hasn't been specified. This value can be changed with the {{para|other}} parameter:
{{pagetype|other=''custom text''}}
; Examples
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|other=custom text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|other=custom text}}
|-
| <code><nowiki>{{pagetype|page=Wikipedia:Namespace|other=custom text|wikipedia=wikipedia-space text}}</nowiki></code> || {{pagetype|page=Wikipedia:Namespace|other=custom text|wikipedia=wikipedia-space text}}
|}
== Plurals ==
By default the module returns the name of the namespace in the singular. Adding the parameter {{para|plural|y}} returns the plural form.
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|plural=y}}</nowiki></code> || {{pagetype|page=United Kingdom|plural=y}}
|-
| <code><nowiki>{{pagetype|page=Category:Books}}</nowiki></code> || {{pagetype|page=Category:Books}}
|-
| <code><nowiki>{{pagetype|page=Category:Books|plural=y}}</nowiki></code> || {{pagetype|page=Category:Books|plural=y}}
|}
The rules for pluralisation can be customised in [[Module:Pagetype/config]] to allow localisation.
== Capitalisation ==
By default the module returns the page type in lowercase. Adding the parameter {{para|caps|y}} returns a version with a capital letter at the start.
{| class="wikitable"
|-
! Code !! Result
|-
| <code><nowiki>{{pagetype|page=United Kingdom}}</nowiki></code> || {{pagetype|page=United Kingdom}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|caps=y}}</nowiki></code> || {{pagetype|page=United Kingdom|caps=y}}
|-
| <code><nowiki>{{pagetype|page=United Kingdom|plural=y|caps=y}}</nowiki></code> || {{pagetype|page=United Kingdom|plural=y|caps=y}}
|}
==TemplateData==
{{Collapse top|[[Wikipedia:TemplateData|TemplateData]] documentation used by [[Wikipedia:VisualEditor|VisualEditor]] and other tools}}
{{TemplateData header|noheader=1}}
<templatedata>
{
"description": "This template Identifies the type of a given page. It is highly customisable. By default it detects redirects, articles, files, templates, categories, and modules, and other types of page are displayed as \"page\".",
"params": {
"1": {
"label": "Class",
"description": "Class is used to distinguish between different non-article pages in mainspace. 'disambig', 'disamb', 'dab', 'na' and 'n/a' give \"page\". The values can be customised with the \"dab\" and \"na\" parameters.",
"type": "string",
"required": false,
"suggestedvalues": [
"na"
]
},
"page": {
"label": "Page name",
"description": "The name of the page to detect the type of. Defaults to the current subject page, or to the current page if the \"talk\" parameter is activated.",
"type": "wiki-page-name",
"required": false,
"default": "{{SUBST:PAGENAME}}"
},
"main": {
"type": "string",
"label": "Main namespace",
"description": "When enabled, outputs \"article\" or custom text for the main namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"user": {
"type": "string",
"label": "User namespace",
"description": "When enabled, outputs \"user page\" or custom text for the User namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"wikipedia": {
"aliases": [
"project",
"wp"
],
"type": "string",
"label": "Wikipedia namespace",
"description": "When enabled, outputs \"project page\" or custom text for the Wikipedia namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"file": {
"type": "string",
"aliases": [
"image"
],
"label": "File namespace",
"description": "When enabled, outputs \"file\" or custom text for the File namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes",
"example": "custom"
},
"mediawiki": {
"type": "string",
"label": "MediaWiki namespace",
"description": "When enabled, outputs \"interface page\" or custom text for the MediaWiki namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"template": {
"type": "string",
"label": "Template namespace",
"description": "When enabled, outputs \"template\" or custom text for the Template namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes",
"example": "custom"
},
"help": {
"type": "string",
"label": "Help namespace",
"description": "When enabled, outputs \"help page\" or custom text for the Help namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"category": {
"type": "string",
"label": "Category namespace",
"description": "When enabled, outputs \"category\" or custom text for the Category namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"portal": {
"type": "string",
"label": "Portal namespace",
"description": "When enabled, outputs \"portal\" or custom text for the Portal namespace",
"suggestedvalues": [
"yes",
"no"
],
"default": "no",
"example": "custom"
},
"timedtext": {
"type": "string",
"label": "TimedText namespace",
"description": "When enabled, outputs \"Timed Text page\" or custom text for the TimedText namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"module": {
"type": "string",
"label": "Module namespace",
"description": "When enabled, outputs \"module\" or custom text for the Module namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"special": {
"type": "string",
"label": "Special namespace",
"description": "When enabled, outputs \"special page\" or custom text for the Special namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"media": {
"type": "string",
"label": "Media namespace",
"description": "When enabled, outputs \"file\" or custom text for the Media namespace",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"talk": {
"type": "string",
"label": "All talk namespaces",
"description": "When enabled, outputs \"talk page\" or custom text for all talk namespaces. When disabled, uses the subject page of the specified page",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"redirect": {
"label": "Redirect page value",
"description": "When enabled, outputs \"redirect\" or custom text for redirects. When disabled, uses the destination",
"example": "custom",
"type": "string",
"suggestedvalues": [
"yes",
"no"
],
"default": "yes"
},
"dab": {
"type": "string",
"label": "Disambiguation page value",
"description": "When enabled, outputs \"disambiguation page\" or custom text for when the \"Class\" parameter has been set to \"disambiguation\", \"disamb\", or \"dab\"",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"na": {
"type": "string",
"label": "N/A page value",
"description": "When enabled, outputs \"page\" or custom text for pages in mainspace when the \"Class\" parameter has been set to \"disambiguation\", \"disamb\", or \"dab\"",
"example": "custom",
"suggestedvalues": [
"yes",
"no"
],
"default": "no"
},
"other": {
"type": "string",
"label": "Other namespaces",
"description": "Outputs \"page\" or custom text for namespaces that have not been specified",
"default": "page"
},
"defaultns": {
"type": "line",
"label": "Set of default namespaces",
"description": "This parameter is used to specify the set of namespaces used by default. By default the template detects page types in the main, File, Template, Category, and Module namespaces. If this parameter is set to \"none\", the template doesn't detect page types in any namespaces. If it is set to \"extended\", the template detects page types in the main, User, Wikipedia, File, MediaWiki, Template, Help, Category, Portal, and Module namespaces. If it is set to \"all\", the template detects page types in all namespaces, including talk pages. The namespaces set by this parameter can be overridden by the parameters for individual namespaces.",
"suggestedvalues": [
"all",
"extended",
"none",
"default"
],
"default": "default"
},
"plural": {
"type": "boolean",
"label": "Pluralise output?",
"description": "Outputs a plural form (e.g. \"articles\" instead of \"article\").",
"default": "n"
},
"caps": {
"type": "boolean",
"label": "Capitalise output?",
"description": "Outputs a capital letter (e.g. \"Article\" instead of \"article\").",
"default": "n"
}
}
}
</templatedata>
{{Collapse bottom}}
<includeonly>{{Sandbox other||
<!--Categories below this line, please; interwikis at Wikidata-->
[[Category:Namespace manipulation templates]]
}}</includeonly>
1mavbzulf9vx2u1or7jmpsf5m6jrd72
Wikipidiya:Namespace
4
1154
9335
2026-08-11T21:59:15Z
Voidxor
349
/* Virtual namespaces */ ce
9335
wikitext
text/x-wiki
{{Short description|Prefix before a Wikipedia page's name}}
{{redirect-distinguish|WP:NS|Wikipedia:WikiProject Nova Scotia}}
{{redirect-distinguish|WP:NSPACE|Wikipedia:Notability (astronomical objects)}}
{{pp-semi-vandalism|small=yes}}{{pp-move-indef}}
{{Infopage|WP:NS|WP:NSPACE}}
{{Namespaces}}
A Wikipedia '''namespace''' is a set of Wikipedia pages whose [[Help:page name|names]] begin with a reserved word, followed by a colon. The reserved word is recognized by the [[MediaWiki]] software. For example, in the ''user namespace'' all titles begin with the prefix ''User:''. In the case of the article (or main) namespace, in which encyclopedia articles appear, the reserved word and colon are absent. (Note: main space articles can optionally include a colon at the beginning with no reserved word, so <code>[<nowiki/>[Article]]</code> and <code>[<nowiki/>[:Article]]</code> are equivalent. This is usually only necessary for the advanced technique of [[WP:Transclusion|transcluding]] a main space article into a page in another namespace.)
More generally, a Wikipedia '''namespace''' is a class of pages that falls under a common type. All pages in the <code>User</code> namespace, for example, are [[Wikipedia:User pages|user pages]], whereas [[WP:Drafts|Drafts]] are in the <code>Draft</code> namespace. This page is in the <code>[[WP:Project namespace|Wikipedia]]</code> namespace, for information or discussions about the project itself and its policies.
Wikipedia has 30 current namespaces: 14 subject namespaces, 14 corresponding talk namespaces, and 2 virtual namespaces. These are all listed in the box to the right. While surfing Wikipedia, a list of namespaces is available in two clicks: do an empty search, then click ''Advanced'' under the search box. The list also makes itself available where needed in the dropdown menus of, for example, [[Special:PrefixIndex]], [[Special:AllPages]], [[Special:RecentChanges]], and [[Special:Contributions]].
The aliases '''WP''' for '''Wikipedia''', and '''WT''' for '''Wikipedia talk''', work for page names in the search box, and making links as well as inclusions. See [[#Aliases|Aliases]] below for other aliases. (The pseudo-namespaces such as '''H''' for '''Help''', and '''CAT''' for '''Category''', are extremely limited. See ''[[#Pseudo-namespaces|Pseudo-namespaces]]'' below.)
The table on the right shows what number to use when you want to hide pages that are on your watchlist. See: [[Wikipedia:Hide Pages in Watchlist]] for details.
== Subject namespaces ==
{{see|Wikipedia:Administration#Data structure and development}}
[[File:Policies and guidelines indicator.png|thumb|350px|This page is in the [[Wikipedia:Project namespace|Wikipedia namespace]].]]
Namespaces allow for the organization and separation of [[Wikipedia:Administration#Content namespaces|content pages]] from [[Wikipedia:Administration#Administrative namespaces|administration pages]]. Namespaces separate data into core sets, those intended for public viewing, and those intended for the editing community. Wikipedia's subject namespaces and their functions are listed below. A brief description is provided, but see the link for more information.
{{anchor|subjectpage}}A namespace is sometimes called a ''space'', for short, as in "Project space". A ''subject page'' and its ''talk page'' form a pair.
<!--
in order of {{NAMESPACENUMBER}}
-->
===Current namespaces===
* '''[[Wikipedia:Main namespace|Main namespace]]''' (no prefix): contains all encyclopedia articles, lists, [[Wikipedia:Disambiguation|disambiguation pages]], and encyclopedia [[Wikipedia:Redirect|redirects]]. Sometimes referred to as "mainspace" or "Article".
* '''[[Wikipedia:User namespace|User namespace]]''' (prefix '''User:'''): contains user pages and other pages created by individual users for their own personal use. Pages under this namespace can still be viewed and modified by others, so do not keep any of your sensitive data here.
* '''[[Wikipedia:Wikipedia namespace|Wikipedia namespace]]''' or '''[[Wikipedia:Project namespace|Project namespace]]''' (prefix '''Wikipedia:'''): contains many types of pages connected with the Wikipedia project itself: information, policies, guidelines, essays, processes, discussion, etc. [[Wikipedia:Namespace#Aliases|Namespace aliases]]: '''WP:''' or '''Project:'''
*{{anchor|File|File namespace}}'''[[Wikipedia:File namespace|File namespace]]''' (prefix '''File:'''): contains [[Help:File description page|description pages for media files]] (images, videos, and audio files). A link starting with <code><nowiki>[[File:</nowiki></code> will display the media at that position on the page instead of showing a wikilink that leads to the specified file description page, so if you want the latter effect, use a link beginning with <code><nowiki>[[:File:</nowiki></code> (the [[Help:Colon trick|colon trick]]). Namespace alias: '''Image:'''
* '''[[Help:MediaWiki namespace|MediaWiki namespace]]''' (prefix '''MediaWiki:'''): a namespace containing interface texts, such as the links and messages that appear on automatically generated pages. Pages in this namespace are permanently [[Wikipedia:Protection policy|protected]] against editing by regular users. For a list of these messages, see [[Special:AllMessages]]. (The prefix ''cannot'' be shortened to "MW" because '''mw''' is an interwiki prefix. See ''[[#Interwiki links|Interwiki links]]'' below.)
* '''[[Wikipedia:Template namespace|Template namespace]]''' (prefix '''Template:'''): contains templates – pages that are intended primarily to be [[Wikipedia:Transclusion|transcluded]] or [[Wikipedia:Substitution|substituted]] onto other pages to insert standard text or boxes such as infoboxes and navigation boxes. [[Wikipedia:Namespace#Aliases|Namespace alias]]: '''TM:'''
* '''[[WP:Help namespace|Help namespace]]''' (prefix '''Help:'''): contains pages which provide help in using Wikipedia and its software, both for users of the encyclopedia and for editors.
* '''[[Wikipedia:Category namespace|Category namespace]]''' (prefix '''Category:'''): contains category pages, which are curated lists of related pages and subcategories, along with optional additional text. A link beginning with <code><nowiki>[[Category:</nowiki></code> has the effect of adding the page the link appears on to the specified category; it will not result in a wikilink to the category page itself. If you want the latter, use the [[Help:Colon trick|colon trick]]: <code><nowiki>[[:Category:</nowiki></code>.
* '''[[Wikipedia:Portal namespace|Portal namespace]]''' (prefix '''Portal:'''): for reader-oriented portals that help readers find articles related to a specific topic, and may contain links to encourage contributions to relevant [[Wikipedia:WikiProject|WikiProjects]]. See, for example, [[Portal:Cricket]] and [[Portal:Spaceflight]].
* '''[[Wikipedia:Draft namespace|Draft namespace]]''' (prefix '''Draft:'''): hosts drafts of new (potential) Wikipedia articles.
* '''[[mw:Extension:TimedMediaHandler|TimedText namespace]]''' (prefix '''TimedText:'''): synchronized subtitles for media files.
* '''[[Wikipedia:Module namespace|Module namespace]]''' (prefix '''Module:'''): contains [[mw:Extension:Scribunto|Scribunto]] modules – Lua scripts implementing special-purpose [[mw:Manual:Parser functions|parser functions]] for use in templates, beyond the [[Help:Magic words#Parser functions|basic set]] included with MediaWiki and its [[mw:Extensions FAQ|extensions]].
* {{anchor|MOS}}'''[[WP:Manual of Style|MOS namespace]]''' (prefix '''MOS:'''): contains redirects to subpages of [[WP:Manual of Style]]. Until 2024 this was a pseudo-namespace, but it was turned into a real namespace in 2024 to avoid conflicts with the [[Mooré]] Wikipedia (with the language code <code>mos:</code>).<ref>[[phab:T363538]]</ref>
* '''[[Event:Sandbox|Event namespace]]''' (prefix '''Event:''') contains [[mw:Extension:CampaignEvents]] events.
===Former namespaces===
The following namespaces previously existed but no longer do:
*'''[[Wikipedia:Flow|Flow namespace]]''' (prefix '''Topic:''') was a proposed talk page replacement, formerly installed on English Wikipedia by [[mw:Extension:StructuredDiscussions|Extension:StructuredDiscussions]]. It is no longer installed after being rejected by the community.
* '''[[Wikipedia:Course pages|Education Program namespace]]''' (prefix '''Education Program:'''): uninstalled in 2018, and replaced with the [[wmfdashboard:|Programs & Events Dashboard]].<ref>[[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]], Wikimedia outreach</ref><ref>{{Section link|Wikipedia:Education noticeboard/Archive 18#NOTICE:_EducationProgram extension is being deprecated}}</ref> However, the namespace was re-added later that year to allow access to old talk pages in the Education program talk: namespace. The namespace was then uninstalled again in 2021 after the remaining talk pages were moved to subpages of [[Wikipedia talk:Education program archive]].
* '''[[Wikipedia:Books|Book namespace]]''' (prefix '''Book:'''): contained entries for Wikipedia books, collections of articles about one theme, which were used to generate downloadable files or printable documents or order books from PediaPress. In 2017, the online book rendering service was withdrawn, leading to the removal of most links leading to the namespace in 2019. The namespace and its transclusions were still retained in the hope that the WMF would come up with a solution,<ref>{{Section link|Wikipedia:Village pump (technical)/Archive 176|Suppress rendering of Template:Wikipedia books}}</ref> but in 2021 the namespace was uninstalled after all remaining books were moved to subpages of [[Wikipedia:Books/archive]].
* '''Gadget namespace''' (prefix '''Gadget:'''):<ref>{{Section link|Wikipedia:Village pump (technical)/Archive 139#New "Gadget:" and "Gadget definition:" namespaces?}}</ref> was intended to store [[Wikipedia:Gadget|Gadgets]], which are small [[Snippet (programming)|snippets]] enabled in [[Special:Preferences#mw-prefsection-gadgets|user preferences]], but was never used for anything other than redirects to the video game ''[[Gadget: Invention, Travel, & Adventure]]'', and for most of its existence could only be edited by WMF staff. Gadgets currently use the [[Help:MediaWiki namespace|MediaWiki namespace]] with the ''MediaWiki:Gadget-'' page name prefix. It was a [[mw:Manual:Using custom namespaces|custom namespace]] installed by the [[mw:Extension:Gadgets|Gadget extension]].
* '''Gadget definition namespace''' (prefix '''Gadget definition:'''): installed but never used; see above for more information. Gadget definitions currently use the [[MediaWiki:Gadgets-definition]] page.
===Aliases and pseudo-namespaces===
{{redirect|Wikipedia:Alias|template parameter aliases|Help:Template#Handling parameters}}
An ''alias'' of a namespace is its namespace. For example, '''WP:''' is '''Wikipedia:''', and so
<code><nowiki>[[</nowiki>Wikipedia:[[WP:Page name|''Page name'']]]]</code> can be abbreviated <code><nowiki>[[WP:</nowiki>[[WP:Page name|''Page name'']]]]</code>.
See ''[[#Aliases|Aliases]]'' below, for a list of aliases, such as '''WT:''' for '''Wikipedia talk:'''.
A ''pseudo-namespace'' is an agreement to create redirect pages named that way, each of which
is a shortcut from mainspace to ''a single page in its namespace''.
So an alias refers to ''any page in its namespace'', but a pseudo-namespace has far fewer pages than its real namespace.
There are a few pseudo-namespace names like '''H:''' for '''Help:''', and '''CAT:''' for '''Category:''', and these can be discovered below in the section ''[[#Pseudo-namespaces|Pseudo-namespaces]]''.
== <span id="Talk"></span><span id="Wikipedia talk"></span><span id="WT"></span> Talk namespaces==
{{shortcut|WP:TALKSPACE}}
{{main|Help:Using talk pages|Wikipedia:Talk page guidelines}}
Each of the above namespaces (but not the virtual namespaces and the former Topic: namespace) has an associated [[help:talk page|talk namespace]]—these are also known as ''discussion pages''. The talk namespaces are designated by appending the word <code>talk</code> to the namespace name. For example, the talk namespace associated with the user namespace has the prefix '''User talk:'''. The talk namespace associated with the article namespace is '''Talk:'''.
Most of the pages in the talk namespaces are used to discuss changes to the corresponding page in the associated namespace. Pages in the ''user talk'' namespace are used to leave messages for a particular user. The user talk namespace is special in that, whenever a user's talk page is edited, that user will see an orange box saying "You have new messages" on the top of every page that they view until they visit their talk page. By default, logged-in users will see [[Wikipedia:Notifications|a red notification square]] ''and'' a small orange box on the top right hand corner of the page; IP users will only see a wide orange box spanning the top of the page. (Minor edits made by [[Wikipedia:Bot policy|bots]] no longer set off the new message bar. For logged-in users, the new-message bar may be disabled in [[Special:Preferences]].)
Note that the prefix '''WT:''' expands to '''Wikipedia talk:''', just as '''WP:''' expands to '''Wikipedia:''' (see [[#Aliases|Aliases]] below). For example, <nowiki>[[WT:Verifiability]]</nowiki> links to [[Wikipedia talk:Verifiability]].
== Virtual namespaces<span id="Special"></span> ==
In addition to subject namespaces and their corresponding talk pages, there are two virtual namespaces (without corresponding talk pages) for specialist purposes:
=== Special ===
{{Main|Help:Special page}}
The ''Special:'' namespace consists of pages (called ''special pages'') that are created by the software on demand, such as [[Special:RecentChanges]]. These pages can be linked as usual, as with <nowiki>[[Special:RecentChanges]]</nowiki>, except when they have parameters. To use parameters, the full URL must be given as an external link. For example, https:{{SERVER}}{{SCRIPTPATH}}/index.php?title=Special:Recentchanges&days=3&limit=10, which returns the last ten changes in the last three days.
You can create a [[Wikipedia:redirect|redirect]] to a Special page, but the redirect will not be followed automatically.
For a list of special pages, see [[Special:SpecialPages]].
=== Media<span class="anchor" id="Media namespace"></span> ===
{{Main|Help:Files}}
The ''Media:'' namespace can be used to link directly to a file, rather than to the file description page.
== Aliases and pseudo-namespaces==
{{See|Wikipedia:Shortcut#List of prefixes}}
Aliases and pseudo-namespaces are not namespaces in themselves; their main role is to provide handy ways to link to actual namespaces, by providing shortened links.
The main difference between them being the way they work for this purpose; while aliases directly link to namespaces, pseudo-namespaces can only link to other namespaces by using specialist [[Wikipedia:Redirect|redirect pages]] in the main namespace called [[Wikipedia:Shortcut|shortcuts]]. While aliases are also used for shortcuts, this isn't necessary if the pagename is not shortened.
Pseudo-namespaces all actually reside in main namespace; but a pseudo-namespace called [[m:Help:Transwiki|Transwiki:]] exists as a pseudo-namespace before being moved to another namespace.
=== Aliases ===
{{Shortcut|WP:ALIAS}}
There are seven aliases defined for namespaces, all of which are case-insensitive:
{| class=wikitable
!Namespace
!Alias
|-
| rowspan="2" |Wikipedia
|WP
|-
|Project
|-
| rowspan="2" |Wikipedia talk
|WT
|-
|Project talk
|-
|File
|Image
|-
|File talk
|Image talk
|-
|Template
|TM
|}
These aliases are automatically translated by the Wikipedia servers to the proper namespace prefix. So if a link is made to a page title beginning with one of these aliases, or else entered in the search box or used in a URL in a browser address bar, the alias links to the page with the corresponding true namespace prefix. Hence entering [[WP:External links]] or [[Project:External links]] is equivalent to entering [[Wikipedia:External links]]; and entering [[WT:External links]] or [[Project talk:External links]] is equivalent to entering [[Wikipedia talk:External links]].
An alias cannot be used as the actual namespace in a page title. For example, you cannot create page ''WP:123''; if tried, the page name is instantly converted to ''Wikipedia:123''. It ''is'', however, possible to [[Wikipedia:Page name#Changing the displayed title|change the ''displayed'' title]] on page ''Wikipedia:123'' to make it ''WP:123'' or ''Project:123''.
<span class="plainlinks">This is very handy for the creation of [[Wikipedia:Shortcut|shortcuts]]. For example, the shortcut for this section is [[WP:ALIAS]], as shown in the right-side box. When the link is clicked, it is automatically translated to [https://en.wikipedia.org/w/index.php?title=Wikipedia:ALIAS&redirect=no Wikipedia:ALIAS]. At this page is a [[Help:Redirect|redirect]] to {{Section link|Wikipedia:Namespace#Aliases}}. This means that the shortcut goes directly to this section from anywhere on Wikipedia. It can also be entered as a [[URL]] in the browser address bar as https://en.wikipedia.org/wiki/WP:ALIAS .</span>
=== Pseudo-namespaces ===
<!-- This section is linked from [[Wikipedia:Glossary]] -->
{{Shortcut|WP:PNS}}
Apart from Wikipedia's 24 regular namespaces and their aliases, and 2 virtual ones, there are several title prefixes appearing in [[Help:Shortcut|shortcut redirects]] pointing to frequently-referred-to Wikipedia pages. These prefixes are referred to as '''pseudo-namespaces''' and include the following:
* '''[[Special:Prefixindex/CAT:|CAT:]]''' for shortcuts to the [[Wikipedia:Category namespace|Category namespace]]. See also [[:Category:Redirects to category space]]
* '''[[Special:Prefixindex/H:|H:]]''' for shortcuts to the [[Wikipedia:Help namespace|Help namespace]]. See also [[:Category:Redirects to help namespace]]
* '''[[Special:Prefixindex/P:|P:]]''' for shortcuts to the [[Wikipedia:Portal namespace|Portal namespace]]. See also [[:Category:Redirects to portal namespace]]
A more complete list is available at {{Section link|Wikipedia:Shortcut#List of prefixes}}.
Pseudo-namespaces are not in any way recognised by the wiki software; they are purely a community custom. Titles in pseudo-namespaces actually belong technically in the main (article) namespace and are treated as such by the software: they are case-sensitive and appear in [[Help:Search#Syntax|search results]] restricted to the main namespace. An alias is treated like a real namespace, resulting in a search for the [[WP:page name|pagename]] in its namespace, but the "pseudo-namespace:pagename" search is in mainspace, not its pseudo-namespace. For example, searching for "H:S" will not search '''Help'''.
To learn some of these shortcuts, first follow the pseudo-namespace link above, then follow one of the redirects listed on that page. It will take you to the target, where you then notice any {{tl|shortcut}} boxes to the right of the page, which may also list some additional shortcuts to that same area. By observing these steps repeatedly, you can discover ways to shorten your typing. You will use pseudo-namespace names more often if you are an advanced editor, highly active in many namespaces, or constantly linking to pages that have a pseudo-namespace shortcut.
To understand the appropriateness of redirects of this type, see [[Wikipedia:Cross-namespace redirects]]. All shortcuts are discoverable by [[Help:Searching|searching]] for redirects. There is also the category [[:Category:Wikipedia redirects|Wikipedia redirects]].
As a final example, every [[Wikimedia Foundation]] project has a "[[m:Help:Transwiki|Transwiki:]]" pseudo-namespace (sometimes a real namespace) for importing articles manually. A wiki project that would manually move many pages between [[wp:sister|sister projects]] uses this tag. Redirects/shortcuts are not directly involved here, as described above. Instead, the page title is [[WP:move|move]]d to "Transwiki:''namespace:pagename''", and that content is then copied and pasted into a new page name of that temporary title on the target wiki. When it is accepted, the title is then moved out of the '''Transwiki''' pseudo-namespace there and becomes a real page name in its respective namespace.
==<span id="Interwiki links"></span>Interwiki and interlanguage links ==
{{see|Help:Interwiki linking|Help:Interlanguage links}}
[[m:Table of Wikimedia projects|Interwiki]] and [[m:List of Wikipedias|interlanguage]] prefixes do not define namespaces, but point to pages in other Wikimedia projects, outside the en.wikipedia.org website. They are mentioned here because they use a namespace-like prefix technique for linking. Examples of interwiki prefixes include '''w:''' for Wikipedia; '''m:''' (or '''meta:''') for [[Meta-Wiki]], '''mw:''' for [[MediaWiki]], and '''wikt:''' for [[Wiktionary]]. Examples of interlanguage prefixes include '''en:''' for English language, '''fr:''' for French language, and '''de:''' for German language.
Important points to note:
* In the presence of an interwiki prefix and the absence of an interlanguage prefix, the link will be to a specified project in the current language. So <code><nowiki>[[w:Internet]]</nowiki></code> links to "[[w:Internet|Internet]]" on the English Wikipedia, if the link is on any English-language Wikimedia project.
* In the presence of an interlanguage prefix and the absence of an interwiki prefix, the link will be to a specified language in the current project. So <code><nowiki>[[:en:Internet]]</nowiki></code> will link to "[[:en:Internet|Internet]]" on the English Wikipedia, if the link is on a Wikipedia project in any language.
When making links to other language Wikipedias, add an initial colon if you want the link to appear inline rather than in the skin's sidebar under "Languages"; see [[Help:Colon trick]] for an explanation. So <code><nowiki>[[:de:Internet]]</nowiki></code> is an inline link to "[[:de:Internet|Internet]]" in the German Wikipedia; but if using an interwiki prefix this is unnecessary, for example <code><nowiki>[[w:de:Internet]]</nowiki></code> is the same inline link.
Further examples:
* [[m:Meta:Babel]] and [[meta:Meta:Babel]] both link to the "Babel" page in the project namespace (Meta:, the 2nd prefix) of Meta-Wiki (m: or meta:, the 1st prefix).
* [[wikt:fr:Discuter:pied/fusion daf]] links to the "pied/fusion daf" page in the talk namespace (Discuter:, the 3rd prefix) of French (fr:, the 2nd prefix) Wiktionary (wikt:, the 1st prefix).
Interwiki prefixes are not just for Wikimedia projects. For example, [[google:]] is the interwiki link for [[Google]]. For a complete list of interwiki prefixes, see the [[m:Interwiki map|interwiki map]] and [[m:Special:Interwiki|interwiki table]].
As with aliases, it is not possible to create a page with a title beginning with an interwiki or interlanguage prefix. It is also not possible to create redirects to interwiki pages, unless it is a [[Wikipedia:Soft redirect|soft redirect]].
== Case insensitivity ==
Standard namespace names, aliases and interwiki prefixes are case insensitive. The same applies to the first character after the colon. Hence the following all link to the same page:
* [[Wikipedia:Afd]], [[WIKIPEDIA:Afd]], [[wIKIpedia:Afd]], [[wikipedia:afd]]
* [[wP:Afd]], [[wp:Afd]], [[WP:afd]]
* [[PROJECT:Afd]], [[project:Afd]], [[ProjecT:Afd]], [[Project:afd]]
== Namespace-dependent functionality ==
The namespace name is a useful variable for searching in and reporting on sets of [[WP:Page name|pages]]. It is also used to apply features that configure the sets of pages in one namespace differently from another namespace. Using the namespace name MediaWiki can:
*[[WP:Search|Search]] for pages in a particular namespace only.
* [[Help:Special page|Report]] on [[Special:AllPages|content]] or [[WP:Recent changes|changes in content]] of a namespace.
* Enable or disable the [[WP:Subpage|subpage]] feature, per namespace.
* Offer a [[WP:Random article|random article]] for the mainspace (<kbd><nowiki>[[</nowiki>Special:Random<nowiki>]]</nowiki></kbd>), or for a namespace <kbd><nowiki>[[</nowiki>Special:Random/''Namespace'']]</kbd>.
* Change the functionality of <kbd><nowiki>[[</nowiki>''wikilink''<nowiki>]]</nowiki></kbd> if it targets the '''Category''' namespace or '''File''' namespace. Normally wikilinks are activated by the mouse, but <kbd><nowiki>[[</nowiki>Category:''Pagename''<nowiki>]]</nowiki></kbd> activates software functionality when the [[WP:Category|page is saved]], and <kbd><nowiki>[[</nowiki>File:''Page name''<nowiki>]]</nowiki></kbd> activates software functionality when the [[WP:Image|page is rendered]].
* Change the functionality of <kbd><nowiki>{{</nowiki>[[WP:Transclusion|pagename]]<nowiki>}}</nowiki></kbd> so that it defaults to the set of pagenames in '''Template'''.
* Tailor ''[[Wikipedia:Edit notices|edit notices]]'' to a particular namespace's edit page, informing an editor of certain aspects about the content of that namespace.
* Allow ''[[Wikipedia:Templates|templates]]'' to behave differently on pages of different namespaces.
The namespace functionality is often visible in the URL, where you will see a namespace number. These are given in the table below.
Subpages are configured for all namespaces except Main, File, MediaWiki and Category namespaces. Subpages are configured in the software by enabling or disabling the subpage feature per namespace. This further extends the function of a namespace by extending the types of pages or topics of pages a namespace can home. For example, talk page ''/archives'' are subpages, and they are both namespace searchable and page name searchable from the search box, unlike [[WP:page history|history pages]], which are in no namespace. Another example is in the Template namespace where it is routine to put the documentation in a subpage called ''/doc''.
Random pages are enabled, in the default software configuration, only for the mainspace.
Searching and reporting can operate over the entire database, or they can be limited to a namespace, and so they will offer a list of all the namespaces currently configured. [[Special:WhatLinksHere]] also offers a list of namespaces.
== <span class="anchor" id="Enumeration"></span> Programming ==
The 30 namespaces in the English Wikipedia are numbered for programming purposes. The prefix for each namespace is generated using the [[Help:Magic words#Paths|magic word]] <syntaxhighlight lang=wikitext inline>{{ns}}</syntaxhighlight>, in the form <syntaxhighlight lang=wikitext inline>{{ns:xx}}</syntaxhighlight>, as shown in the table below.
{| border="0" cellpadding="4" cellspacing="0" class="wikitable"
|-
!Namespace variable
!Result (namespace name)
!Namespace variable
!Result (talk namespace name)
|-
|<syntaxhighlight lang=wikitext inline>{{ns:-2}}</syntaxhighlight>
|{{ns:-2}}
|
|
|-
|<syntaxhighlight lang=wikitext inline>{{ns:-1}}</syntaxhighlight>
|{{ns:-1}}
|
|
|-
|<syntaxhighlight lang=wikitext inline>{{ns:0}}</syntaxhighlight>
|{{ns:0}} (main namespace, returns empty string)
|<syntaxhighlight lang=wikitext inline>{{ns:1}}</syntaxhighlight>
|{{ns:1}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:2}}</syntaxhighlight>
|{{ns:2}}
|<syntaxhighlight lang=wikitext inline>{{ns:3}}</syntaxhighlight>
|{{ns:3}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:4}}</syntaxhighlight>
|{{ns:4}}
|<syntaxhighlight lang=wikitext inline>{{ns:5}}</syntaxhighlight>
|{{ns:5}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:6}}</syntaxhighlight>
|{{ns:6}}
|<syntaxhighlight lang=wikitext inline>{{ns:7}}</syntaxhighlight>
|{{ns:7}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:8}}</syntaxhighlight>
|{{ns:8}}
|<syntaxhighlight lang=wikitext inline>{{ns:9}}</syntaxhighlight>
|{{ns:9}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:10}}</syntaxhighlight>
|{{ns:10}}
|<syntaxhighlight lang=wikitext inline>{{ns:11}}</syntaxhighlight>
|{{ns:11}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:12}}</syntaxhighlight>
|{{ns:12}}
|<syntaxhighlight lang=wikitext inline>{{ns:13}}</syntaxhighlight>
|{{ns:13}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:14}}</syntaxhighlight>
|{{ns:14}}
|<syntaxhighlight lang=wikitext inline>{{ns:15}}</syntaxhighlight>
|{{ns:15}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:100}}</syntaxhighlight>
|{{ns:100}}
|<syntaxhighlight lang=wikitext inline>{{ns:101}}</syntaxhighlight>
|{{ns:101}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:118}}</syntaxhighlight>
|{{ns:118}}
|<syntaxhighlight lang=wikitext inline>{{ns:119}}</syntaxhighlight>
|{{ns:119}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:126}}</syntaxhighlight>
|{{ns:126}}
|<syntaxhighlight lang=wikitext inline>{{ns:127}}</syntaxhighlight>
|{{ns:127}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:710}}</syntaxhighlight>
|{{ns:710}}
|<syntaxhighlight lang=wikitext inline>{{ns:711}}</syntaxhighlight>
|{{ns:711}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:828}}</syntaxhighlight>
|{{ns:828}}
|<syntaxhighlight lang=wikitext inline>{{ns:829}}</syntaxhighlight>
|{{ns:829}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:1728}}</syntaxhighlight>
|{{ns:1728}}
|<syntaxhighlight lang=wikitext inline>{{ns:1729}}</syntaxhighlight>
|{{ns:1729}}
|}
Alternative variables are available for most namespaces, for example <syntaxhighlight lang=wikitext inline>{{ns:talk}}</syntaxhighlight>, <syntaxhighlight lang=wikitext inline>{{ns:user}}</syntaxhighlight>, and <syntaxhighlight lang=wikitext inline>{{ns:user_talk}}</syntaxhighlight> for <syntaxhighlight lang=wikitext inline>{{ns:1}}</syntaxhighlight>, <syntaxhighlight lang=wikitext inline>{{ns:2}}</syntaxhighlight> and <syntaxhighlight lang=wikitext inline>{{ns:3}}</syntaxhighlight>. The portal namespace is numbered in the 100-plus range, as are all MediaWiki nonstandard namespaces. It is also possible to use {{tl|Namespace name}} for this, i.e. "<syntaxhighlight lang=wikitext inline>{{Namespace name|711}}</syntaxhighlight>" produces "{{Namespace name|711}}".
All namespaces with a positive number or zero in this list are searchable. Specifically, the {{ns:-2}} and {{ns:-1}} namespaces are not searchable.
The [[Help:Magic words|magic word]] <syntaxhighlight lang=wikitext inline>{{NAMESPACE}}</syntaxhighlight> returns the namespace prefix of the current page. This can be used in combination with other magic words and [[meta:Help:ParserFunctions|parser functions]] to change the appearance of [[WP:Template|templates]] depending on the namespace in which they are transcluded.
Meta-templates have been created to simplify this process. These include the simple template {{tl|main other}}, and the more complex and versatile {{tl|namespace detect}}.
For information on changing the appearance of a page or template by namespace based on CSS, see '''CSS''' section of [[mw:Help:Namespaces#Identifying namespaces|Identifying namespaces]] on the MediaWiki help page.
== See also ==
{{Help desk}}
* [[Wikipedia:Page name]]
* [[Wikipedia:Controlling search engine indexing]]
* [[mw:Help:Namespaces|MediaWiki help page on namespaces]], for general MediaWiki technical information
* [[mw:Extension default namespaces]], for namespaces added by extensions
* [[Special:NamespaceInfo]] - automated listing of information for configured namespaces
== References ==
{{reflist}}
{{Wikipedia technical help|collapsed}}
[[Category:Wikipedia features]]
[[Category:Wikipedia namespace administration| ]]
43kmj91411x9t412ztruprllz6bxqtb
9336
9335
2026-08-23T08:17:44Z
RAPTOR7762
18
1 revision imported from [[:en:Wikipedia:Namespace]]
9335
wikitext
text/x-wiki
{{Short description|Prefix before a Wikipedia page's name}}
{{redirect-distinguish|WP:NS|Wikipedia:WikiProject Nova Scotia}}
{{redirect-distinguish|WP:NSPACE|Wikipedia:Notability (astronomical objects)}}
{{pp-semi-vandalism|small=yes}}{{pp-move-indef}}
{{Infopage|WP:NS|WP:NSPACE}}
{{Namespaces}}
A Wikipedia '''namespace''' is a set of Wikipedia pages whose [[Help:page name|names]] begin with a reserved word, followed by a colon. The reserved word is recognized by the [[MediaWiki]] software. For example, in the ''user namespace'' all titles begin with the prefix ''User:''. In the case of the article (or main) namespace, in which encyclopedia articles appear, the reserved word and colon are absent. (Note: main space articles can optionally include a colon at the beginning with no reserved word, so <code>[<nowiki/>[Article]]</code> and <code>[<nowiki/>[:Article]]</code> are equivalent. This is usually only necessary for the advanced technique of [[WP:Transclusion|transcluding]] a main space article into a page in another namespace.)
More generally, a Wikipedia '''namespace''' is a class of pages that falls under a common type. All pages in the <code>User</code> namespace, for example, are [[Wikipedia:User pages|user pages]], whereas [[WP:Drafts|Drafts]] are in the <code>Draft</code> namespace. This page is in the <code>[[WP:Project namespace|Wikipedia]]</code> namespace, for information or discussions about the project itself and its policies.
Wikipedia has 30 current namespaces: 14 subject namespaces, 14 corresponding talk namespaces, and 2 virtual namespaces. These are all listed in the box to the right. While surfing Wikipedia, a list of namespaces is available in two clicks: do an empty search, then click ''Advanced'' under the search box. The list also makes itself available where needed in the dropdown menus of, for example, [[Special:PrefixIndex]], [[Special:AllPages]], [[Special:RecentChanges]], and [[Special:Contributions]].
The aliases '''WP''' for '''Wikipedia''', and '''WT''' for '''Wikipedia talk''', work for page names in the search box, and making links as well as inclusions. See [[#Aliases|Aliases]] below for other aliases. (The pseudo-namespaces such as '''H''' for '''Help''', and '''CAT''' for '''Category''', are extremely limited. See ''[[#Pseudo-namespaces|Pseudo-namespaces]]'' below.)
The table on the right shows what number to use when you want to hide pages that are on your watchlist. See: [[Wikipedia:Hide Pages in Watchlist]] for details.
== Subject namespaces ==
{{see|Wikipedia:Administration#Data structure and development}}
[[File:Policies and guidelines indicator.png|thumb|350px|This page is in the [[Wikipedia:Project namespace|Wikipedia namespace]].]]
Namespaces allow for the organization and separation of [[Wikipedia:Administration#Content namespaces|content pages]] from [[Wikipedia:Administration#Administrative namespaces|administration pages]]. Namespaces separate data into core sets, those intended for public viewing, and those intended for the editing community. Wikipedia's subject namespaces and their functions are listed below. A brief description is provided, but see the link for more information.
{{anchor|subjectpage}}A namespace is sometimes called a ''space'', for short, as in "Project space". A ''subject page'' and its ''talk page'' form a pair.
<!--
in order of {{NAMESPACENUMBER}}
-->
===Current namespaces===
* '''[[Wikipedia:Main namespace|Main namespace]]''' (no prefix): contains all encyclopedia articles, lists, [[Wikipedia:Disambiguation|disambiguation pages]], and encyclopedia [[Wikipedia:Redirect|redirects]]. Sometimes referred to as "mainspace" or "Article".
* '''[[Wikipedia:User namespace|User namespace]]''' (prefix '''User:'''): contains user pages and other pages created by individual users for their own personal use. Pages under this namespace can still be viewed and modified by others, so do not keep any of your sensitive data here.
* '''[[Wikipedia:Wikipedia namespace|Wikipedia namespace]]''' or '''[[Wikipedia:Project namespace|Project namespace]]''' (prefix '''Wikipedia:'''): contains many types of pages connected with the Wikipedia project itself: information, policies, guidelines, essays, processes, discussion, etc. [[Wikipedia:Namespace#Aliases|Namespace aliases]]: '''WP:''' or '''Project:'''
*{{anchor|File|File namespace}}'''[[Wikipedia:File namespace|File namespace]]''' (prefix '''File:'''): contains [[Help:File description page|description pages for media files]] (images, videos, and audio files). A link starting with <code><nowiki>[[File:</nowiki></code> will display the media at that position on the page instead of showing a wikilink that leads to the specified file description page, so if you want the latter effect, use a link beginning with <code><nowiki>[[:File:</nowiki></code> (the [[Help:Colon trick|colon trick]]). Namespace alias: '''Image:'''
* '''[[Help:MediaWiki namespace|MediaWiki namespace]]''' (prefix '''MediaWiki:'''): a namespace containing interface texts, such as the links and messages that appear on automatically generated pages. Pages in this namespace are permanently [[Wikipedia:Protection policy|protected]] against editing by regular users. For a list of these messages, see [[Special:AllMessages]]. (The prefix ''cannot'' be shortened to "MW" because '''mw''' is an interwiki prefix. See ''[[#Interwiki links|Interwiki links]]'' below.)
* '''[[Wikipedia:Template namespace|Template namespace]]''' (prefix '''Template:'''): contains templates – pages that are intended primarily to be [[Wikipedia:Transclusion|transcluded]] or [[Wikipedia:Substitution|substituted]] onto other pages to insert standard text or boxes such as infoboxes and navigation boxes. [[Wikipedia:Namespace#Aliases|Namespace alias]]: '''TM:'''
* '''[[WP:Help namespace|Help namespace]]''' (prefix '''Help:'''): contains pages which provide help in using Wikipedia and its software, both for users of the encyclopedia and for editors.
* '''[[Wikipedia:Category namespace|Category namespace]]''' (prefix '''Category:'''): contains category pages, which are curated lists of related pages and subcategories, along with optional additional text. A link beginning with <code><nowiki>[[Category:</nowiki></code> has the effect of adding the page the link appears on to the specified category; it will not result in a wikilink to the category page itself. If you want the latter, use the [[Help:Colon trick|colon trick]]: <code><nowiki>[[:Category:</nowiki></code>.
* '''[[Wikipedia:Portal namespace|Portal namespace]]''' (prefix '''Portal:'''): for reader-oriented portals that help readers find articles related to a specific topic, and may contain links to encourage contributions to relevant [[Wikipedia:WikiProject|WikiProjects]]. See, for example, [[Portal:Cricket]] and [[Portal:Spaceflight]].
* '''[[Wikipedia:Draft namespace|Draft namespace]]''' (prefix '''Draft:'''): hosts drafts of new (potential) Wikipedia articles.
* '''[[mw:Extension:TimedMediaHandler|TimedText namespace]]''' (prefix '''TimedText:'''): synchronized subtitles for media files.
* '''[[Wikipedia:Module namespace|Module namespace]]''' (prefix '''Module:'''): contains [[mw:Extension:Scribunto|Scribunto]] modules – Lua scripts implementing special-purpose [[mw:Manual:Parser functions|parser functions]] for use in templates, beyond the [[Help:Magic words#Parser functions|basic set]] included with MediaWiki and its [[mw:Extensions FAQ|extensions]].
* {{anchor|MOS}}'''[[WP:Manual of Style|MOS namespace]]''' (prefix '''MOS:'''): contains redirects to subpages of [[WP:Manual of Style]]. Until 2024 this was a pseudo-namespace, but it was turned into a real namespace in 2024 to avoid conflicts with the [[Mooré]] Wikipedia (with the language code <code>mos:</code>).<ref>[[phab:T363538]]</ref>
* '''[[Event:Sandbox|Event namespace]]''' (prefix '''Event:''') contains [[mw:Extension:CampaignEvents]] events.
===Former namespaces===
The following namespaces previously existed but no longer do:
*'''[[Wikipedia:Flow|Flow namespace]]''' (prefix '''Topic:''') was a proposed talk page replacement, formerly installed on English Wikipedia by [[mw:Extension:StructuredDiscussions|Extension:StructuredDiscussions]]. It is no longer installed after being rejected by the community.
* '''[[Wikipedia:Course pages|Education Program namespace]]''' (prefix '''Education Program:'''): uninstalled in 2018, and replaced with the [[wmfdashboard:|Programs & Events Dashboard]].<ref>[[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]], Wikimedia outreach</ref><ref>{{Section link|Wikipedia:Education noticeboard/Archive 18#NOTICE:_EducationProgram extension is being deprecated}}</ref> However, the namespace was re-added later that year to allow access to old talk pages in the Education program talk: namespace. The namespace was then uninstalled again in 2021 after the remaining talk pages were moved to subpages of [[Wikipedia talk:Education program archive]].
* '''[[Wikipedia:Books|Book namespace]]''' (prefix '''Book:'''): contained entries for Wikipedia books, collections of articles about one theme, which were used to generate downloadable files or printable documents or order books from PediaPress. In 2017, the online book rendering service was withdrawn, leading to the removal of most links leading to the namespace in 2019. The namespace and its transclusions were still retained in the hope that the WMF would come up with a solution,<ref>{{Section link|Wikipedia:Village pump (technical)/Archive 176|Suppress rendering of Template:Wikipedia books}}</ref> but in 2021 the namespace was uninstalled after all remaining books were moved to subpages of [[Wikipedia:Books/archive]].
* '''Gadget namespace''' (prefix '''Gadget:'''):<ref>{{Section link|Wikipedia:Village pump (technical)/Archive 139#New "Gadget:" and "Gadget definition:" namespaces?}}</ref> was intended to store [[Wikipedia:Gadget|Gadgets]], which are small [[Snippet (programming)|snippets]] enabled in [[Special:Preferences#mw-prefsection-gadgets|user preferences]], but was never used for anything other than redirects to the video game ''[[Gadget: Invention, Travel, & Adventure]]'', and for most of its existence could only be edited by WMF staff. Gadgets currently use the [[Help:MediaWiki namespace|MediaWiki namespace]] with the ''MediaWiki:Gadget-'' page name prefix. It was a [[mw:Manual:Using custom namespaces|custom namespace]] installed by the [[mw:Extension:Gadgets|Gadget extension]].
* '''Gadget definition namespace''' (prefix '''Gadget definition:'''): installed but never used; see above for more information. Gadget definitions currently use the [[MediaWiki:Gadgets-definition]] page.
===Aliases and pseudo-namespaces===
{{redirect|Wikipedia:Alias|template parameter aliases|Help:Template#Handling parameters}}
An ''alias'' of a namespace is its namespace. For example, '''WP:''' is '''Wikipedia:''', and so
<code><nowiki>[[</nowiki>Wikipedia:[[WP:Page name|''Page name'']]]]</code> can be abbreviated <code><nowiki>[[WP:</nowiki>[[WP:Page name|''Page name'']]]]</code>.
See ''[[#Aliases|Aliases]]'' below, for a list of aliases, such as '''WT:''' for '''Wikipedia talk:'''.
A ''pseudo-namespace'' is an agreement to create redirect pages named that way, each of which
is a shortcut from mainspace to ''a single page in its namespace''.
So an alias refers to ''any page in its namespace'', but a pseudo-namespace has far fewer pages than its real namespace.
There are a few pseudo-namespace names like '''H:''' for '''Help:''', and '''CAT:''' for '''Category:''', and these can be discovered below in the section ''[[#Pseudo-namespaces|Pseudo-namespaces]]''.
== <span id="Talk"></span><span id="Wikipedia talk"></span><span id="WT"></span> Talk namespaces==
{{shortcut|WP:TALKSPACE}}
{{main|Help:Using talk pages|Wikipedia:Talk page guidelines}}
Each of the above namespaces (but not the virtual namespaces and the former Topic: namespace) has an associated [[help:talk page|talk namespace]]—these are also known as ''discussion pages''. The talk namespaces are designated by appending the word <code>talk</code> to the namespace name. For example, the talk namespace associated with the user namespace has the prefix '''User talk:'''. The talk namespace associated with the article namespace is '''Talk:'''.
Most of the pages in the talk namespaces are used to discuss changes to the corresponding page in the associated namespace. Pages in the ''user talk'' namespace are used to leave messages for a particular user. The user talk namespace is special in that, whenever a user's talk page is edited, that user will see an orange box saying "You have new messages" on the top of every page that they view until they visit their talk page. By default, logged-in users will see [[Wikipedia:Notifications|a red notification square]] ''and'' a small orange box on the top right hand corner of the page; IP users will only see a wide orange box spanning the top of the page. (Minor edits made by [[Wikipedia:Bot policy|bots]] no longer set off the new message bar. For logged-in users, the new-message bar may be disabled in [[Special:Preferences]].)
Note that the prefix '''WT:''' expands to '''Wikipedia talk:''', just as '''WP:''' expands to '''Wikipedia:''' (see [[#Aliases|Aliases]] below). For example, <nowiki>[[WT:Verifiability]]</nowiki> links to [[Wikipedia talk:Verifiability]].
== Virtual namespaces<span id="Special"></span> ==
In addition to subject namespaces and their corresponding talk pages, there are two virtual namespaces (without corresponding talk pages) for specialist purposes:
=== Special ===
{{Main|Help:Special page}}
The ''Special:'' namespace consists of pages (called ''special pages'') that are created by the software on demand, such as [[Special:RecentChanges]]. These pages can be linked as usual, as with <nowiki>[[Special:RecentChanges]]</nowiki>, except when they have parameters. To use parameters, the full URL must be given as an external link. For example, https:{{SERVER}}{{SCRIPTPATH}}/index.php?title=Special:Recentchanges&days=3&limit=10, which returns the last ten changes in the last three days.
You can create a [[Wikipedia:redirect|redirect]] to a Special page, but the redirect will not be followed automatically.
For a list of special pages, see [[Special:SpecialPages]].
=== Media<span class="anchor" id="Media namespace"></span> ===
{{Main|Help:Files}}
The ''Media:'' namespace can be used to link directly to a file, rather than to the file description page.
== Aliases and pseudo-namespaces==
{{See|Wikipedia:Shortcut#List of prefixes}}
Aliases and pseudo-namespaces are not namespaces in themselves; their main role is to provide handy ways to link to actual namespaces, by providing shortened links.
The main difference between them being the way they work for this purpose; while aliases directly link to namespaces, pseudo-namespaces can only link to other namespaces by using specialist [[Wikipedia:Redirect|redirect pages]] in the main namespace called [[Wikipedia:Shortcut|shortcuts]]. While aliases are also used for shortcuts, this isn't necessary if the pagename is not shortened.
Pseudo-namespaces all actually reside in main namespace; but a pseudo-namespace called [[m:Help:Transwiki|Transwiki:]] exists as a pseudo-namespace before being moved to another namespace.
=== Aliases ===
{{Shortcut|WP:ALIAS}}
There are seven aliases defined for namespaces, all of which are case-insensitive:
{| class=wikitable
!Namespace
!Alias
|-
| rowspan="2" |Wikipedia
|WP
|-
|Project
|-
| rowspan="2" |Wikipedia talk
|WT
|-
|Project talk
|-
|File
|Image
|-
|File talk
|Image talk
|-
|Template
|TM
|}
These aliases are automatically translated by the Wikipedia servers to the proper namespace prefix. So if a link is made to a page title beginning with one of these aliases, or else entered in the search box or used in a URL in a browser address bar, the alias links to the page with the corresponding true namespace prefix. Hence entering [[WP:External links]] or [[Project:External links]] is equivalent to entering [[Wikipedia:External links]]; and entering [[WT:External links]] or [[Project talk:External links]] is equivalent to entering [[Wikipedia talk:External links]].
An alias cannot be used as the actual namespace in a page title. For example, you cannot create page ''WP:123''; if tried, the page name is instantly converted to ''Wikipedia:123''. It ''is'', however, possible to [[Wikipedia:Page name#Changing the displayed title|change the ''displayed'' title]] on page ''Wikipedia:123'' to make it ''WP:123'' or ''Project:123''.
<span class="plainlinks">This is very handy for the creation of [[Wikipedia:Shortcut|shortcuts]]. For example, the shortcut for this section is [[WP:ALIAS]], as shown in the right-side box. When the link is clicked, it is automatically translated to [https://en.wikipedia.org/w/index.php?title=Wikipedia:ALIAS&redirect=no Wikipedia:ALIAS]. At this page is a [[Help:Redirect|redirect]] to {{Section link|Wikipedia:Namespace#Aliases}}. This means that the shortcut goes directly to this section from anywhere on Wikipedia. It can also be entered as a [[URL]] in the browser address bar as https://en.wikipedia.org/wiki/WP:ALIAS .</span>
=== Pseudo-namespaces ===
<!-- This section is linked from [[Wikipedia:Glossary]] -->
{{Shortcut|WP:PNS}}
Apart from Wikipedia's 24 regular namespaces and their aliases, and 2 virtual ones, there are several title prefixes appearing in [[Help:Shortcut|shortcut redirects]] pointing to frequently-referred-to Wikipedia pages. These prefixes are referred to as '''pseudo-namespaces''' and include the following:
* '''[[Special:Prefixindex/CAT:|CAT:]]''' for shortcuts to the [[Wikipedia:Category namespace|Category namespace]]. See also [[:Category:Redirects to category space]]
* '''[[Special:Prefixindex/H:|H:]]''' for shortcuts to the [[Wikipedia:Help namespace|Help namespace]]. See also [[:Category:Redirects to help namespace]]
* '''[[Special:Prefixindex/P:|P:]]''' for shortcuts to the [[Wikipedia:Portal namespace|Portal namespace]]. See also [[:Category:Redirects to portal namespace]]
A more complete list is available at {{Section link|Wikipedia:Shortcut#List of prefixes}}.
Pseudo-namespaces are not in any way recognised by the wiki software; they are purely a community custom. Titles in pseudo-namespaces actually belong technically in the main (article) namespace and are treated as such by the software: they are case-sensitive and appear in [[Help:Search#Syntax|search results]] restricted to the main namespace. An alias is treated like a real namespace, resulting in a search for the [[WP:page name|pagename]] in its namespace, but the "pseudo-namespace:pagename" search is in mainspace, not its pseudo-namespace. For example, searching for "H:S" will not search '''Help'''.
To learn some of these shortcuts, first follow the pseudo-namespace link above, then follow one of the redirects listed on that page. It will take you to the target, where you then notice any {{tl|shortcut}} boxes to the right of the page, which may also list some additional shortcuts to that same area. By observing these steps repeatedly, you can discover ways to shorten your typing. You will use pseudo-namespace names more often if you are an advanced editor, highly active in many namespaces, or constantly linking to pages that have a pseudo-namespace shortcut.
To understand the appropriateness of redirects of this type, see [[Wikipedia:Cross-namespace redirects]]. All shortcuts are discoverable by [[Help:Searching|searching]] for redirects. There is also the category [[:Category:Wikipedia redirects|Wikipedia redirects]].
As a final example, every [[Wikimedia Foundation]] project has a "[[m:Help:Transwiki|Transwiki:]]" pseudo-namespace (sometimes a real namespace) for importing articles manually. A wiki project that would manually move many pages between [[wp:sister|sister projects]] uses this tag. Redirects/shortcuts are not directly involved here, as described above. Instead, the page title is [[WP:move|move]]d to "Transwiki:''namespace:pagename''", and that content is then copied and pasted into a new page name of that temporary title on the target wiki. When it is accepted, the title is then moved out of the '''Transwiki''' pseudo-namespace there and becomes a real page name in its respective namespace.
==<span id="Interwiki links"></span>Interwiki and interlanguage links ==
{{see|Help:Interwiki linking|Help:Interlanguage links}}
[[m:Table of Wikimedia projects|Interwiki]] and [[m:List of Wikipedias|interlanguage]] prefixes do not define namespaces, but point to pages in other Wikimedia projects, outside the en.wikipedia.org website. They are mentioned here because they use a namespace-like prefix technique for linking. Examples of interwiki prefixes include '''w:''' for Wikipedia; '''m:''' (or '''meta:''') for [[Meta-Wiki]], '''mw:''' for [[MediaWiki]], and '''wikt:''' for [[Wiktionary]]. Examples of interlanguage prefixes include '''en:''' for English language, '''fr:''' for French language, and '''de:''' for German language.
Important points to note:
* In the presence of an interwiki prefix and the absence of an interlanguage prefix, the link will be to a specified project in the current language. So <code><nowiki>[[w:Internet]]</nowiki></code> links to "[[w:Internet|Internet]]" on the English Wikipedia, if the link is on any English-language Wikimedia project.
* In the presence of an interlanguage prefix and the absence of an interwiki prefix, the link will be to a specified language in the current project. So <code><nowiki>[[:en:Internet]]</nowiki></code> will link to "[[:en:Internet|Internet]]" on the English Wikipedia, if the link is on a Wikipedia project in any language.
When making links to other language Wikipedias, add an initial colon if you want the link to appear inline rather than in the skin's sidebar under "Languages"; see [[Help:Colon trick]] for an explanation. So <code><nowiki>[[:de:Internet]]</nowiki></code> is an inline link to "[[:de:Internet|Internet]]" in the German Wikipedia; but if using an interwiki prefix this is unnecessary, for example <code><nowiki>[[w:de:Internet]]</nowiki></code> is the same inline link.
Further examples:
* [[m:Meta:Babel]] and [[meta:Meta:Babel]] both link to the "Babel" page in the project namespace (Meta:, the 2nd prefix) of Meta-Wiki (m: or meta:, the 1st prefix).
* [[wikt:fr:Discuter:pied/fusion daf]] links to the "pied/fusion daf" page in the talk namespace (Discuter:, the 3rd prefix) of French (fr:, the 2nd prefix) Wiktionary (wikt:, the 1st prefix).
Interwiki prefixes are not just for Wikimedia projects. For example, [[google:]] is the interwiki link for [[Google]]. For a complete list of interwiki prefixes, see the [[m:Interwiki map|interwiki map]] and [[m:Special:Interwiki|interwiki table]].
As with aliases, it is not possible to create a page with a title beginning with an interwiki or interlanguage prefix. It is also not possible to create redirects to interwiki pages, unless it is a [[Wikipedia:Soft redirect|soft redirect]].
== Case insensitivity ==
Standard namespace names, aliases and interwiki prefixes are case insensitive. The same applies to the first character after the colon. Hence the following all link to the same page:
* [[Wikipedia:Afd]], [[WIKIPEDIA:Afd]], [[wIKIpedia:Afd]], [[wikipedia:afd]]
* [[wP:Afd]], [[wp:Afd]], [[WP:afd]]
* [[PROJECT:Afd]], [[project:Afd]], [[ProjecT:Afd]], [[Project:afd]]
== Namespace-dependent functionality ==
The namespace name is a useful variable for searching in and reporting on sets of [[WP:Page name|pages]]. It is also used to apply features that configure the sets of pages in one namespace differently from another namespace. Using the namespace name MediaWiki can:
*[[WP:Search|Search]] for pages in a particular namespace only.
* [[Help:Special page|Report]] on [[Special:AllPages|content]] or [[WP:Recent changes|changes in content]] of a namespace.
* Enable or disable the [[WP:Subpage|subpage]] feature, per namespace.
* Offer a [[WP:Random article|random article]] for the mainspace (<kbd><nowiki>[[</nowiki>Special:Random<nowiki>]]</nowiki></kbd>), or for a namespace <kbd><nowiki>[[</nowiki>Special:Random/''Namespace'']]</kbd>.
* Change the functionality of <kbd><nowiki>[[</nowiki>''wikilink''<nowiki>]]</nowiki></kbd> if it targets the '''Category''' namespace or '''File''' namespace. Normally wikilinks are activated by the mouse, but <kbd><nowiki>[[</nowiki>Category:''Pagename''<nowiki>]]</nowiki></kbd> activates software functionality when the [[WP:Category|page is saved]], and <kbd><nowiki>[[</nowiki>File:''Page name''<nowiki>]]</nowiki></kbd> activates software functionality when the [[WP:Image|page is rendered]].
* Change the functionality of <kbd><nowiki>{{</nowiki>[[WP:Transclusion|pagename]]<nowiki>}}</nowiki></kbd> so that it defaults to the set of pagenames in '''Template'''.
* Tailor ''[[Wikipedia:Edit notices|edit notices]]'' to a particular namespace's edit page, informing an editor of certain aspects about the content of that namespace.
* Allow ''[[Wikipedia:Templates|templates]]'' to behave differently on pages of different namespaces.
The namespace functionality is often visible in the URL, where you will see a namespace number. These are given in the table below.
Subpages are configured for all namespaces except Main, File, MediaWiki and Category namespaces. Subpages are configured in the software by enabling or disabling the subpage feature per namespace. This further extends the function of a namespace by extending the types of pages or topics of pages a namespace can home. For example, talk page ''/archives'' are subpages, and they are both namespace searchable and page name searchable from the search box, unlike [[WP:page history|history pages]], which are in no namespace. Another example is in the Template namespace where it is routine to put the documentation in a subpage called ''/doc''.
Random pages are enabled, in the default software configuration, only for the mainspace.
Searching and reporting can operate over the entire database, or they can be limited to a namespace, and so they will offer a list of all the namespaces currently configured. [[Special:WhatLinksHere]] also offers a list of namespaces.
== <span class="anchor" id="Enumeration"></span> Programming ==
The 30 namespaces in the English Wikipedia are numbered for programming purposes. The prefix for each namespace is generated using the [[Help:Magic words#Paths|magic word]] <syntaxhighlight lang=wikitext inline>{{ns}}</syntaxhighlight>, in the form <syntaxhighlight lang=wikitext inline>{{ns:xx}}</syntaxhighlight>, as shown in the table below.
{| border="0" cellpadding="4" cellspacing="0" class="wikitable"
|-
!Namespace variable
!Result (namespace name)
!Namespace variable
!Result (talk namespace name)
|-
|<syntaxhighlight lang=wikitext inline>{{ns:-2}}</syntaxhighlight>
|{{ns:-2}}
|
|
|-
|<syntaxhighlight lang=wikitext inline>{{ns:-1}}</syntaxhighlight>
|{{ns:-1}}
|
|
|-
|<syntaxhighlight lang=wikitext inline>{{ns:0}}</syntaxhighlight>
|{{ns:0}} (main namespace, returns empty string)
|<syntaxhighlight lang=wikitext inline>{{ns:1}}</syntaxhighlight>
|{{ns:1}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:2}}</syntaxhighlight>
|{{ns:2}}
|<syntaxhighlight lang=wikitext inline>{{ns:3}}</syntaxhighlight>
|{{ns:3}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:4}}</syntaxhighlight>
|{{ns:4}}
|<syntaxhighlight lang=wikitext inline>{{ns:5}}</syntaxhighlight>
|{{ns:5}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:6}}</syntaxhighlight>
|{{ns:6}}
|<syntaxhighlight lang=wikitext inline>{{ns:7}}</syntaxhighlight>
|{{ns:7}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:8}}</syntaxhighlight>
|{{ns:8}}
|<syntaxhighlight lang=wikitext inline>{{ns:9}}</syntaxhighlight>
|{{ns:9}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:10}}</syntaxhighlight>
|{{ns:10}}
|<syntaxhighlight lang=wikitext inline>{{ns:11}}</syntaxhighlight>
|{{ns:11}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:12}}</syntaxhighlight>
|{{ns:12}}
|<syntaxhighlight lang=wikitext inline>{{ns:13}}</syntaxhighlight>
|{{ns:13}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:14}}</syntaxhighlight>
|{{ns:14}}
|<syntaxhighlight lang=wikitext inline>{{ns:15}}</syntaxhighlight>
|{{ns:15}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:100}}</syntaxhighlight>
|{{ns:100}}
|<syntaxhighlight lang=wikitext inline>{{ns:101}}</syntaxhighlight>
|{{ns:101}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:118}}</syntaxhighlight>
|{{ns:118}}
|<syntaxhighlight lang=wikitext inline>{{ns:119}}</syntaxhighlight>
|{{ns:119}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:126}}</syntaxhighlight>
|{{ns:126}}
|<syntaxhighlight lang=wikitext inline>{{ns:127}}</syntaxhighlight>
|{{ns:127}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:710}}</syntaxhighlight>
|{{ns:710}}
|<syntaxhighlight lang=wikitext inline>{{ns:711}}</syntaxhighlight>
|{{ns:711}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:828}}</syntaxhighlight>
|{{ns:828}}
|<syntaxhighlight lang=wikitext inline>{{ns:829}}</syntaxhighlight>
|{{ns:829}}
|-
|<syntaxhighlight lang=wikitext inline>{{ns:1728}}</syntaxhighlight>
|{{ns:1728}}
|<syntaxhighlight lang=wikitext inline>{{ns:1729}}</syntaxhighlight>
|{{ns:1729}}
|}
Alternative variables are available for most namespaces, for example <syntaxhighlight lang=wikitext inline>{{ns:talk}}</syntaxhighlight>, <syntaxhighlight lang=wikitext inline>{{ns:user}}</syntaxhighlight>, and <syntaxhighlight lang=wikitext inline>{{ns:user_talk}}</syntaxhighlight> for <syntaxhighlight lang=wikitext inline>{{ns:1}}</syntaxhighlight>, <syntaxhighlight lang=wikitext inline>{{ns:2}}</syntaxhighlight> and <syntaxhighlight lang=wikitext inline>{{ns:3}}</syntaxhighlight>. The portal namespace is numbered in the 100-plus range, as are all MediaWiki nonstandard namespaces. It is also possible to use {{tl|Namespace name}} for this, i.e. "<syntaxhighlight lang=wikitext inline>{{Namespace name|711}}</syntaxhighlight>" produces "{{Namespace name|711}}".
All namespaces with a positive number or zero in this list are searchable. Specifically, the {{ns:-2}} and {{ns:-1}} namespaces are not searchable.
The [[Help:Magic words|magic word]] <syntaxhighlight lang=wikitext inline>{{NAMESPACE}}</syntaxhighlight> returns the namespace prefix of the current page. This can be used in combination with other magic words and [[meta:Help:ParserFunctions|parser functions]] to change the appearance of [[WP:Template|templates]] depending on the namespace in which they are transcluded.
Meta-templates have been created to simplify this process. These include the simple template {{tl|main other}}, and the more complex and versatile {{tl|namespace detect}}.
For information on changing the appearance of a page or template by namespace based on CSS, see '''CSS''' section of [[mw:Help:Namespaces#Identifying namespaces|Identifying namespaces]] on the MediaWiki help page.
== See also ==
{{Help desk}}
* [[Wikipedia:Page name]]
* [[Wikipedia:Controlling search engine indexing]]
* [[mw:Help:Namespaces|MediaWiki help page on namespaces]], for general MediaWiki technical information
* [[mw:Extension default namespaces]], for namespaces added by extensions
* [[Special:NamespaceInfo]] - automated listing of information for configured namespaces
== References ==
{{reflist}}
{{Wikipedia technical help|collapsed}}
[[Category:Wikipedia features]]
[[Category:Wikipedia namespace administration| ]]
43kmj91411x9t412ztruprllz6bxqtb
Wikipidiya mossa:Namespace
5
1155
9337
2026-07-11T23:57:38Z
Andrybak
343
Reverted 1 edit by [[Special:Contributions/~2026-39313-84|~2026-39313-84]] ([[User talk:~2026-39313-84|talk]]) to last revision by OzmoOzmo
9337
wikitext
text/x-wiki
{{WikiProject banner shell|
{{Wikipedia Help Project|class=NA|importance=high}}
}}
{{old moves|list=
*Wikipedia:Namespace → Help:Namespace, 13 January 2013, [[Wikipedia talk:Namespace#Requested move]]
}}
{{merged-from |Help:Namespace |12 June 2009}}
{{Archives}}
== FAQ Namespace ==
Where would one petition to have a FAQ namespace added? There are many articles where discussions are endlessly repeated, and calls for merges, deletions, or era changes, etc are repeated by newcomers. A few of the Talk pages I've seen recently have mentioned the desire to have a FAQ page where results of major-change discussions, or results of discussions of questions frequently asked can be placed for easy reference without having to rehash a long discussion all over again on the Talk page. Is there a place at WP where a request for a new namespace could be placed? Many thanks. — [[User:Imeriki al-Shimoni|<span style="color:#60d;font-weight:bold;text-shadow:3px 3px 2px #aaa;">al-Shimoni</span>]] ([[User talk:Imeriki al-Shimoni|talk]]) 07:51, 16 December 2011 (UTC)
== Request for comment: Page move nomination ==
Due to the fact that this page is a how to guide, It should be moved to Help:Namespaces with a redirect. -- [[User:PythonSwarm|PythonSwarm]] <sup>[[User talk:PythonSwarm|Talk]] | [[Special:Contribs/PythonSwarm|Contribs]] | [[Special:CentralAuth/PythonSwarm|Global]]</sup> 01:10, 24 August 2020 (UTC)
:{{u|PythonSwarm}}, this is '''almost''' a [[WP:RM|requested move]] discussion. [[User:I dream of horses|I dream of horses]] [[Special:Contribs/I dream of horses|(Contribs)]] Please [[WP:NOTIFY|notify]] me after replying off my [[User talk:I dream of horses|talk page.]] Thank you. 02:34, 24 August 2020 (UTC)
=== Discussion ===
*'''Opposed''' really only seeing infomation here rather then how to do something.--<span style="font-weight:bold;color:darkblue">[[User_talk:Moxy|Moxy]]</span> <span style="color:red">🍁</span> 03:04, 24 August 2020 (UTC)
*'''Oppose''' <small>(Called forth by bot)</small> This is not a help page, it does fine in the Wikipedia namespace. We try to keep only the most relevant things in the help namespace so that our experienced hands can easily find things by searching something like "WP:NAMESPACE". I wouldn't think to search "Help:Namespace", because help pages are not really built for our experienced hands, and I don't think this page is meant as a starter guide. [[User:CaptainEek|<span style="color:#6a1f7f">'''CaptainEek'''</span>]] <sup>[[User talk:CaptainEek|<span style="font-size:82%"><span style="color:#a479e5">''Edits Ho Cap'n!''</span></span>]]</sup>[[Special:Contributions/CaptainEek|⚓]] 04:18, 24 August 2020 (UTC)
*'''opposed''' This page is more than a help page. It fits this namespace well. [[User:Philoserf|—¿philoserf?]] ([[User talk:Philoserf|talk]]) 22:48, 24 August 2020 (UTC)
*'''Keep'''. This page is more about the guidelines we have established for the use of namespaces on Wikipedia, than about how namespaces work within our software. --[[User:Bsherr|Bsherr]] ([[User talk:Bsherr|talk]]) 04:02, 25 August 2020 (UTC)
*'''Support''', this is almost entirely a help page, and I believe these should ideally placed in the Help namespace. Almost all of it is about the technical aspects of namespaces, and there is very little policy discussion or commentary. --[[User:Mrjulesd|<span style="color:orange;">--Jules</span>]] [[User talk:Mrjulesd|(Mrjulesd)]] 20:59, 25 August 2020 (UTC)
== RIP Gadget talk: Invention, Travel, & Adventure ==
GOOD NIGHT SWEET PRINCE
YOU WILL BE MISSED
/-_-\
/ / \
/ / \
\ \ /
\__\__/
\\
-\\ ____
\\ / /
____ \\/___/
\ \ -//
\___\//-
-//
\\
//
//-
-//
//
\\
\\
<b style="font-family: monospace; color:#E35BD8">[[User:JPxG|<b style="color:#029D74">jp</b>]]×[[Special:Contributions/JPxG|<b style="color: #029D74">g</b>]][[User talk:JPxG|🗯️]]</b> 07:42, 3 March 2024 (UTC)
== Semi-protected edit request on 21 August 2024 ==
{{edit semi-protected|Wikipedia:Namespace|answered=yes}}
Please change the Wikimedia Outreach reference: from <code><nowiki>[https://outreach.m.wikimedia.org/wiki/Education/News/January_2018/Education_Extension_scheduled_shutdown Education_Extension_scheduled_shutdown, Wikimedia outreach]</nowiki></code> to <code><nowiki>[https://outreach.wikimedia.org/wiki/Education/News/January_2018/Education_Extension_scheduled_shutdown "Education Extension scheduled shutdown"], Wikimedia Outreach</nowiki></code>; this removes the [[:Help:Mobile access|mobile site prefix]] that isn't optimised for desktop usage (and if browsing on a mobile, it should be automatically changed anyway), and it also doesn't display underscores in the link. [[Special:Contributions/83.28.217.24|83.28.217.24]] ([[User talk:83.28.217.24|talk]]) 09:22, 21 August 2024 (UTC)
:It would be better to use <code><nowiki>[[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]]</nowiki></code> which yields [[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]]. --[[User:Redrose64|<span style="color:#a80000; background:#ffeeee; text-decoration:inherit">Red</span>rose64]] 🌹 ([[User talk:Redrose64|talk]]) 16:49, 21 August 2024 (UTC)
:: Agreed, {{done}}<!-- Template:ESp --> [[User:Tollens|Tollens]] ([[User talk:Tollens|talk]]) 19:32, 21 August 2024 (UTC)
== Alias "cat:" ==
Commons already supports it, e.g., [[:c:cat:SVG numbers]] redirects to [[:c:Category:SVG numbers]] -- why not on English Wikipedia, too? [[Wikipedia_talk:Namespace/Archive_1#Integrate_pseudo-namespace_into_alias-namespace|Previous discussion]] alluded to "pollution" and the use of colon character in article titles. But the actual problem would be articles starting with "cat:", which currently are only some "pseudo-namespaces" (cross-space redirects) [https://en.wikipedia.org/wiki/Special:PrefixIndex/CAT:] . [[User:Fgnievinski|fgnievinski]] ([[User talk:Fgnievinski|talk]]) 02:45, 23 February 2025 (UTC)
==Discussion at [[:Wikipedia:Village pump (technical)#Adding a SecurePoll namespace|Wikipedia:Village pump (technical) § Adding a SecurePoll namespace]]==
[[File:Symbol watching blue lashes high contrast.svg|25px|link=|alt=]] You are invited to join the discussion at [[:Wikipedia:Village pump (technical)#Adding a SecurePoll namespace|Wikipedia:Village pump (technical) § Adding a SecurePoll namespace]]. –[[User:Novem Linguae|<span style="color:blue">'''Novem Linguae'''</span>]] <small>([[User talk:Novem Linguae|talk]])</small> 08:06, 19 June 2025 (UTC)<!-- [[Template:Please see]] -->
== Feedback requested regarding WP and Help namespaces ==
Your feedback would be appreciated at the following discussion: [[WP:Village pump (idea lab)#Same titled page in both WP and Help namespaces]]. Thanks, [[User:Mathglot|Mathglot]] ([[User talk:Mathglot|talk]]) 09:20, 14 December 2025 (UTC)
: It should be further noted that subpage [[Wikipedia:Namespace/Help vs. Wikipedia]] is featured in that discussion, and was created for it. [[User:Mathglot|Mathglot]] ([[User talk:Mathglot|talk]]) 10:26, 16 December 2025 (UTC)
e2qkxdlgdb0fv5gimfzwdhiv3re4o5o
9338
9337
2026-08-23T08:17:45Z
RAPTOR7762
18
1 revision imported from [[:en:Wikipedia_talk:Namespace]]
9337
wikitext
text/x-wiki
{{WikiProject banner shell|
{{Wikipedia Help Project|class=NA|importance=high}}
}}
{{old moves|list=
*Wikipedia:Namespace → Help:Namespace, 13 January 2013, [[Wikipedia talk:Namespace#Requested move]]
}}
{{merged-from |Help:Namespace |12 June 2009}}
{{Archives}}
== FAQ Namespace ==
Where would one petition to have a FAQ namespace added? There are many articles where discussions are endlessly repeated, and calls for merges, deletions, or era changes, etc are repeated by newcomers. A few of the Talk pages I've seen recently have mentioned the desire to have a FAQ page where results of major-change discussions, or results of discussions of questions frequently asked can be placed for easy reference without having to rehash a long discussion all over again on the Talk page. Is there a place at WP where a request for a new namespace could be placed? Many thanks. — [[User:Imeriki al-Shimoni|<span style="color:#60d;font-weight:bold;text-shadow:3px 3px 2px #aaa;">al-Shimoni</span>]] ([[User talk:Imeriki al-Shimoni|talk]]) 07:51, 16 December 2011 (UTC)
== Request for comment: Page move nomination ==
Due to the fact that this page is a how to guide, It should be moved to Help:Namespaces with a redirect. -- [[User:PythonSwarm|PythonSwarm]] <sup>[[User talk:PythonSwarm|Talk]] | [[Special:Contribs/PythonSwarm|Contribs]] | [[Special:CentralAuth/PythonSwarm|Global]]</sup> 01:10, 24 August 2020 (UTC)
:{{u|PythonSwarm}}, this is '''almost''' a [[WP:RM|requested move]] discussion. [[User:I dream of horses|I dream of horses]] [[Special:Contribs/I dream of horses|(Contribs)]] Please [[WP:NOTIFY|notify]] me after replying off my [[User talk:I dream of horses|talk page.]] Thank you. 02:34, 24 August 2020 (UTC)
=== Discussion ===
*'''Opposed''' really only seeing infomation here rather then how to do something.--<span style="font-weight:bold;color:darkblue">[[User_talk:Moxy|Moxy]]</span> <span style="color:red">🍁</span> 03:04, 24 August 2020 (UTC)
*'''Oppose''' <small>(Called forth by bot)</small> This is not a help page, it does fine in the Wikipedia namespace. We try to keep only the most relevant things in the help namespace so that our experienced hands can easily find things by searching something like "WP:NAMESPACE". I wouldn't think to search "Help:Namespace", because help pages are not really built for our experienced hands, and I don't think this page is meant as a starter guide. [[User:CaptainEek|<span style="color:#6a1f7f">'''CaptainEek'''</span>]] <sup>[[User talk:CaptainEek|<span style="font-size:82%"><span style="color:#a479e5">''Edits Ho Cap'n!''</span></span>]]</sup>[[Special:Contributions/CaptainEek|⚓]] 04:18, 24 August 2020 (UTC)
*'''opposed''' This page is more than a help page. It fits this namespace well. [[User:Philoserf|—¿philoserf?]] ([[User talk:Philoserf|talk]]) 22:48, 24 August 2020 (UTC)
*'''Keep'''. This page is more about the guidelines we have established for the use of namespaces on Wikipedia, than about how namespaces work within our software. --[[User:Bsherr|Bsherr]] ([[User talk:Bsherr|talk]]) 04:02, 25 August 2020 (UTC)
*'''Support''', this is almost entirely a help page, and I believe these should ideally placed in the Help namespace. Almost all of it is about the technical aspects of namespaces, and there is very little policy discussion or commentary. --[[User:Mrjulesd|<span style="color:orange;">--Jules</span>]] [[User talk:Mrjulesd|(Mrjulesd)]] 20:59, 25 August 2020 (UTC)
== RIP Gadget talk: Invention, Travel, & Adventure ==
GOOD NIGHT SWEET PRINCE
YOU WILL BE MISSED
/-_-\
/ / \
/ / \
\ \ /
\__\__/
\\
-\\ ____
\\ / /
____ \\/___/
\ \ -//
\___\//-
-//
\\
//
//-
-//
//
\\
\\
<b style="font-family: monospace; color:#E35BD8">[[User:JPxG|<b style="color:#029D74">jp</b>]]×[[Special:Contributions/JPxG|<b style="color: #029D74">g</b>]][[User talk:JPxG|🗯️]]</b> 07:42, 3 March 2024 (UTC)
== Semi-protected edit request on 21 August 2024 ==
{{edit semi-protected|Wikipedia:Namespace|answered=yes}}
Please change the Wikimedia Outreach reference: from <code><nowiki>[https://outreach.m.wikimedia.org/wiki/Education/News/January_2018/Education_Extension_scheduled_shutdown Education_Extension_scheduled_shutdown, Wikimedia outreach]</nowiki></code> to <code><nowiki>[https://outreach.wikimedia.org/wiki/Education/News/January_2018/Education_Extension_scheduled_shutdown "Education Extension scheduled shutdown"], Wikimedia Outreach</nowiki></code>; this removes the [[:Help:Mobile access|mobile site prefix]] that isn't optimised for desktop usage (and if browsing on a mobile, it should be automatically changed anyway), and it also doesn't display underscores in the link. [[Special:Contributions/83.28.217.24|83.28.217.24]] ([[User talk:83.28.217.24|talk]]) 09:22, 21 August 2024 (UTC)
:It would be better to use <code><nowiki>[[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]]</nowiki></code> which yields [[outreach:Education/News/January 2018/Education Extension scheduled shutdown|Education Extension scheduled shutdown]]. --[[User:Redrose64|<span style="color:#a80000; background:#ffeeee; text-decoration:inherit">Red</span>rose64]] 🌹 ([[User talk:Redrose64|talk]]) 16:49, 21 August 2024 (UTC)
:: Agreed, {{done}}<!-- Template:ESp --> [[User:Tollens|Tollens]] ([[User talk:Tollens|talk]]) 19:32, 21 August 2024 (UTC)
== Alias "cat:" ==
Commons already supports it, e.g., [[:c:cat:SVG numbers]] redirects to [[:c:Category:SVG numbers]] -- why not on English Wikipedia, too? [[Wikipedia_talk:Namespace/Archive_1#Integrate_pseudo-namespace_into_alias-namespace|Previous discussion]] alluded to "pollution" and the use of colon character in article titles. But the actual problem would be articles starting with "cat:", which currently are only some "pseudo-namespaces" (cross-space redirects) [https://en.wikipedia.org/wiki/Special:PrefixIndex/CAT:] . [[User:Fgnievinski|fgnievinski]] ([[User talk:Fgnievinski|talk]]) 02:45, 23 February 2025 (UTC)
==Discussion at [[:Wikipedia:Village pump (technical)#Adding a SecurePoll namespace|Wikipedia:Village pump (technical) § Adding a SecurePoll namespace]]==
[[File:Symbol watching blue lashes high contrast.svg|25px|link=|alt=]] You are invited to join the discussion at [[:Wikipedia:Village pump (technical)#Adding a SecurePoll namespace|Wikipedia:Village pump (technical) § Adding a SecurePoll namespace]]. –[[User:Novem Linguae|<span style="color:blue">'''Novem Linguae'''</span>]] <small>([[User talk:Novem Linguae|talk]])</small> 08:06, 19 June 2025 (UTC)<!-- [[Template:Please see]] -->
== Feedback requested regarding WP and Help namespaces ==
Your feedback would be appreciated at the following discussion: [[WP:Village pump (idea lab)#Same titled page in both WP and Help namespaces]]. Thanks, [[User:Mathglot|Mathglot]] ([[User talk:Mathglot|talk]]) 09:20, 14 December 2025 (UTC)
: It should be further noted that subpage [[Wikipedia:Namespace/Help vs. Wikipedia]] is featured in that discussion, and was created for it. [[User:Mathglot|Mathglot]] ([[User talk:Mathglot|talk]]) 10:26, 16 December 2025 (UTC)
e2qkxdlgdb0fv5gimfzwdhiv3re4o5o
Module:Wikitext Parsing
828
1156
9339
2026-07-29T21:33:46Z
Pppery
320
Copy from sandbox per request
9339
Scribunto
text/plain
require("strict")
-- We're calling up to thousands of string methods each time we run, so
-- do this very simple micro optimisation to help a tiny bit
local string = string
-- Helper functions for PrepareText --
local function endswith(text, subtext)
return string.sub(text, -#subtext, -1) == subtext
end
local function allcases(s)
return string.gsub(s, "%a", function(c)
return "["..string.upper(c)..string.lower(c).."]"
end)
end
--[=[ Implementation notes
---- NORMAL HTML TAGS ----
Tags are very strict on how they want to start, but loose on how they end.
The start must strictly follow <[tAgNaMe](%s|>) with no room for whitespace in
the tag's name, but may then flow as they want afterwards, making
<div\nclass\n=\n"\nerror\n"\n> valid. If a tag has no end, it will consume all
text instead of not processing.
There's no sense of escaping < or >
E.g.
<div class="error\>"> will end at \> despite it being inside a quote
<div class="<span class="error">error</span>"> will not process the larger div
---- NOPROCESSING TAGS (nowiki, pre, syntaxhighlight, source, etc.) ----
(Note: <source> is the deprecated version of <syntaxhighlight>)
No-processing tags have some differences to the above rules. Specifically, their
syntax is a lot stricter. While an opening tag follows the same set of rules, A
closing tag can't have any sort of extra formatting. </div a/a> is valid,
</nowiki a/a> is not. Only newlines and spaces/tabs are allowed in closing tags.
Note that, even though tags may cause a visual change without an ending tag like
<pre>, one is required for the no-processing effects.
Both the content inside the tag pair and the text in the tags will not be
processed. E.g. <nowiki |}}>|}}</nowiki> would have both of the |}} escaped.
Since we only care about these no-processing tags, we can ignore the idea of an
intercepting tag messing us up, and just go for the first ending we can find. If
there is no ending, the tag will NOT consume the rest of the text. Even if there
is no ending tag, the content inside the opening tag will still be unprocessed,
meaning {{X20|<nowiki }}>}} wouldn't end at the first }} despite there being no
ending tag.
There are some tags, like <math>, which also function like <nowiki> for our
purposes, and are handled here. Some other tags, like <ref>, have more complex
behaviour that can't be reasonably implemented in this, and so are ignored. I
suspect that every tag listed in [[Special:Version]] may behave somewhat like
this, but that's far too many cases worth checking for rarely used tags that may
not even have a good reason to contain {{ or }} anyways, so we leave them alone.
---- INCLUDEONLY ----
While includeonly tags do technically serve the same purpose as a nowiki tag for
what this module does, contextually they don't always make sense to escape, and
as such are ignored by this module entirely.
--]=]
-- This function expects the string to start with the tag
local validtags = {nowiki=1, pre=1, syntaxhighlight=1, source=1, math=1}
local function TestForNowikiTag(text, scanPosition)
local tagName = string.match(text, "^<([^\n />]+)", scanPosition)
if not tagName or not validtags[string.lower(tagName)] then
return nil
end
local nextOpener = string.find(text, "<", scanPosition+1, true)
local nextCloser = string.find(text, ">", scanPosition+1, true)
if nextCloser and (not nextOpener or nextCloser < nextOpener) then
local startingTag = string.sub(text, scanPosition, nextCloser)
-- We have our starting tag (E.g. '<pre style="color:red">')
-- Now find our ending...
if endswith(startingTag, "/>") then -- self-closing tag (we are our own ending)
return {
Tag = tagName,
Start = startingTag,
Content = "", End = "",
Length = #startingTag
}
else
local endingTagStart, endingTagEnd = string.find(text, "</"..allcases(tagName).."[ \t\n]*>", scanPosition)
if endingTagStart then --Regular tag formation
local endingTag = string.sub(text, endingTagStart, endingTagEnd)
local tagContent = string.sub(text, nextCloser+1, endingTagStart-1)
return {
Tag = tagName,
Start = startingTag,
Content = tagContent,
End = endingTag,
Length = #startingTag + #tagContent + #endingTag
}
else -- Content inside still needs escaping (also linter error!)
return {
Tag = tagName,
Start = startingTag,
Content = "", End = "",
Length = #startingTag
}
end
end
end
return nil
end
--[=[ Implementation Notes
HTML Comments are about as basic as it gets. Start at <!--, end at -->, no extra
conditions. If a comment has no end, it will eat all the text ahead.
--]=]
local function TestForComment(text, scanPosition)
if string.match(text, "^<!%-%-", scanPosition) then
local commentEnd = string.find(text, "-->", scanPosition+4, true)
if commentEnd then
return {
Start = "<!--", End = "-->",
Content = string.sub(text, scanPosition+4, commentEnd-1),
Length = commentEnd-scanPosition+3
}
else -- Consumes all text if not given an ending
return {
Start = "<!--", End = "",
Content = string.sub(text, scanPosition+4),
Length = #text-scanPosition+1
}
end
end
return nil
end
--[[ Implementation notes
The goal of this function is to escape all text that wouldn't be parsed if it
was preprocessed (see above implementation notes).
Using keepComments will keep all HTML comments instead of removing them. They
will still be escaped regardless.
--]]
local function PrepareText(text, keepComments)
local newtext = {}
local scanPosition = 1
local textPosition = 1
while true do
local nextCheck = string.find(text, "<", scanPosition, true) -- Advance to the next potential tag we care about
if not nextCheck then -- Done
newtext[#newtext+1] = string.sub(text, textPosition)
break
end
scanPosition = nextCheck
local Comment = TestForComment(text, scanPosition)
if Comment then
newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)
if keepComments then
newtext[#newtext+1] = Comment.Start .. mw.text.nowiki(Comment.Content) .. Comment.End
end
scanPosition = scanPosition + Comment.Length
textPosition = scanPosition
else
local Tag = TestForNowikiTag(text, scanPosition)
if Tag then
newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)
local newTagStart = "<" .. mw.text.nowiki(string.sub(Tag.Start, 2, -2)) .. ">"
local newTagEnd =
Tag.End == "" and "" or -- Respect no tag ending
"</" .. mw.text.nowiki(string.sub(Tag.End, 3, -2)) .. ">"
local newContent = mw.text.nowiki(Tag.Content)
newtext[#newtext+1] = newTagStart .. newContent .. newTagEnd
scanPosition = scanPosition + Tag.Length
textPosition = scanPosition
else -- Nothing special, move on...
scanPosition = scanPosition + 1
end
end
end
return table.concat(newtext, "")
end
local p = {}
--Main entry points
p.PrepareText = PrepareText
--Extra entry points, not really required
p.TestForNowikiTag = TestForNowikiTag
p.TestForComment = TestForComment
return p
--[==[ console tests
local s = [=[Hey!{{Text|<nowiki | ||>
Hey! }}
A</nowiki>|<!--AAAAA|AAA-->Should see|Shouldn't see}}]=]
local out = p.PrepareText(s)
mw.logObject(out)
local s = [=[B<!--
Hey!
-->A]=]
local out = p.TestForComment(s, 2)
mw.logObject(out); mw.log(string.sub(s, 2, out.Length))
]==]
iiu3f4jhxaiu5ehdw27fgi71pmkfo78
9340
9339
2026-08-23T08:17:45Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Wikitext_Parsing]]
9339
Scribunto
text/plain
require("strict")
-- We're calling up to thousands of string methods each time we run, so
-- do this very simple micro optimisation to help a tiny bit
local string = string
-- Helper functions for PrepareText --
local function endswith(text, subtext)
return string.sub(text, -#subtext, -1) == subtext
end
local function allcases(s)
return string.gsub(s, "%a", function(c)
return "["..string.upper(c)..string.lower(c).."]"
end)
end
--[=[ Implementation notes
---- NORMAL HTML TAGS ----
Tags are very strict on how they want to start, but loose on how they end.
The start must strictly follow <[tAgNaMe](%s|>) with no room for whitespace in
the tag's name, but may then flow as they want afterwards, making
<div\nclass\n=\n"\nerror\n"\n> valid. If a tag has no end, it will consume all
text instead of not processing.
There's no sense of escaping < or >
E.g.
<div class="error\>"> will end at \> despite it being inside a quote
<div class="<span class="error">error</span>"> will not process the larger div
---- NOPROCESSING TAGS (nowiki, pre, syntaxhighlight, source, etc.) ----
(Note: <source> is the deprecated version of <syntaxhighlight>)
No-processing tags have some differences to the above rules. Specifically, their
syntax is a lot stricter. While an opening tag follows the same set of rules, A
closing tag can't have any sort of extra formatting. </div a/a> is valid,
</nowiki a/a> is not. Only newlines and spaces/tabs are allowed in closing tags.
Note that, even though tags may cause a visual change without an ending tag like
<pre>, one is required for the no-processing effects.
Both the content inside the tag pair and the text in the tags will not be
processed. E.g. <nowiki |}}>|}}</nowiki> would have both of the |}} escaped.
Since we only care about these no-processing tags, we can ignore the idea of an
intercepting tag messing us up, and just go for the first ending we can find. If
there is no ending, the tag will NOT consume the rest of the text. Even if there
is no ending tag, the content inside the opening tag will still be unprocessed,
meaning {{X20|<nowiki }}>}} wouldn't end at the first }} despite there being no
ending tag.
There are some tags, like <math>, which also function like <nowiki> for our
purposes, and are handled here. Some other tags, like <ref>, have more complex
behaviour that can't be reasonably implemented in this, and so are ignored. I
suspect that every tag listed in [[Special:Version]] may behave somewhat like
this, but that's far too many cases worth checking for rarely used tags that may
not even have a good reason to contain {{ or }} anyways, so we leave them alone.
---- INCLUDEONLY ----
While includeonly tags do technically serve the same purpose as a nowiki tag for
what this module does, contextually they don't always make sense to escape, and
as such are ignored by this module entirely.
--]=]
-- This function expects the string to start with the tag
local validtags = {nowiki=1, pre=1, syntaxhighlight=1, source=1, math=1}
local function TestForNowikiTag(text, scanPosition)
local tagName = string.match(text, "^<([^\n />]+)", scanPosition)
if not tagName or not validtags[string.lower(tagName)] then
return nil
end
local nextOpener = string.find(text, "<", scanPosition+1, true)
local nextCloser = string.find(text, ">", scanPosition+1, true)
if nextCloser and (not nextOpener or nextCloser < nextOpener) then
local startingTag = string.sub(text, scanPosition, nextCloser)
-- We have our starting tag (E.g. '<pre style="color:red">')
-- Now find our ending...
if endswith(startingTag, "/>") then -- self-closing tag (we are our own ending)
return {
Tag = tagName,
Start = startingTag,
Content = "", End = "",
Length = #startingTag
}
else
local endingTagStart, endingTagEnd = string.find(text, "</"..allcases(tagName).."[ \t\n]*>", scanPosition)
if endingTagStart then --Regular tag formation
local endingTag = string.sub(text, endingTagStart, endingTagEnd)
local tagContent = string.sub(text, nextCloser+1, endingTagStart-1)
return {
Tag = tagName,
Start = startingTag,
Content = tagContent,
End = endingTag,
Length = #startingTag + #tagContent + #endingTag
}
else -- Content inside still needs escaping (also linter error!)
return {
Tag = tagName,
Start = startingTag,
Content = "", End = "",
Length = #startingTag
}
end
end
end
return nil
end
--[=[ Implementation Notes
HTML Comments are about as basic as it gets. Start at <!--, end at -->, no extra
conditions. If a comment has no end, it will eat all the text ahead.
--]=]
local function TestForComment(text, scanPosition)
if string.match(text, "^<!%-%-", scanPosition) then
local commentEnd = string.find(text, "-->", scanPosition+4, true)
if commentEnd then
return {
Start = "<!--", End = "-->",
Content = string.sub(text, scanPosition+4, commentEnd-1),
Length = commentEnd-scanPosition+3
}
else -- Consumes all text if not given an ending
return {
Start = "<!--", End = "",
Content = string.sub(text, scanPosition+4),
Length = #text-scanPosition+1
}
end
end
return nil
end
--[[ Implementation notes
The goal of this function is to escape all text that wouldn't be parsed if it
was preprocessed (see above implementation notes).
Using keepComments will keep all HTML comments instead of removing them. They
will still be escaped regardless.
--]]
local function PrepareText(text, keepComments)
local newtext = {}
local scanPosition = 1
local textPosition = 1
while true do
local nextCheck = string.find(text, "<", scanPosition, true) -- Advance to the next potential tag we care about
if not nextCheck then -- Done
newtext[#newtext+1] = string.sub(text, textPosition)
break
end
scanPosition = nextCheck
local Comment = TestForComment(text, scanPosition)
if Comment then
newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)
if keepComments then
newtext[#newtext+1] = Comment.Start .. mw.text.nowiki(Comment.Content) .. Comment.End
end
scanPosition = scanPosition + Comment.Length
textPosition = scanPosition
else
local Tag = TestForNowikiTag(text, scanPosition)
if Tag then
newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)
local newTagStart = "<" .. mw.text.nowiki(string.sub(Tag.Start, 2, -2)) .. ">"
local newTagEnd =
Tag.End == "" and "" or -- Respect no tag ending
"</" .. mw.text.nowiki(string.sub(Tag.End, 3, -2)) .. ">"
local newContent = mw.text.nowiki(Tag.Content)
newtext[#newtext+1] = newTagStart .. newContent .. newTagEnd
scanPosition = scanPosition + Tag.Length
textPosition = scanPosition
else -- Nothing special, move on...
scanPosition = scanPosition + 1
end
end
end
return table.concat(newtext, "")
end
local p = {}
--Main entry points
p.PrepareText = PrepareText
--Extra entry points, not really required
p.TestForNowikiTag = TestForNowikiTag
p.TestForComment = TestForComment
return p
--[==[ console tests
local s = [=[Hey!{{Text|<nowiki | ||>
Hey! }}
A</nowiki>|<!--AAAAA|AAA-->Should see|Shouldn't see}}]=]
local out = p.PrepareText(s)
mw.logObject(out)
local s = [=[B<!--
Hey!
-->A]=]
local out = p.TestForComment(s, 2)
mw.logObject(out); mw.log(string.sub(s, 2, out.Length))
]==]
iiu3f4jhxaiu5ehdw27fgi71pmkfo78
Module:Disambiguation/templates
828
1157
9341
2026-02-26T17:22:58Z
Pppery
320
Update list
9341
Scribunto
text/plain
-- This page contains a table of all disambiguation templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["Disambiguation"] = true,
["Begriffsklärung"] = true,
["DAB"] = true,
["Dab"] = true,
["Dab page"] = true,
["Dabpage"] = true,
["Dbig"] = true,
["Dis"] = true,
["Disam"] = true,
["Disamb"] = true,
["Disambig"] = true,
["Disambig misspelling"] = true,
["Disambig-plants"] = true,
["Disambiguation page"] = true,
["Manual of Style disambiguation"] = true,
["Meta disambig"] = true,
["MOS disambiguation"] = true,
["MoS disambiguation"] = true,
["Portal disambig"] = true,
["Portal disambiguation"] = true,
["Project disambiguation"] = true,
["Shortcut disambig"] = true,
["Wikipedia disambiguation"] = true,
["WP disambig"] = true,
["WP-disambig"] = true,
["Airport disambiguation"] = true,
["Airport disambig"] = true,
["Biology disambiguation"] = true,
["Call sign disambiguation"] = true,
["Callsigndis"] = true,
["Caselaw disambiguation"] = true,
["Case law disambiguation"] = true,
["Chinese title disambiguation"] = true,
["Chinese title disambig"] = true,
["CJKVdab"] = true,
["Disambig-Chinese-char-title"] = true,
["Disambiguation cleanup"] = true,
["Cleanup disambig"] = true,
["Cleanup disambiguation"] = true,
["CleanupDisambig"] = true,
["Dab cleanup"] = true,
["Dab-cleanup"] = true,
["Dabclean"] = true,
["Disamb-cleanup"] = true,
["Disambcleanup"] = true,
["Disambig cleanup"] = true,
["Disambig-cleanup"] = true,
["Disambig-CU"] = true,
["Disambig-cu"] = true,
["Disambigcleanup"] = true,
["Disambiguate-cleanup"] = true,
["Disambiguation-cleanup"] = true,
["Geodis-cleanup"] = true,
["Disambiguation with potential"] = true,
["Disambiguation with possibilties"] = true,
["Genus disambiguation"] = true,
["Genus disambig"] = true,
["Greek letter organization disambiguation"] = true,
["GLO disambiguation"] = true,
["Hangul title disambiguation"] = true,
["Hospital disambiguation"] = true,
["Hospitaldis"] = true,
["Human name disambiguation"] = true,
["Bio-dab"] = true,
["Hndab"] = true,
["HNDIS"] = true,
["HnDis"] = true,
["Hndis"] = true,
["Hndisambig"] = true,
["Human name dab"] = true,
["Name list"] = true,
["Personal name"] = true,
["Personal name disambiguation"] = true,
["Human name disambiguation cleanup"] = true,
["Hndis-cleanup"] = true,
["Personal name disambiguation cleanup"] = true,
["Hurricane season disambiguation"] = true,
["Letter–number combination disambiguation"] = true,
["Letter-Number Combination Disambiguation"] = true,
["Letter-Number combination disambiguation"] = true,
["Letter-number combination disambiguation"] = true,
["Letter-NumberCombDisambig"] = true,
["Letter-NumberCombdisambig"] = true,
["Letter-NumberCombinationDisambiguation"] = true,
["LNCD"] = true,
["Mathematical disambiguation"] = true,
["Math dab"] = true,
["Math disambiguation"] = true,
["Math-dab"] = true,
["Mathdab"] = true,
["Mathematics disambiguation"] = true,
["Maths disambiguation"] = true,
["Military unit disambiguation"] = true,
["Mil-unit-dis"] = true,
["Mil-unit-disambig"] = true,
["Music disambiguation"] = true,
["Music disambig"] = true,
["Number disambiguation"] = true,
["Numberdis"] = true,
["Numdab"] = true,
["Numdisambig"] = true,
["Opus number disambiguation"] = true,
["Phonetics disambiguation"] = true,
["Place name disambiguation"] = true,
["DisambigG"] = true,
["DisambigGeo"] = true,
["Disambiggeo"] = true,
["Geo-dis"] = true,
["Geodab"] = true,
["Geodis"] = true,
["Geodisambig"] = true,
["Geographic disambiguation"] = true,
["Geographical disambiguation"] = true,
["Pnd"] = true,
["Road disambiguation"] = true,
["Roaddis"] = true,
["School disambiguation"] = true,
["School disambig"] = true,
["Schooldab"] = true,
["Schooldis"] = true,
["Species Latin name abbreviation disambiguation"] = true,
["Species Latin name disambiguation"] = true,
["LatinNameDisambig"] = true,
["Species disambiguation"] = true,
["SpeciesLatinNameDisambig"] = true,
["Station disambiguation"] = true,
["Station dab"] = true,
["Synagogue disambiguation"] = true,
["Taxonomy disambiguation"] = true,
["Template disambiguation"] = true,
["Template ambiguous"] = true,
["Template dab"] = true,
["Template disambig"] = true,
["WoO number disambiguation"] = true,
}
120emfqmecg5jbyx2n1prgswwe275a0
9342
9341
2026-08-23T08:17:45Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Disambiguation/templates]]
9341
Scribunto
text/plain
-- This page contains a table of all disambiguation templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["Disambiguation"] = true,
["Begriffsklärung"] = true,
["DAB"] = true,
["Dab"] = true,
["Dab page"] = true,
["Dabpage"] = true,
["Dbig"] = true,
["Dis"] = true,
["Disam"] = true,
["Disamb"] = true,
["Disambig"] = true,
["Disambig misspelling"] = true,
["Disambig-plants"] = true,
["Disambiguation page"] = true,
["Manual of Style disambiguation"] = true,
["Meta disambig"] = true,
["MOS disambiguation"] = true,
["MoS disambiguation"] = true,
["Portal disambig"] = true,
["Portal disambiguation"] = true,
["Project disambiguation"] = true,
["Shortcut disambig"] = true,
["Wikipedia disambiguation"] = true,
["WP disambig"] = true,
["WP-disambig"] = true,
["Airport disambiguation"] = true,
["Airport disambig"] = true,
["Biology disambiguation"] = true,
["Call sign disambiguation"] = true,
["Callsigndis"] = true,
["Caselaw disambiguation"] = true,
["Case law disambiguation"] = true,
["Chinese title disambiguation"] = true,
["Chinese title disambig"] = true,
["CJKVdab"] = true,
["Disambig-Chinese-char-title"] = true,
["Disambiguation cleanup"] = true,
["Cleanup disambig"] = true,
["Cleanup disambiguation"] = true,
["CleanupDisambig"] = true,
["Dab cleanup"] = true,
["Dab-cleanup"] = true,
["Dabclean"] = true,
["Disamb-cleanup"] = true,
["Disambcleanup"] = true,
["Disambig cleanup"] = true,
["Disambig-cleanup"] = true,
["Disambig-CU"] = true,
["Disambig-cu"] = true,
["Disambigcleanup"] = true,
["Disambiguate-cleanup"] = true,
["Disambiguation-cleanup"] = true,
["Geodis-cleanup"] = true,
["Disambiguation with potential"] = true,
["Disambiguation with possibilties"] = true,
["Genus disambiguation"] = true,
["Genus disambig"] = true,
["Greek letter organization disambiguation"] = true,
["GLO disambiguation"] = true,
["Hangul title disambiguation"] = true,
["Hospital disambiguation"] = true,
["Hospitaldis"] = true,
["Human name disambiguation"] = true,
["Bio-dab"] = true,
["Hndab"] = true,
["HNDIS"] = true,
["HnDis"] = true,
["Hndis"] = true,
["Hndisambig"] = true,
["Human name dab"] = true,
["Name list"] = true,
["Personal name"] = true,
["Personal name disambiguation"] = true,
["Human name disambiguation cleanup"] = true,
["Hndis-cleanup"] = true,
["Personal name disambiguation cleanup"] = true,
["Hurricane season disambiguation"] = true,
["Letter–number combination disambiguation"] = true,
["Letter-Number Combination Disambiguation"] = true,
["Letter-Number combination disambiguation"] = true,
["Letter-number combination disambiguation"] = true,
["Letter-NumberCombDisambig"] = true,
["Letter-NumberCombdisambig"] = true,
["Letter-NumberCombinationDisambiguation"] = true,
["LNCD"] = true,
["Mathematical disambiguation"] = true,
["Math dab"] = true,
["Math disambiguation"] = true,
["Math-dab"] = true,
["Mathdab"] = true,
["Mathematics disambiguation"] = true,
["Maths disambiguation"] = true,
["Military unit disambiguation"] = true,
["Mil-unit-dis"] = true,
["Mil-unit-disambig"] = true,
["Music disambiguation"] = true,
["Music disambig"] = true,
["Number disambiguation"] = true,
["Numberdis"] = true,
["Numdab"] = true,
["Numdisambig"] = true,
["Opus number disambiguation"] = true,
["Phonetics disambiguation"] = true,
["Place name disambiguation"] = true,
["DisambigG"] = true,
["DisambigGeo"] = true,
["Disambiggeo"] = true,
["Geo-dis"] = true,
["Geodab"] = true,
["Geodis"] = true,
["Geodisambig"] = true,
["Geographic disambiguation"] = true,
["Geographical disambiguation"] = true,
["Pnd"] = true,
["Road disambiguation"] = true,
["Roaddis"] = true,
["School disambiguation"] = true,
["School disambig"] = true,
["Schooldab"] = true,
["Schooldis"] = true,
["Species Latin name abbreviation disambiguation"] = true,
["Species Latin name disambiguation"] = true,
["LatinNameDisambig"] = true,
["Species disambiguation"] = true,
["SpeciesLatinNameDisambig"] = true,
["Station disambiguation"] = true,
["Station dab"] = true,
["Synagogue disambiguation"] = true,
["Taxonomy disambiguation"] = true,
["Template disambiguation"] = true,
["Template ambiguous"] = true,
["Template dab"] = true,
["Template disambig"] = true,
["WoO number disambiguation"] = true,
}
120emfqmecg5jbyx2n1prgswwe275a0
Panni:Books
14
1158
9343
2026-06-06T09:10:28Z
en>~2026-26767-44
0
Remove redundant category
9343
wikitext
text/x-wiki
{{Portal|Books}}
{{Commons category}}
{{Wikisourcecat|Books}}
{{Category main article|book|outline of books}}
{{Distinguish|Category:Wikibooks}}
{{Category see also|Literature}}
{{Category diffuse}}
[[Category:Documents]]
[[Category:Humanities]]
[[Category:Literature by medium]]
[[Category:Manufactured goods]]
[[Category:Media formats]]
[[Category:Paper products]]
[[Category:Print media]]
[[Category:Publications by format]]
[[Category:Publishing]]
[[Category:Written communication]]
3ob5fmwcfe42c6cxa1gpe2u820ns2cj
9344
9343
2026-08-23T08:17:45Z
RAPTOR7762
18
1 revision imported from [[:en:Category:Books]]
9343
wikitext
text/x-wiki
{{Portal|Books}}
{{Commons category}}
{{Wikisourcecat|Books}}
{{Category main article|book|outline of books}}
{{Distinguish|Category:Wikibooks}}
{{Category see also|Literature}}
{{Category diffuse}}
[[Category:Documents]]
[[Category:Humanities]]
[[Category:Literature by medium]]
[[Category:Manufactured goods]]
[[Category:Media formats]]
[[Category:Paper products]]
[[Category:Print media]]
[[Category:Publications by format]]
[[Category:Publishing]]
[[Category:Written communication]]
3ob5fmwcfe42c6cxa1gpe2u820ns2cj
TimedText:MS Sam.ogg.en.srt
710
1159
9345
2020-12-02T07:41:13Z
Graham87
350
Protected "[[TimedText:MS Sam.ogg.en.srt]]" ([Edit=Require autoconfirmed or confirmed access] (indefinite) [Move=Require autoconfirmed or confirmed access] (indefinite))
9345
wikitext
text/x-wiki
1
00:00:00,000 --> 00:00:08,900
The quick brown fox jumps over the lazy dog 1,234,567,890 times.
2
00:00:09,000 --> 00:00:10,900
Soif.
mfzkmboq6h4q02gc1jxkfdb0ik9eosy
9346
9345
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:TimedText:MS_Sam.ogg.en.srt]]
9345
wikitext
text/x-wiki
1
00:00:00,000 --> 00:00:08,900
The quick brown fox jumps over the lazy dog 1,234,567,890 times.
2
00:00:09,000 --> 00:00:10,900
Soif.
mfzkmboq6h4q02gc1jxkfdb0ik9eosy
Module:Pagetype/disambiguation
828
1160
9347
2024-02-23T03:46:01Z
Pppery
320
Use built-in redirect syntax
9347
Scribunto
text/plain
return require [[Module:Disambiguation/templates]]
i5ooe2bqffrglszpd82v0i3pqyp187b
9348
9347
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype/disambiguation]]
9347
Scribunto
text/plain
return require [[Module:Disambiguation/templates]]
i5ooe2bqffrglszpd82v0i3pqyp187b
Module:Pagetype/softredirect
828
1161
9349
2024-08-08T21:25:34Z
MSGJ
321
update from sandbox as StradBot found lots more of these templates
9349
Scribunto
text/plain
-- This page contains a table of all soft redirect templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["R from category navigation"] = true,
["Redirect from category navigation"] = true,
["Category redirect"] = true,
["Cat move"] = true,
["Cat red"] = true,
["Cat redir"] = true,
["Cat redirect"] = true,
["Category move"] = true,
["Category Redirect"] = true,
["Categoryredirect"] = true,
["Catr"] = true,
["Catred"] = true,
["Catredir"] = true,
["Catredirect"] = true,
["R from template-generated category"] = true,
["Redirect from template-generated category"] = true,
["Portal soft redirect"] = true,
["Portal Redirect"] = true,
["Portal redirect"] = true,
["Portal Soft Redirect"] = true,
["Portalredirect"] = true,
["Portalsoftredirect"] = true,
["PortRed"] = true,
["Portred"] = true,
["Portsoftred"] = true,
["PSR"] = true,
["Psr"] = true,
["Soft portal redirect"] = true,
["Soft redirect portal"] = true,
["SPR"] = true,
["Spr"] = true,
["SRP"] = true,
["Srp"] = true,
["Salted redirect"] = true,
["Soft redirect"] = true,
["Interwiki redirect"] = true,
["Plain soft redirect"] = true,
["Soft"] = true,
["Soft link"] = true,
["Soft redir"] = true,
["Soft Redirect"] = true,
["Softr"] = true,
["Softredir"] = true,
["SoftRedirect"] = true,
["Softredirect"] = true,
["Userrename"] = true,
["Wikibooks redirect"] = true,
["WBOOK"] = true,
["Wbook"] = true,
["Wikibook redirect"] = true,
["Wikibooks Redirect"] = true,
["WikibooksRedirect"] = true,
["Wikibooksredirect"] = true,
["Wikimedia Commons redirect"] = true,
["COMM"] = true,
["Comm"] = true,
["Commons Redirect"] = true,
["Commons redirect"] = true,
["CommonsRedirect"] = true,
["Commonsredirect"] = true,
["Wikimedia commons redirect"] = true,
["Wikiquote redirect"] = true,
["Wq"] = true,
["Wikisource redirect"] = true,
["Wikispecies redirect"] = true,
["Wikispecies Redirect"] = true,
["WikispeciesRedirect"] = true,
["Wikispeciesredirect"] = true,
["WSPEC"] = true,
["Wspec"] = true,
["Wikivoyage redirect"] = true,
["Wiktionary redirect"] = true,
["Moved to Wiktionary"] = true,
["RedirecttoWiktionary"] = true,
["Wi"] = true,
["Wikt red"] = true,
["Wikt redirect"] = true,
["Wiktionary Redirect"] = true,
["Wiktionary-redirect"] = true,
["WiktionaryRedirect"] = true,
["Wiktionaryredirect"] = true,
["Wiktr"] = true,
["Wiktred"] = true,
["Wiktredir"] = true,
["Wtr"] = true,
["Wtsr"] = true,
}
krad2do3vq17ck777hpwdoaxr3vo5yt
9350
9349
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype/softredirect]]
9349
Scribunto
text/plain
-- This page contains a table of all soft redirect templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["R from category navigation"] = true,
["Redirect from category navigation"] = true,
["Category redirect"] = true,
["Cat move"] = true,
["Cat red"] = true,
["Cat redir"] = true,
["Cat redirect"] = true,
["Category move"] = true,
["Category Redirect"] = true,
["Categoryredirect"] = true,
["Catr"] = true,
["Catred"] = true,
["Catredir"] = true,
["Catredirect"] = true,
["R from template-generated category"] = true,
["Redirect from template-generated category"] = true,
["Portal soft redirect"] = true,
["Portal Redirect"] = true,
["Portal redirect"] = true,
["Portal Soft Redirect"] = true,
["Portalredirect"] = true,
["Portalsoftredirect"] = true,
["PortRed"] = true,
["Portred"] = true,
["Portsoftred"] = true,
["PSR"] = true,
["Psr"] = true,
["Soft portal redirect"] = true,
["Soft redirect portal"] = true,
["SPR"] = true,
["Spr"] = true,
["SRP"] = true,
["Srp"] = true,
["Salted redirect"] = true,
["Soft redirect"] = true,
["Interwiki redirect"] = true,
["Plain soft redirect"] = true,
["Soft"] = true,
["Soft link"] = true,
["Soft redir"] = true,
["Soft Redirect"] = true,
["Softr"] = true,
["Softredir"] = true,
["SoftRedirect"] = true,
["Softredirect"] = true,
["Userrename"] = true,
["Wikibooks redirect"] = true,
["WBOOK"] = true,
["Wbook"] = true,
["Wikibook redirect"] = true,
["Wikibooks Redirect"] = true,
["WikibooksRedirect"] = true,
["Wikibooksredirect"] = true,
["Wikimedia Commons redirect"] = true,
["COMM"] = true,
["Comm"] = true,
["Commons Redirect"] = true,
["Commons redirect"] = true,
["CommonsRedirect"] = true,
["Commonsredirect"] = true,
["Wikimedia commons redirect"] = true,
["Wikiquote redirect"] = true,
["Wq"] = true,
["Wikisource redirect"] = true,
["Wikispecies redirect"] = true,
["Wikispecies Redirect"] = true,
["WikispeciesRedirect"] = true,
["Wikispeciesredirect"] = true,
["WSPEC"] = true,
["Wspec"] = true,
["Wikivoyage redirect"] = true,
["Wiktionary redirect"] = true,
["Moved to Wiktionary"] = true,
["RedirecttoWiktionary"] = true,
["Wi"] = true,
["Wikt red"] = true,
["Wikt redirect"] = true,
["Wiktionary Redirect"] = true,
["Wiktionary-redirect"] = true,
["WiktionaryRedirect"] = true,
["Wiktionaryredirect"] = true,
["Wiktr"] = true,
["Wiktred"] = true,
["Wiktredir"] = true,
["Wtr"] = true,
["Wtsr"] = true,
}
krad2do3vq17ck777hpwdoaxr3vo5yt
Module:Pagetype/setindex
828
1162
9351
2024-02-17T03:50:28Z
Pppery
320
Changed protection settings for "[[Module:Pagetype/setindex]]": Per parent ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9351
Scribunto
text/plain
-- This page contains a table of all set index templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["Set index article"] = true,
["Sia"] = true,
["Set index"] = true,
["SIA"] = true,
["Set-index"] = true,
["Setindex"] = true,
["Set-index article"] = true,
["Animal common name"] = true,
["Chemistry index"] = true,
["Chemdisambig"] = true,
["Chemistry disambiguation"] = true,
["Chemistry set index"] = true,
["Chemindex"] = true,
["Enzyme index"] = true,
["Fungus common name"] = true,
["Given name"] = true,
["First name"] = true,
["Forename"] = true,
["Greek myth index"] = true,
["Lake index"] = true,
["Lakeindex"] = true,
["Locomotive index"] = true,
["Media set index"] = true,
["Media index"] = true,
["Molecular formula index"] = true,
["MolFormDisambig"] = true,
["Molecular formula disambiguation"] = true,
["MolFormIndex"] = true,
["Mountain index"] = true,
["Mountainindex"] = true,
["Nickname"] = true,
["Painting index"] = true,
["Plant common name"] = true,
["River index"] = true,
["Road index"] = true,
["Roadindex"] = true,
["Ship index"] = true,
["Shipindex"] = true,
["Sport index"] = true,
["Sportindex"] = true,
["Storm index"] = true,
["Surname"] = true,
["Surnames"] = true,
["DisambigName"] = true,
["DisambigNm"] = true,
["DisambigN"] = true,
}
nn9l9r1pmrobxspg0rm1qgng5nzu19x
9352
9351
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype/setindex]]
9351
Scribunto
text/plain
-- This page contains a table of all set index templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
["Set index article"] = true,
["Sia"] = true,
["Set index"] = true,
["SIA"] = true,
["Set-index"] = true,
["Setindex"] = true,
["Set-index article"] = true,
["Animal common name"] = true,
["Chemistry index"] = true,
["Chemdisambig"] = true,
["Chemistry disambiguation"] = true,
["Chemistry set index"] = true,
["Chemindex"] = true,
["Enzyme index"] = true,
["Fungus common name"] = true,
["Given name"] = true,
["First name"] = true,
["Forename"] = true,
["Greek myth index"] = true,
["Lake index"] = true,
["Lakeindex"] = true,
["Locomotive index"] = true,
["Media set index"] = true,
["Media index"] = true,
["Molecular formula index"] = true,
["MolFormDisambig"] = true,
["Molecular formula disambiguation"] = true,
["MolFormIndex"] = true,
["Mountain index"] = true,
["Mountainindex"] = true,
["Nickname"] = true,
["Painting index"] = true,
["Plant common name"] = true,
["River index"] = true,
["Road index"] = true,
["Roadindex"] = true,
["Ship index"] = true,
["Shipindex"] = true,
["Sport index"] = true,
["Sportindex"] = true,
["Storm index"] = true,
["Surname"] = true,
["Surnames"] = true,
["DisambigName"] = true,
["DisambigNm"] = true,
["DisambigN"] = true,
}
nn9l9r1pmrobxspg0rm1qgng5nzu19x
Module:Pagetype/rfd
828
1163
9353
2024-08-20T20:41:41Z
Pppery
320
Changed protection settings for "[[Module:Pagetype/rfd]]": The highest-use template on the project that's not currently fully protected ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9353
Scribunto
text/plain
-- This page contains a table of all RfD templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
-- Template forms (these should be substituted so we should rarely see these)
["Redirect for discussion"] = true,
["RFD"] = true,
["RfD"] = true,
["Rfd1"] = true,
["Rfd-t"] = true,
["Rfd"] = true,
["Rfd-NPF"] = true,
["Rfd-NPF/core"] = true,
-- Module forms
["#invoke:RfD"] = true,
["<includeonly>safesubst:</includeonly>#invoke:RfD"] = true, -- The form made by substituting RfD
}
9dx0g2c8g863kg6hcwx1wgsou16k45p
9354
9353
2026-08-23T08:17:47Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Pagetype/rfd]]
9353
Scribunto
text/plain
-- This page contains a table of all RfD templates and their
-- redirects. Templates names are capitalized, and the Template: prefix is
-- removed. Templates are grouped with the main template first, followed by
-- its redirects.
return {
-- Template forms (these should be substituted so we should rarely see these)
["Redirect for discussion"] = true,
["RFD"] = true,
["RfD"] = true,
["Rfd1"] = true,
["Rfd-t"] = true,
["Rfd"] = true,
["Rfd-NPF"] = true,
["Rfd-NPF/core"] = true,
-- Module forms
["#invoke:RfD"] = true,
["<includeonly>safesubst:</includeonly>#invoke:RfD"] = true, -- The form made by substituting RfD
}
9dx0g2c8g863kg6hcwx1wgsou16k45p
Tempilet:!!
10
1164
9358
2014-11-04T14:12:38Z
en>Pigsonthewing
0
stet
9358
wikitext
text/x-wiki
||<noinclude>
{{documentation}}
</noinclude>
o9jjx0pl1nk3xv3maqyewo5ud79pa5g
9359
9358
2026-08-23T08:31:03Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!!]]
9358
wikitext
text/x-wiki
||<noinclude>
{{documentation}}
</noinclude>
o9jjx0pl1nk3xv3maqyewo5ud79pa5g
Tempilet:Nowrap
10
1165
9360
2015-11-28T10:13:53Z
en>Edokter
0
Adapt comment; edits inside noinclude blocks should not affect job queue, but won't kill parser either way.
9360
wikitext
text/x-wiki
<span class="nowrap">{{{1}}}</span><noinclude>
{{documentation}}
<!-- Categories go on the /doc page; interwikis go to Wikidata. -->
</noinclude>
avb5tcymgupik1ikutqclidkj9tnitx
9361
9360
2026-08-23T08:31:03Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Nowrap]]
9360
wikitext
text/x-wiki
<span class="nowrap">{{{1}}}</span><noinclude>
{{documentation}}
<!-- Categories go on the /doc page; interwikis go to Wikidata. -->
</noinclude>
avb5tcymgupik1ikutqclidkj9tnitx
Tempilet:Pipe
10
1166
9364
2022-09-27T13:42:50Z
en>Ymblanter
0
Protected "[[Template:Pipe]]": [[WP:High-risk templates|Highly visible template]]: request at [[WP:RFPP]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9364
wikitext
text/x-wiki
|<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage -->
</noinclude>
5edw5gzp5q8wdkv58s32kzu46ex9w8t
9365
9364
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pipe]]
9364
wikitext
text/x-wiki
|<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage -->
</noinclude>
5edw5gzp5q8wdkv58s32kzu46ex9w8t
Tempilet:!((
10
1167
9366
2020-11-08T16:32:29Z
en>Pppery
0
Undid revision 987674468 by [[Special:Contributions/Primefac|Primefac]] ([[User talk:Primefac|talk]]) [[Wikipedia:Village_pump_(technical)#Template:!((_broken?]]
9366
wikitext
text/x-wiki
[[<noinclude>{{documentation}}</noinclude>
kx6wfr2em4x51ldy401n0q58z3lvxb8
9367
9366
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!((]]
9366
wikitext
text/x-wiki
[[<noinclude>{{documentation}}</noinclude>
kx6wfr2em4x51ldy401n0q58z3lvxb8
Tempilet:))!
10
1168
9368
2014-08-07T05:34:06Z
en>Plastikspork
0
Protected Template:))!: [[WP:High-risk templates|Highly visible template]] ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))
9368
wikitext
text/x-wiki
]]<noinclude>{{documentation}}</noinclude>
9eedfl8595z67nnifo09swq3y20vmvs
9369
9368
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:))!]]
9368
wikitext
text/x-wiki
]]<noinclude>{{documentation}}</noinclude>
9eedfl8595z67nnifo09swq3y20vmvs
Tempilet:((
10
1169
9370
2015-11-13T02:17:23Z
en>Fuhghettaboutit
0
Changed protection level of Template:((: when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators] (indefinite)...
9370
wikitext
text/x-wiki
{{<noinclude>
{{documentation}}
</noinclude>
7ddca00qmssfls0dctzbj32xy1q28ir
9371
9370
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:((]]
9370
wikitext
text/x-wiki
{{<noinclude>
{{documentation}}
</noinclude>
7ddca00qmssfls0dctzbj32xy1q28ir
Tempilet:))
10
1170
9372
2022-02-23T02:26:26Z
en>Xaosflux
0
Changed protection settings for "[[Template:))]]": 100K+uses ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9372
wikitext
text/x-wiki
}}<noinclude>
{{documentation}}
</noinclude>
fmm8htexq13hwrjrvzcsiy59gv65l36
9373
9372
2026-08-23T08:31:04Z
RAPTOR7762
18
1 revision imported from [[:en:Template:))]]
9372
wikitext
text/x-wiki
}}<noinclude>
{{documentation}}
</noinclude>
fmm8htexq13hwrjrvzcsiy59gv65l36
Tempilet:Always substitute
10
1171
9374
2026-08-13T09:25:48Z
en>Oshwah
0
Dummy Edit: Accidentally pressed 'Enter' while typing edit summary. The last statement should've said, "the boolean conditions for 'auto' and 'nocat' now consistently default to "no" when set to a non-true string.
9374
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:Unsubst|main|$B=
{{Ombox
| style = text-align: center;
| name = Subst only
| type = notice
| text = This template <strong>{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may={{lc:{{{yesnomaybe}}}}} be [[Help:Substitution|substituted]]</strong> by using <!--
--><strong>{{{actualtemplate|{{template other|{{Tls|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default={{PAGENAME}}}}}}|{{Tlsu|{{FULLPAGENAME}}}}}}}}}</strong><!--
-->|not|never=should <em>{{lc:{{{yesnomaybe}}}}}</em> be [[Help:Substitution|substituted]]</strong> – use <!--
--><strong>{{{actualtemplate|{{template other|{{Tl|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default={{PAGENAME}}}}}}|{{Tlu|{{FULLPAGENAME}}}}}}}}}</strong><!--
-->|#default=should <em>always</em> be [[Help:Substitution|substituted]]</strong> – use <!--
--><strong>{{{actualtemplate|{{template other|{{Tls|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default=<includeonly>{{PAGENAME}}</includeonly><noinclude>Example</noinclude>}}}}|{{Tlsu|{{FULLPAGENAME}}}}}}}}}</strong>}}. <!--
-->{{#ifeq:{{yesno-no|{{{auto|}}}}}|yes|{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may|not|never=|#default=Any accidental transclusions will be automatically substituted by a bot.{{{1|}}}{{#ifeq:{{yesno-no|{{{nocat|<noinclude>true</noinclude>}}}}}|yes|<!--no categorization-->|{{#switch:{{SUBPAGENAME}}|doc|sandbox=|#default=[[Category:Wikipedia templates to be automatically substituted]]}}}}}}}} <!--
-->{{#if:{{{alt|}}}|{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may|not|never=|#default={{#ifeq:{{{auto|}}}|yes|<br/>}}For [[Help:Transclusion|transclusion]], use <strong>{{#ifeq:{{NAMESPACE:{{{alt}}}}}|Template|{{[[{{{alt}}}|{{PAGENAME:{{{alt}}}}}]]}}|{{Tlg|{{{alt}}}}}}}</strong> instead.}}}}
}}{{#ifeq:{{yesno-no|{{{nocat|<noinclude>true</noinclude>}}}}}|yes|<!--no categorization-->|{{#switch:{{SUBPAGENAME}}|doc|sandbox=|#default={{#switch:{{lc:{{{yesnomaybe|}}}}}
|not|never=[[Category:Wikipedia never-substituted templates]]
|can|may=<!--No applicable category-->
|#default=[[Category:Wikipedia substituted templates]]{{#ifexpr: 0{{Find page text |text=<!%-%- *{{NAMESPACE}}:[{{lc:{{str left|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}}}}{{uc:{{str left|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}}}}]{{str right|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}} *%-%-> |title={{FULLPAGENAME}} |plain=f}} > 0 | [[Category:Templates with matching hidden id]]}}
}}}}}}}}<includeonly>__EXPECTUNUSEDTEMPLATE__</includeonly><noinclude>
{{Documentation}}
</noinclude>
97ot5yef1a57x458n4y84wnemwq1wo3
9375
9374
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Always_substitute]]
9374
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:Unsubst|main|$B=
{{Ombox
| style = text-align: center;
| name = Subst only
| type = notice
| text = This template <strong>{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may={{lc:{{{yesnomaybe}}}}} be [[Help:Substitution|substituted]]</strong> by using <!--
--><strong>{{{actualtemplate|{{template other|{{Tls|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default={{PAGENAME}}}}}}|{{Tlsu|{{FULLPAGENAME}}}}}}}}}</strong><!--
-->|not|never=should <em>{{lc:{{{yesnomaybe}}}}}</em> be [[Help:Substitution|substituted]]</strong> – use <!--
--><strong>{{{actualtemplate|{{template other|{{Tl|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default={{PAGENAME}}}}}}|{{Tlu|{{FULLPAGENAME}}}}}}}}}</strong><!--
-->|#default=should <em>always</em> be [[Help:Substitution|substituted]]</strong> – use <!--
--><strong>{{{actualtemplate|{{template other|{{Tls|{{#switch:{{SUBPAGENAME}}|doc|sandbox={{BASEPAGENAME}}|#default=<includeonly>{{PAGENAME}}</includeonly><noinclude>Example</noinclude>}}}}|{{Tlsu|{{FULLPAGENAME}}}}}}}}}</strong>}}. <!--
-->{{#ifeq:{{yesno-no|{{{auto|}}}}}|yes|{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may|not|never=|#default=Any accidental transclusions will be automatically substituted by a bot.{{{1|}}}{{#ifeq:{{yesno-no|{{{nocat|<noinclude>true</noinclude>}}}}}|yes|<!--no categorization-->|{{#switch:{{SUBPAGENAME}}|doc|sandbox=|#default=[[Category:Wikipedia templates to be automatically substituted]]}}}}}}}} <!--
-->{{#if:{{{alt|}}}|{{#switch:{{lc:{{{yesnomaybe|}}}}}|can|may|not|never=|#default={{#ifeq:{{{auto|}}}|yes|<br/>}}For [[Help:Transclusion|transclusion]], use <strong>{{#ifeq:{{NAMESPACE:{{{alt}}}}}|Template|{{[[{{{alt}}}|{{PAGENAME:{{{alt}}}}}]]}}|{{Tlg|{{{alt}}}}}}}</strong> instead.}}}}
}}{{#ifeq:{{yesno-no|{{{nocat|<noinclude>true</noinclude>}}}}}|yes|<!--no categorization-->|{{#switch:{{SUBPAGENAME}}|doc|sandbox=|#default={{#switch:{{lc:{{{yesnomaybe|}}}}}
|not|never=[[Category:Wikipedia never-substituted templates]]
|can|may=<!--No applicable category-->
|#default=[[Category:Wikipedia substituted templates]]{{#ifexpr: 0{{Find page text |text=<!%-%- *{{NAMESPACE}}:[{{lc:{{str left|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}}}}{{uc:{{str left|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}}}}]{{str right|{{Lua escape|{{{1|{{PAGENAME}}}}}}}|1}} *%-%-> |title={{FULLPAGENAME}} |plain=f}} > 0 | [[Category:Templates with matching hidden id]]}}
}}}}}}}}<includeonly>__EXPECTUNUSEDTEMPLATE__</includeonly><noinclude>
{{Documentation}}
</noinclude>
97ot5yef1a57x458n4y84wnemwq1wo3
Tempilet:(
10
1172
9376
2015-11-13T02:17:23Z
en>Fuhghettaboutit
0
Changed protection level of Template:(: when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators] (indefinite) [...
9376
wikitext
text/x-wiki
{<noinclude>
{{documentation}}
</noinclude>
bo68003d0rx5gzaxu8kxrb3a6qyoyjo
9377
9376
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:(]]
9376
wikitext
text/x-wiki
{<noinclude>
{{documentation}}
</noinclude>
bo68003d0rx5gzaxu8kxrb3a6qyoyjo
Tempilet:)
10
1173
9378
2015-11-13T02:17:23Z
en>Fuhghettaboutit
0
Changed protection level of Template:): when I changed this to add template editors, I didn't realize it had cascding protection—so all my change did was make it appear as if it could be edited by them ([Edit=Allow only administrators] (indefinite) [...
9378
wikitext
text/x-wiki
}<noinclude>
{{documentation}}
</noinclude>
trjzkxjnoc4j3s8syx7lt7qs0fnlhua
9379
9378
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:)]]
9378
wikitext
text/x-wiki
}<noinclude>
{{documentation}}
</noinclude>
trjzkxjnoc4j3s8syx7lt7qs0fnlhua
Tempilet:No wrap
10
1174
9380
2026-04-18T03:39:26Z
en>Pppery
0
Changed protection settings for "[[Template:No wrap]]" ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9380
wikitext
text/x-wiki
#Redirect [[Template:Nowrap]]
{{Rcat shell|
{{R from modification}}
{{R from template shortcut}}
}}
cv5x5byf5ysyp5qrels2k59tsrtgwhe
9381
9380
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:No_wrap]]
9380
wikitext
text/x-wiki
#Redirect [[Template:Nowrap]]
{{Rcat shell|
{{R from modification}}
{{R from template shortcut}}
}}
cv5x5byf5ysyp5qrels2k59tsrtgwhe
Tempilet:(((
10
1175
9382
2025-01-21T16:39:02Z
208.114.63.4
9382
wikitext
text/x-wiki
{{{<noinclude>
{{documentation}}
</noinclude>
p09oe358xifexyxixwqlowpxpmqlo9g
9383
9382
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:(((]]
9382
wikitext
text/x-wiki
{{{<noinclude>
{{documentation}}
</noinclude>
p09oe358xifexyxixwqlowpxpmqlo9g
Tempilet:)))
10
1176
9384
2019-03-23T17:18:06Z
en>John of Reading
0
Reverted 1 edit by [[Special:Contributions/103.77.60.42|103.77.60.42]] ([[User talk:103.77.60.42|talk]]) to last revision by Zenexer ([[WP:TW|TW]])
9384
wikitext
text/x-wiki
}}}<noinclude>
{{Documentation}}
</noinclude>
002a69ugw3az2pvs9vxuj7ng65ojzln
9385
9384
2026-08-23T08:31:05Z
RAPTOR7762
18
1 revision imported from [[:en:Template:)))]]
9384
wikitext
text/x-wiki
}}}<noinclude>
{{Documentation}}
</noinclude>
002a69ugw3az2pvs9vxuj7ng65ojzln
Tempilet:)!
10
1177
9386
2023-11-06T02:11:08Z
en>JPxG
0
whitespace
9386
wikitext
text/x-wiki
]<noinclude>
{{documentation}}</noinclude>
05x8ly4kzqrmn4t2xzp01wmyex95anx
9387
9386
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:)!]]
9386
wikitext
text/x-wiki
]<noinclude>
{{documentation}}</noinclude>
05x8ly4kzqrmn4t2xzp01wmyex95anx
Tempilet:!(
10
1178
9388
2013-11-02T02:26:45Z
en>Fuhghettaboutit
0
Changed protection level of Template:!(: Enable access by template editors ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template editors and admins] (indefinite))
9388
wikitext
text/x-wiki
[<noinclude>{{documentation}}</noinclude>
6vijsq3zwt5xugaaojfotqflpcklz8r
9389
9388
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!(]]
9388
wikitext
text/x-wiki
[<noinclude>{{documentation}}</noinclude>
6vijsq3zwt5xugaaojfotqflpcklz8r
Tempilet:Never substitute
10
1179
9390
2026-08-11T12:16:54Z
en>Oshwah
0
Add noinclude to example when directly viewed.
9390
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke: Unsubst||$B=
{{Always substitute|yesnomaybe=never|nocat={{{nocat|}}}<noinclude>|actualtemplate={{[[Template:Example|Example]]}}</noinclude>}}
}}<noinclude>
{{Documentation}}
</noinclude>
02wsjbeniz85kn3s45oqw6d0fj6qiyc
9391
9390
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Never_substitute]]
9390
wikitext
text/x-wiki
{{safesubst:<noinclude />#invoke: Unsubst||$B=
{{Always substitute|yesnomaybe=never|nocat={{{nocat|}}}<noinclude>|actualtemplate={{[[Template:Example|Example]]}}</noinclude>}}
}}<noinclude>
{{Documentation}}
</noinclude>
02wsjbeniz85kn3s45oqw6d0fj6qiyc
Tempilet:High-risk
10
1180
9392
2023-04-09T16:46:44Z
en>Nagsb
0
9392
wikitext
text/x-wiki
#REDIRECT [[Template:High-use]]
{{Rcat shell|
{{R with Wikidata item}}
{{R from merge}}
{{R from template shortcut}}
}}
9o509tuzggiizv8673s2ucyx82hdjgp
9393
9392
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:High-risk]]
9392
wikitext
text/x-wiki
#REDIRECT [[Template:High-use]]
{{Rcat shell|
{{R with Wikidata item}}
{{R from merge}}
{{R from template shortcut}}
}}
9o509tuzggiizv8673s2ucyx82hdjgp
Tempilet:Escape template list
10
1181
9394
2026-05-01T14:49:20Z
en>Andrybak
0
Show navbar for demonstration purposes (no need for <includeonly></includeonly> here). Fix usage of parameter `style`. Link to [[mw:Help:Magic words#Escaped characters]]. Clean up wikitext.
9394
wikitext
text/x-wiki
{| class="wikitable" style="text-align: center;"
|+ {{Navbar|Escape template list|text=This table:|style=float: right;}}
|-
! scope="col" style="width: 7.0em;" | {{no wrap|Template call}}<br />{{normal|('''m''' for [[mw:Help:Magic words#Escaped characters|magic word]])}} !! scope="col" style="width: 5.75em;" | {{no wrap|Output}} {{normal|(delayed interpretation as wikimarkup)}} !! scope="col" style="width: 9.0em;" | {{no wrap|HTML alternative}} {{normal|(never interpreted as wikimarkup)}}
|-
| <code><nowiki>{{!}}</nowiki></code> '''(m)''' || {{pipe}} || <code>&#124;</code> or {{tl|pipe}}
|-
| <code><nowiki>{{=}}</nowiki></code> '''(m)''' || <nowiki>=</nowiki> || <code>&#61;</code>
|-
| {{tlx|!!}} || {{pipe}}{{pipe}} || <code>&#124;&#124;</code>
|-
| {{tlx|!(}} || {{!(}} || <code>&#91;</code>
|-
| {{tlx|)!}} || {{)!}} || <code>&#93;</code>
|-
| {{tlx|!((}} || {{!((}} || <code>&#91;&#91;</code>
|-
| {{tlx|))!}} || {{))!}} || <code>&#93;&#93;</code>
|-
| {{tlx|(}} || {{(}} || <code>&#123;</code>
|-
| {{tlx|)}} || {{)}} || <code>&#125;</code>
|-
| {{tlx|((}} || {{((}} || <code>&#123;&#123;</code>
|-
| {{tlx|))}} || {{))}} || <code>&#125;&#125;</code>
|-
| {{tlx|(((}} || {{(((}} || <code>&#123;&#123;&#123;</code>
|-
| {{tlx|)))}} || {{)))}} || <code>&#125;&#125;&#125;</code>
|-
| {{tlx|(!}} || <nowiki>{|</nowiki> || <code>&#123;&#124;</code>
|-
| {{tlx|!+}} || <nowiki>|+</nowiki> || <code>&#124;&#43;</code>
|-
| {{tlx|!-}} || <nowiki>|-</nowiki> || <code>&#124;&#45;</code>
|-
| {{tlx|!)}} || <nowiki>|}</nowiki> || <code>&#124;&#125;</code>
|}<noinclude>
{{Documentation}}
</noinclude>
j687znpkr29pbhhko5hfb2tyd5e76hp
9395
9394
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Escape_template_list]]
9394
wikitext
text/x-wiki
{| class="wikitable" style="text-align: center;"
|+ {{Navbar|Escape template list|text=This table:|style=float: right;}}
|-
! scope="col" style="width: 7.0em;" | {{no wrap|Template call}}<br />{{normal|('''m''' for [[mw:Help:Magic words#Escaped characters|magic word]])}} !! scope="col" style="width: 5.75em;" | {{no wrap|Output}} {{normal|(delayed interpretation as wikimarkup)}} !! scope="col" style="width: 9.0em;" | {{no wrap|HTML alternative}} {{normal|(never interpreted as wikimarkup)}}
|-
| <code><nowiki>{{!}}</nowiki></code> '''(m)''' || {{pipe}} || <code>&#124;</code> or {{tl|pipe}}
|-
| <code><nowiki>{{=}}</nowiki></code> '''(m)''' || <nowiki>=</nowiki> || <code>&#61;</code>
|-
| {{tlx|!!}} || {{pipe}}{{pipe}} || <code>&#124;&#124;</code>
|-
| {{tlx|!(}} || {{!(}} || <code>&#91;</code>
|-
| {{tlx|)!}} || {{)!}} || <code>&#93;</code>
|-
| {{tlx|!((}} || {{!((}} || <code>&#91;&#91;</code>
|-
| {{tlx|))!}} || {{))!}} || <code>&#93;&#93;</code>
|-
| {{tlx|(}} || {{(}} || <code>&#123;</code>
|-
| {{tlx|)}} || {{)}} || <code>&#125;</code>
|-
| {{tlx|((}} || {{((}} || <code>&#123;&#123;</code>
|-
| {{tlx|))}} || {{))}} || <code>&#125;&#125;</code>
|-
| {{tlx|(((}} || {{(((}} || <code>&#123;&#123;&#123;</code>
|-
| {{tlx|)))}} || {{)))}} || <code>&#125;&#125;&#125;</code>
|-
| {{tlx|(!}} || <nowiki>{|</nowiki> || <code>&#123;&#124;</code>
|-
| {{tlx|!+}} || <nowiki>|+</nowiki> || <code>&#124;&#43;</code>
|-
| {{tlx|!-}} || <nowiki>|-</nowiki> || <code>&#124;&#45;</code>
|-
| {{tlx|!)}} || <nowiki>|}</nowiki> || <code>&#124;&#125;</code>
|}<noinclude>
{{Documentation}}
</noinclude>
j687znpkr29pbhhko5hfb2tyd5e76hp
Tempilet:Normal
10
1182
9396
2023-05-10T17:59:43Z
en>MusikBot II
0
Protected "[[Template:Normal]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 5871 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9396
wikitext
text/x-wiki
<span style{{=}}"font-weight:normal; font-style:normal">{{{1}}}</span><noinclude>
{{documentation}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS -->
</noinclude>
by5g2x3z4239sbhbwj4w94fvh04nsbn
9397
9396
2026-08-23T08:31:06Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Normal]]
9396
wikitext
text/x-wiki
<span style{{=}}"font-weight:normal; font-style:normal">{{{1}}}</span><noinclude>
{{documentation}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS -->
</noinclude>
by5g2x3z4239sbhbwj4w94fvh04nsbn
Module:Transclusion count/data/other
828
1183
9398
2026-08-23T05:11:45Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9398
Scribunto
text/plain
return {
["!!"] = 249000,
["!(("] = 548000,
["!)"] = 304000,
["!-"] = 32000,
["!tq"] = 2100,
["!xt"] = 8800,
["\"'"] = 3400,
["'"] = 98000,
["'\""] = 8000,
["'-"] = 4300,
["'_\""] = 2500,
["'s"] = 26000,
["(!"] = 300000,
["(("] = 122000,
["(Dis)establishments_in_year_category_header"] = 2500,
["(Dis)establishments_in_year_category_header/core"] = 2500,
[")"] = 4500,
["))"] = 121000,
["))!"] = 17000,
["*"] = 106000,
["+1"] = 2000,
[","] = 3800,
["-"] = 467000,
["-\""] = 7200,
["-'"] = 2500,
["----"] = 3900,
["-?"] = 4800,
["-Class"] = 11000,
["-r"] = 554000,
["0"] = 54000,
["16TeamBracket"] = 6700,
["16TeamBracket-Compact-Tennis3"] = 10000,
["16TeamBracket-Compact-Tennis3-Byes"] = 9800,
["1x"] = 7000,
["20th_Century_Press_Archives"] = 3400,
["2TeamBracket"] = 3700,
["4TeamBracket"] = 7300,
["4TeamBracket-Tennis3"] = 11000,
["50k_Invite"] = 3700,
["8TeamBracket"] = 7400,
["8TeamBracket-Tennis3"] = 4200,
["90minut"] = 2500,
[";"] = 517000,
["=)"] = 13000,
["@"] = 6300,
["\\"] = 26000,
["^"] = 4600,
["`"] = 4500,
["`s"] = 9300,
["±"] = 5800,
["·"] = 143000,
["•"] = 200000,
}
cpfpwkcu394t83zo205fwp3nzgabzl3
9399
9398
2026-08-23T08:31:07Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/other]]
9398
Scribunto
text/plain
return {
["!!"] = 249000,
["!(("] = 548000,
["!)"] = 304000,
["!-"] = 32000,
["!tq"] = 2100,
["!xt"] = 8800,
["\"'"] = 3400,
["'"] = 98000,
["'\""] = 8000,
["'-"] = 4300,
["'_\""] = 2500,
["'s"] = 26000,
["(!"] = 300000,
["(("] = 122000,
["(Dis)establishments_in_year_category_header"] = 2500,
["(Dis)establishments_in_year_category_header/core"] = 2500,
[")"] = 4500,
["))"] = 121000,
["))!"] = 17000,
["*"] = 106000,
["+1"] = 2000,
[","] = 3800,
["-"] = 467000,
["-\""] = 7200,
["-'"] = 2500,
["----"] = 3900,
["-?"] = 4800,
["-Class"] = 11000,
["-r"] = 554000,
["0"] = 54000,
["16TeamBracket"] = 6700,
["16TeamBracket-Compact-Tennis3"] = 10000,
["16TeamBracket-Compact-Tennis3-Byes"] = 9800,
["1x"] = 7000,
["20th_Century_Press_Archives"] = 3400,
["2TeamBracket"] = 3700,
["4TeamBracket"] = 7300,
["4TeamBracket-Tennis3"] = 11000,
["50k_Invite"] = 3700,
["8TeamBracket"] = 7400,
["8TeamBracket-Tennis3"] = 4200,
["90minut"] = 2500,
[";"] = 517000,
["=)"] = 13000,
["@"] = 6300,
["\\"] = 26000,
["^"] = 4600,
["`"] = 4500,
["`s"] = 9300,
["±"] = 5800,
["·"] = 143000,
["•"] = 200000,
}
cpfpwkcu394t83zo205fwp3nzgabzl3
Tempilet:!!/doc
10
1184
9400
2026-06-28T12:35:21Z
en>Primefac
0
rmv cat which says it's for single characters
9400
wikitext
text/x-wiki
{{Documentation subpage}}
{{High-risk}}
{{Never substitute}}
This is an auxiliary [[Help:Template|template]] that allows one to encode "<code>||</code>" (two pipes or [[vertical bar]]s) within template parameters. If this does not need to be interpreted as wikitext (i.e. table cell separators), it is better to use "<code>&#124;&#124;</code>". However the "<code>||</code>" delimiter for a [[Wikipedia:Manual of Style/Tables|wikitable]] has to be [[:Category:Character-substitution templates|escaped by a template]] if it is used within a template.
This template extends the magic word <code><nowiki>{{!}}</nowiki></code>, which is used to escape a single [[vertical bar]] character.
== Notes ==
There is usually no such problem with "<code>!!</code>" (exclamation marks). This problem only affects "<code>||</code>" (vertical bars) in conjunction with the [[m:Help:Parameter default|Help:Parameter default]] mechanism within tables. However, in table rows starting with "<code>!</code>" there can be problems with "<code>!!</code>" being interpreted as a cell separator. Try replacing it with "<code>&#33;&#33;</code>".
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "Escapes double pipe characters within template parameters",
"params": {}
}</templatedata>
== See also ==
{{Escape template list}}
*[[mw:Help:Templates#Using pipes in parameter values]]
*[[Help:Conditional tables]]
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Template namespace templates]]
}}</includeonly>
c9fdwmhn9n4121bxcogeuf9xg5oaw9u
9401
9400
2026-08-23T08:31:07Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!!/doc]]
9400
wikitext
text/x-wiki
{{Documentation subpage}}
{{High-risk}}
{{Never substitute}}
This is an auxiliary [[Help:Template|template]] that allows one to encode "<code>||</code>" (two pipes or [[vertical bar]]s) within template parameters. If this does not need to be interpreted as wikitext (i.e. table cell separators), it is better to use "<code>&#124;&#124;</code>". However the "<code>||</code>" delimiter for a [[Wikipedia:Manual of Style/Tables|wikitable]] has to be [[:Category:Character-substitution templates|escaped by a template]] if it is used within a template.
This template extends the magic word <code><nowiki>{{!}}</nowiki></code>, which is used to escape a single [[vertical bar]] character.
== Notes ==
There is usually no such problem with "<code>!!</code>" (exclamation marks). This problem only affects "<code>||</code>" (vertical bars) in conjunction with the [[m:Help:Parameter default|Help:Parameter default]] mechanism within tables. However, in table rows starting with "<code>!</code>" there can be problems with "<code>!!</code>" being interpreted as a cell separator. Try replacing it with "<code>&#33;&#33;</code>".
== TemplateData ==
{{TemplateData header}}
<templatedata>{
"description": "Escapes double pipe characters within template parameters",
"params": {}
}</templatedata>
== See also ==
{{Escape template list}}
*[[mw:Help:Templates#Using pipes in parameter values]]
*[[Help:Conditional tables]]
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Template namespace templates]]
}}</includeonly>
c9fdwmhn9n4121bxcogeuf9xg5oaw9u
Tempilet:(!
10
1185
9402
2016-08-09T22:00:28Z
en>Renamed user mou89p43twvqcvm8ut9w3
0
Changed protection level of Template:(!: [[WP:High-risk templates|Highly visible template]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9402
wikitext
text/x-wiki
<includeonly>{|</includeonly><noinclude><nowiki>{|</nowiki>{{Documentation}}
</noinclude>
suugjngdajtu9ghvowyeqkomyxg6pqt
9403
9402
2026-08-23T10:32:24Z
RAPTOR7762
18
1 revision imported from [[:en:Template:(!]]
9402
wikitext
text/x-wiki
<includeonly>{|</includeonly><noinclude><nowiki>{|</nowiki>{{Documentation}}
</noinclude>
suugjngdajtu9ghvowyeqkomyxg6pqt
Tempilet:(!/doc
10
1186
9404
2025-06-26T17:19:43Z
208.114.63.4
9404
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
{{High-use}}
This templates produces the '''<code><nowiki>{|</nowiki></code>''' sequence (i.e., start of wikitable), so that wikitables can be built inside templates.
== Explanation ==
The problem is that if a pipe character "<code>{{pipe}}</code>" appears in a template, the template parser assumes that the pipe is part of the template; and so if there is a table within a template the pipe symbols that are usually interpreted as part of the table syntax will be interpreted first as part template.
To prevent this happening it is possible to "hide" the pipe character of the table from the template parser by substituting <code><nowiki>{{!}}</nowiki></code> for a pipe character.
To aid with building a table there are some additional template which can be used to help
* {{tlx|(!}} for <code><nowiki>{|</nowiki></code>
* {{tlx|!+}} for <code><nowiki>|+</nowiki></code>
* {{tlx|!-}} for <code><nowiki>|-</nowiki></code>
* {{tlx|!!}} for <code><nowiki>||</nowiki></code>
* {{tlx|!)}} for <code><nowiki>|}</nowiki></code>
See [[mw:Help:Magic words#Other]] and [[mw:Help:Template#A parameter value containing a pipe character]]
== See also ==
{{Escape template list}}
* {{tlx|End}}
* {{tlx|Aligned table}}, specify table directly as a template, contrasting the special handling of certain syntax above
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "This template produces {| as ordinary text.",
"params": {}
}
</templatedata>
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Character-substitution templates]]
}}</includeonly>
lx5pi76yb8g7613yun14w6olvcnt93l
9405
9404
2026-08-23T10:32:25Z
RAPTOR7762
18
1 revision imported from [[:en:Template:(!/doc]]
9404
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
{{High-use}}
This templates produces the '''<code><nowiki>{|</nowiki></code>''' sequence (i.e., start of wikitable), so that wikitables can be built inside templates.
== Explanation ==
The problem is that if a pipe character "<code>{{pipe}}</code>" appears in a template, the template parser assumes that the pipe is part of the template; and so if there is a table within a template the pipe symbols that are usually interpreted as part of the table syntax will be interpreted first as part template.
To prevent this happening it is possible to "hide" the pipe character of the table from the template parser by substituting <code><nowiki>{{!}}</nowiki></code> for a pipe character.
To aid with building a table there are some additional template which can be used to help
* {{tlx|(!}} for <code><nowiki>{|</nowiki></code>
* {{tlx|!+}} for <code><nowiki>|+</nowiki></code>
* {{tlx|!-}} for <code><nowiki>|-</nowiki></code>
* {{tlx|!!}} for <code><nowiki>||</nowiki></code>
* {{tlx|!)}} for <code><nowiki>|}</nowiki></code>
See [[mw:Help:Magic words#Other]] and [[mw:Help:Template#A parameter value containing a pipe character]]
== See also ==
{{Escape template list}}
* {{tlx|End}}
* {{tlx|Aligned table}}, specify table directly as a template, contrasting the special handling of certain syntax above
== TemplateData ==
{{TemplateData header}}
<templatedata>
{
"description": "This template produces {| as ordinary text.",
"params": {}
}
</templatedata>
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Character-substitution templates]]
}}</includeonly>
lx5pi76yb8g7613yun14w6olvcnt93l
Tempilet:!)
10
1187
9406
2018-12-16T17:33:17Z
en>Amorymeltzer
0
Changed protection level for "[[Template:!)]]": [[WP:High-risk templates|Highly visible template]]: 200k+ transclusions ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
9406
wikitext
text/x-wiki
|}<noinclude>
{{Documentation}}
</noinclude>
8apcw4qp5lvn6mmsnwmuhdas81mpdci
9407
9406
2026-08-23T10:32:44Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!)]]
9406
wikitext
text/x-wiki
|}<noinclude>
{{Documentation}}
</noinclude>
8apcw4qp5lvn6mmsnwmuhdas81mpdci
Tempilet:Thin space
10
1188
9408
2021-07-22T18:00:13Z
en>MusikBot II
0
Protected "[[Template:Thin space]]": [[Wikipedia:High-risk templates|High-risk template or module]] ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9408
wikitext
text/x-wiki
<span style="white-space: nowrap;">{{#if:{{{1|}}}|{{#if:{{{2|}}}|| }}}}{{{1|}}} <!--
-->{{#if:{{{2|}}}|{{{2}}}}}{{#if:{{{3|}}}| {{{3}}}}}<!--
-->{{#if:{{{4|}}}| {{{4}}}}}{{#if:{{{5|}}}| {{{5}}}}}<!--
-->{{#if:{{{6|}}}| {{{6}}}}}{{#if:{{{7|}}}| {{{7}}}}}<!--
-->{{#if:{{{8|}}}| {{{8}}}}}{{#if:{{{9|}}}| {{{9}}}}}<!--
-->{{#if:{{{10|}}}| {{{10}}}}}</span><noinclude>
{{Documentation}}
<!-- Please add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
b3t8ug596s2nqqnys55o7tsr76dnm00
9409
9408
2026-08-23T10:32:44Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Thin_space]]
9408
wikitext
text/x-wiki
<span style="white-space: nowrap;">{{#if:{{{1|}}}|{{#if:{{{2|}}}|| }}}}{{{1|}}} <!--
-->{{#if:{{{2|}}}|{{{2}}}}}{{#if:{{{3|}}}| {{{3}}}}}<!--
-->{{#if:{{{4|}}}| {{{4}}}}}{{#if:{{{5|}}}| {{{5}}}}}<!--
-->{{#if:{{{6|}}}| {{{6}}}}}{{#if:{{{7|}}}| {{{7}}}}}<!--
-->{{#if:{{{8|}}}| {{{8}}}}}{{#if:{{{9|}}}| {{{9}}}}}<!--
-->{{#if:{{{10|}}}| {{{10}}}}}</span><noinclude>
{{Documentation}}
<!-- Please add categories to the /doc subpage; interwikis go to Wikidata, thank you! -->
</noinclude>
b3t8ug596s2nqqnys55o7tsr76dnm00
Tempilet:Bracket
10
1189
9410
2024-12-25T18:19:37Z
en>Pppery
0
Spacing fix per requesy
9410
wikitext
text/x-wiki
{{#if:{{{1|}}}|[{{{1}}}]|[}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
7r29bwt37u6vwptrquqqg2w6lzvjmp9
9411
9410
2026-08-23T10:32:44Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Bracket]]
9410
wikitext
text/x-wiki
{{#if:{{{1|}}}|[{{{1}}}]|[}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage, interwikis to Wikidata, not here -->
</noinclude>
7r29bwt37u6vwptrquqqg2w6lzvjmp9
Tempilet:Brackets
10
1190
9412
2024-03-19T12:52:18Z
en>Cedar101
0
{{tlx}}
9412
wikitext
text/x-wiki
[[<nowiki/>{{{1}}}<nowiki/>]{{#if:{{{2|}}}|{{{2}}}}}]<noinclude>
{{Documentation
| content =
This template provides way to wrap content in double [[square brackets]].
Examples:
*{{tlx|brackets|test}} produces: {{brackets|test}}
*{{tlx|brackets|test{{!}}more}} produces: {{brackets|test{{!}}more}}
*{{tlx|brackets|:ja:山本五十六}} produces: {{brackets|:ja:山本五十六}}
== Function ==
===Function===
This template is a simple wrapper around the <code>&#91;&#91;</code> and <code>&#93;&#93;</code> [[HTML entities]] that produce starting and ending double brackets, respectively.
=== Limitations ===
The template cannot output just the starting double bracket or just the ending double bracket. You will have to use either <code>&#91;&#91;</code> or <code>&#93;&#93;</code> to achieve this.
===See also===
* {{tl|Braces}} — to wrap content in double [[curly brackets]]
* {{tl|Bracket}} — to wrap content in single [[square brackets]]
[[Category:Character-substitution templates]]
}}<!--(end Documentation)-->
</noinclude>
1qn6y7er9yy8fzq090800tdklex4n4g
9413
9412
2026-08-23T10:32:44Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Brackets]]
9412
wikitext
text/x-wiki
[[<nowiki/>{{{1}}}<nowiki/>]{{#if:{{{2|}}}|{{{2}}}}}]<noinclude>
{{Documentation
| content =
This template provides way to wrap content in double [[square brackets]].
Examples:
*{{tlx|brackets|test}} produces: {{brackets|test}}
*{{tlx|brackets|test{{!}}more}} produces: {{brackets|test{{!}}more}}
*{{tlx|brackets|:ja:山本五十六}} produces: {{brackets|:ja:山本五十六}}
== Function ==
===Function===
This template is a simple wrapper around the <code>&#91;&#91;</code> and <code>&#93;&#93;</code> [[HTML entities]] that produce starting and ending double brackets, respectively.
=== Limitations ===
The template cannot output just the starting double bracket or just the ending double bracket. You will have to use either <code>&#91;&#91;</code> or <code>&#93;&#93;</code> to achieve this.
===See also===
* {{tl|Braces}} — to wrap content in double [[curly brackets]]
* {{tl|Bracket}} — to wrap content in single [[square brackets]]
[[Category:Character-substitution templates]]
}}<!--(end Documentation)-->
</noinclude>
1qn6y7er9yy8fzq090800tdklex4n4g
Tempilet:Mset
10
1191
9414
2024-02-13T04:00:34Z
en>Quondum
0
compensating for weirdness of {{#if}}, which trims trailing space
9414
wikitext
text/x-wiki
<includeonly>{{(}}{{{1|}}}{{#if:{{{2|}}}|{{!}}{{{2}}}{{)}}|{{)}}}}</includeonly><noinclude>{{Documentation}}</noinclude>
egrr94609bn35x38pg63ro1mw6mbwjh
9415
9414
2026-08-23T10:32:45Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Mset]]
9414
wikitext
text/x-wiki
<includeonly>{{(}}{{{1|}}}{{#if:{{{2|}}}|{{!}}{{{2}}}{{)}}|{{)}}}}</includeonly><noinclude>{{Documentation}}</noinclude>
egrr94609bn35x38pg63ro1mw6mbwjh
Tempilet:Braces
10
1192
9416
2025-10-25T11:33:46Z
en>Primefac
0
need a tenth
9416
wikitext
text/x-wiki
{{#if:{{{code|{{{tt|}}}}}}|<code>}}<!--
-->{{((}}{{{1|{{thin space}}}}}<!--
-->{{#if:{{{2|}}} |{{thin space}}{{!}}{{thin space}}{{{2}}}}}<!--
-->{{#if:{{{3|}}} |{{thin space}}{{!}}{{thin space}}{{{3}}}}}<!--
-->{{#if:{{{4|}}} |{{thin space}}{{!}}{{thin space}}{{{4}}}}}<!--
-->{{#if:{{{5|}}} |{{thin space}}{{!}}{{thin space}}{{{5}}}}}<!--
-->{{#if:{{{6|}}} |{{thin space}}{{!}}{{thin space}}{{{6}}}}}<!--
-->{{#if:{{{7|}}} |{{thin space}}{{!}}{{thin space}}{{{7}}}}}<!--
-->{{#if:{{{8|}}} |{{thin space}}{{!}}{{thin space}}{{{8}}}}}<!--
-->{{#if:{{{9|}}} |{{thin space}}{{!}}{{thin space}}{{{9}}}}}<!--
-->{{#if:{{{10|}}} |{{thin space}}{{!}}{{thin space}}{{{10}}}}}<!--
-->{{))}}<!--
-->{{#if:{{{code|{{{tt|}}}}}}|</code>}}<noinclude>{{Documentation}}</noinclude>
rewjd17h23cnazchf18utdfl6cf4300
9417
9416
2026-08-23T10:32:45Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Braces]]
9416
wikitext
text/x-wiki
{{#if:{{{code|{{{tt|}}}}}}|<code>}}<!--
-->{{((}}{{{1|{{thin space}}}}}<!--
-->{{#if:{{{2|}}} |{{thin space}}{{!}}{{thin space}}{{{2}}}}}<!--
-->{{#if:{{{3|}}} |{{thin space}}{{!}}{{thin space}}{{{3}}}}}<!--
-->{{#if:{{{4|}}} |{{thin space}}{{!}}{{thin space}}{{{4}}}}}<!--
-->{{#if:{{{5|}}} |{{thin space}}{{!}}{{thin space}}{{{5}}}}}<!--
-->{{#if:{{{6|}}} |{{thin space}}{{!}}{{thin space}}{{{6}}}}}<!--
-->{{#if:{{{7|}}} |{{thin space}}{{!}}{{thin space}}{{{7}}}}}<!--
-->{{#if:{{{8|}}} |{{thin space}}{{!}}{{thin space}}{{{8}}}}}<!--
-->{{#if:{{{9|}}} |{{thin space}}{{!}}{{thin space}}{{{9}}}}}<!--
-->{{#if:{{{10|}}} |{{thin space}}{{!}}{{thin space}}{{{10}}}}}<!--
-->{{))}}<!--
-->{{#if:{{{code|{{{tt|}}}}}}|</code>}}<noinclude>{{Documentation}}</noinclude>
rewjd17h23cnazchf18utdfl6cf4300
Tempilet:Auxiliary template common notice
10
1193
9418
2021-09-12T08:40:51Z
en>Ans
0
/* See also */ +(())
9418
wikitext
text/x-wiki
__NOTOC__
Use this template to produce the [[Character (computing)|character]] or characters "{{thin space|<includeonly>{{ {{BASEPAGENAME}} }}</includeonly><noinclude>{{small|[''character/s appear here'']}}</noinclude>}}" as ordinary text rather than as part of a link <code><nowiki>[[ ]]</nowiki></code>, [[Wikipedia:Transclusion|transclusion]] <code><nowiki>{{ }}</nowiki></code>, variable <code><nowiki>{{{ }}}</nowiki></code>, etc.<!--
-->{{#if:{{{entity|}}} |<br/>The [[Character encodings in HTML#HTML character references|HTML character code]] "<code>&{{{entity}}};</code>" may also be used, which will never be interpreted as markup even if nested in multiple templates or similar.}}
==Similar templates==
{{Escape template list}}
==See also==
* [[Template:\|Template:{{thin space|\}}]], which produces " <nowiki>/</nowiki>" (i.e. a [[Slash (punctuation)|slash]] character preceded by a [[non-breaking space]])
* [[Template:Square bracket open]], which produces "{{thin space|[}}" or, as <kbd><nowiki>{{square bracket open|2}}</nowiki></kbd>, "{{thin space|<nowiki>[[</nowiki>}}"
* [[Template:Square bracket close]], which produces "{{thin space|]}}" or, as <kbd><nowiki>{{square bracket close|2}}</nowiki></kbd>, "{{thin space|<nowiki>]]</nowiki>}}"
The following templates enclose text inside the indicated symbols:
* [[Template:Braces]], to produce text such as "{{braces|example text}}" (without triggering a transclusion)
* [[Template:(())]], like [[Template:Braces]], except that this does not produce html markup, so that it can be processed and expanded by Lua <code>frame:preprocess()</code> function
* [[Template:Brackets]], to produce text such as "{{brackets|example text}}" (without triggering a wikilink)
* [[Template:Bracket]], to produce text such as "{{bracket|example text}}" or "{{bracket|[[example text]]}}"
* [[Template:Mset]], to produce text such as "{{mset|1, 2, ..., N}}" (i.e., a mathematical set)
* [[Template:Tlf]], to produce text such as "{{tlf|example text}}" (without triggering a transclusion)
<includeonly>{{Sandbox other||
[[Category:Template namespace templates]]
}}</includeonly><noinclude>
[[Category:Documentation shared content templates]]
</noinclude>
14aoe3affwssnox3r9emjz1egmzptxl
9419
9418
2026-08-23T10:32:45Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Auxiliary_template_common_notice]]
9418
wikitext
text/x-wiki
__NOTOC__
Use this template to produce the [[Character (computing)|character]] or characters "{{thin space|<includeonly>{{ {{BASEPAGENAME}} }}</includeonly><noinclude>{{small|[''character/s appear here'']}}</noinclude>}}" as ordinary text rather than as part of a link <code><nowiki>[[ ]]</nowiki></code>, [[Wikipedia:Transclusion|transclusion]] <code><nowiki>{{ }}</nowiki></code>, variable <code><nowiki>{{{ }}}</nowiki></code>, etc.<!--
-->{{#if:{{{entity|}}} |<br/>The [[Character encodings in HTML#HTML character references|HTML character code]] "<code>&{{{entity}}};</code>" may also be used, which will never be interpreted as markup even if nested in multiple templates or similar.}}
==Similar templates==
{{Escape template list}}
==See also==
* [[Template:\|Template:{{thin space|\}}]], which produces " <nowiki>/</nowiki>" (i.e. a [[Slash (punctuation)|slash]] character preceded by a [[non-breaking space]])
* [[Template:Square bracket open]], which produces "{{thin space|[}}" or, as <kbd><nowiki>{{square bracket open|2}}</nowiki></kbd>, "{{thin space|<nowiki>[[</nowiki>}}"
* [[Template:Square bracket close]], which produces "{{thin space|]}}" or, as <kbd><nowiki>{{square bracket close|2}}</nowiki></kbd>, "{{thin space|<nowiki>]]</nowiki>}}"
The following templates enclose text inside the indicated symbols:
* [[Template:Braces]], to produce text such as "{{braces|example text}}" (without triggering a transclusion)
* [[Template:(())]], like [[Template:Braces]], except that this does not produce html markup, so that it can be processed and expanded by Lua <code>frame:preprocess()</code> function
* [[Template:Brackets]], to produce text such as "{{brackets|example text}}" (without triggering a wikilink)
* [[Template:Bracket]], to produce text such as "{{bracket|example text}}" or "{{bracket|[[example text]]}}"
* [[Template:Mset]], to produce text such as "{{mset|1, 2, ..., N}}" (i.e., a mathematical set)
* [[Template:Tlf]], to produce text such as "{{tlf|example text}}" (without triggering a transclusion)
<includeonly>{{Sandbox other||
[[Category:Template namespace templates]]
}}</includeonly><noinclude>
[[Category:Documentation shared content templates]]
</noinclude>
14aoe3affwssnox3r9emjz1egmzptxl
Tempilet:!)/doc
10
1194
9420
2025-12-31T12:52:16Z
en>DB1729
0
Reverted 2 edits by [[Special:Contributions/~2025-44101-30|~2025-44101-30]] ([[User talk:~2025-44101-30|talk]]) to last revision by ExE Boss
9420
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AT THE BOTTOM OF THIS PAGE -->
{{High-use|200000+}}
{{Auxiliary template common notice|entity=#124;&#125}}
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Character-substitution templates]]
}}</includeonly>
dencbkx69d61ab02w98uqme90tqp0t3
9421
9420
2026-08-23T10:32:45Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!)/doc]]
9420
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AT THE BOTTOM OF THIS PAGE -->
{{High-use|200000+}}
{{Auxiliary template common notice|entity=#124;&#125}}
<includeonly>{{Sandbox other||
[[Category:Templates with partial table wikitext]]
[[Category:Character-substitution templates]]
}}</includeonly>
dencbkx69d61ab02w98uqme90tqp0t3
Tempilet:Hlist
10
1195
9422
2026-08-20T02:40:59Z
en>Wbm1058
0
notify protected page of requested move
9422
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Horizontal list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude>{{<includeonly>safesubst:</includeonly>#invoke:list|horizontal}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
4bbaviz1ygasi1jjgur897t97i2qbpi
9423
9422
2026-08-23T10:37:52Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Hlist]]
9422
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Horizontal list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude>{{<includeonly>safesubst:</includeonly>#invoke:list|horizontal}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
4bbaviz1ygasi1jjgur897t97i2qbpi
9528
9423
2026-08-23T10:40:46Z
RAPTOR7762
18
9528
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|horizontal}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
ihcdy525o8nnmq114czc48dpk6pnojd
9529
9528
2026-08-23T10:41:05Z
RAPTOR7762
18
Protected "[[Tempilet:Hlist]]" ([Ramu=Allow only administrators] (indefinite) [Zeme=Allow only administrators] (indefinite)) [cascading]
9528
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|horizontal}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
ihcdy525o8nnmq114czc48dpk6pnojd
Tempilet:Flatlist
10
1196
9424
2026-08-20T02:43:39Z
en>Wbm1058
0
notify protected page of requested move
9424
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Flat list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude><templatestyles src="Hlist/styles.css"/><div class="hlist {{{class|}}}" {{#if:{{{style|}}}{{{indent|}}}|style="{{#if:{{{indent|}}}|margin-left: {{#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}"}}>{{#if:{{{1|}}}|
{{{1}}}
</div>}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using flatlist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Flatlist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | class | indent | style }}<noinclude></div><!-- Needed to prevent Linter errors here; when Flatlist without parameters is used to start a list, Endflatlist provides the closing /div tag. -->
{{documentation}}
</noinclude>
ahdzwtj48lbvqiseivd08z3ozk637ls
9425
9424
2026-08-23T10:37:52Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Flatlist]]
9424
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Flat list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude><templatestyles src="Hlist/styles.css"/><div class="hlist {{{class|}}}" {{#if:{{{style|}}}{{{indent|}}}|style="{{#if:{{{indent|}}}|margin-left: {{#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}"}}>{{#if:{{{1|}}}|
{{{1}}}
</div>}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using flatlist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Flatlist]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | class | indent | style }}<noinclude></div><!-- Needed to prevent Linter errors here; when Flatlist without parameters is used to start a list, Endflatlist provides the closing /div tag. -->
{{documentation}}
</noinclude>
ahdzwtj48lbvqiseivd08z3ozk637ls
Tempilet:Unbulleted list
10
1197
9426
2019-12-09T17:31:16Z
en>Jonesey95
0
Undid revision 929522913 by [[Special:Contributions/MSGJ|MSGJ]] ([[User talk:MSGJ|talk]]). Reverted, as this change has been shown to have bugs. Discussion continues on talk page.
9426
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|unbulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
g28jpumica8ycuimxbfi2qlrcbowsb3
9427
9426
2026-08-23T10:37:53Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Unbulleted_list]]
9426
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|unbulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
g28jpumica8ycuimxbfi2qlrcbowsb3
Tempilet:-
10
1198
9428
2017-03-12T14:41:31Z
en>Paine Ellsworth
0
add [[WP:RCAT|rcat]]
9428
wikitext
text/x-wiki
#REDIRECT [[Template:Clear]]
{{Redirect category shell|
{{R from modification}}
{{R from template shortcut}}
}}
7ftw22ju220o4mhfryrhdhdanb4vzun
9429
9428
2026-08-23T10:37:53Z
RAPTOR7762
18
1 revision imported from [[:en:Template:-]]
9428
wikitext
text/x-wiki
#REDIRECT [[Template:Clear]]
{{Redirect category shell|
{{R from modification}}
{{R from template shortcut}}
}}
7ftw22ju220o4mhfryrhdhdanb4vzun
Tempilet:Plainlist
10
1199
9430
2026-08-20T02:44:58Z
en>Wbm1058
0
notify protected page of requested move
9430
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Plain list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude><templatestyles src="Plainlist/styles.css"/><div class="plainlist {{{class|}}}" {{safesubst<noinclude />:#if:{{{style|}}}{{{indent|}}}|style="{{safesubst<noinclude />:#if:{{{indent|}}}|margin-left: {{safesubst<noinclude />:#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}"}}>{{safesubst<noinclude />:#if:{{{1|}}}|
{{{1}}}
</div>}}{{#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 "_VALUE_"|ignoreblank=y| class | style | indent | 1 }}<noinclude></div>
{{documentation}}
</noinclude>
343yzr03qo8bw7sfchk7965now33h1i
9431
9430
2026-08-23T10:37:53Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Plainlist]]
9430
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Plain list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude><templatestyles src="Plainlist/styles.css"/><div class="plainlist {{{class|}}}" {{safesubst<noinclude />:#if:{{{style|}}}{{{indent|}}}|style="{{safesubst<noinclude />:#if:{{{indent|}}}|margin-left: {{safesubst<noinclude />:#expr:{{{indent}}}*1.6}}em;}} {{{style|}}}"}}>{{safesubst<noinclude />:#if:{{{1|}}}|
{{{1}}}
</div>}}{{#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 "_VALUE_"|ignoreblank=y| class | style | indent | 1 }}<noinclude></div>
{{documentation}}
</noinclude>
343yzr03qo8bw7sfchk7965now33h1i
Tempilet:Div col
10
1200
9432
2021-02-14T23:20:57Z
en>Matt Fitzpatrick
0
whitelist parameter class
9432
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{colwidth|}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{colwidth|}}}|column-width: {{{colwidth}}};}}{{#if:{{{gap|}}}|column-gap: {{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
-->{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}<!--
--></includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}<noinclude>
{{Documentation}}
</noinclude>
cwqp9gtrnaa6hga4rh0s9vzcnfwr54n
9433
9432
2026-08-23T10:37:53Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Div_col]]
9432
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{colwidth|}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{colwidth|}}}|column-width: {{{colwidth}}};}}{{#if:{{{gap|}}}|column-gap: {{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
-->{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}<!--
--></includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}<noinclude>
{{Documentation}}
</noinclude>
cwqp9gtrnaa6hga4rh0s9vzcnfwr54n
Tempilet:Div col/styles.css
10
1201
9434
2023-11-07T21:54:12Z
en>Izno
0
revert per talk page
9434
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
n7twp689l8hrwuefq6a9a414zrxegfw
9435
9434
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Div_col/styles.css]]
9434
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
n7twp689l8hrwuefq6a9a414zrxegfw
Tempilet:For loop
10
1202
9436
2018-07-23T22:55:18Z
en>Pppery
0
Merge complete
9436
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:For loop|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
26pm0milru0ru69zbzxe1y37xwy9bg7
9437
9436
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Template:For_loop]]
9436
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:For loop|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
26pm0milru0ru69zbzxe1y37xwy9bg7
Module:For loop
828
1203
9438
2025-04-03T16:31:32Z
en>Ahecht
0
add templatemain function for direct invocation
9438
Scribunto
text/plain
-- This module implements {{for loop}}.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local p = {}
function p.templatemain(frame)
return p.main(frame:newChild{title = "Template:For_loop"})
end
function p.main(frame)
local args = getArgs(frame, {
trim = false,
removeBlanks = false
})
return p._main(args)
end
function p._main(args)
local template = args['call'] or 'void'
local calltemplates = yesno(args.substall or "", true) or not mw.isSubsting()
local variableParam = args.pv
variableParam = tonumber(variableParam) or variableParam or 1 -- fix for positional parameters
local variableValPrefix = args.prefix or ''
local variableValPostfix = args.postfix or ''
local sep = args[1] or ''
local constantArgs = p.getConstants(args)
local variableVals = p.getVariableVals(args)
local result = ''
local addSeparator = false;
for _, v in ipairs(variableVals) do
v = mw.text.trim(v)
if #v > 0 or not yesno(args.skipBlanks) then
if addSeparator then
result = result .. sep
end
addSeparator = true;
local targs = constantArgs
targs[variableParam] = variableValPrefix .. v .. variableValPostfix
if calltemplates then
local output = p.callTemplate(template, targs)
if #mw.text.trim(output) == 0 then
addSeparator = false
end
result = result .. output
else
local makeTemplate = require('Module:Template invocation').invocation
result = result .. makeTemplate(template, targs)
end
end
end
return result
end
function p.getConstants(args)
local constantArgNums = p.getArgNums(args, 'pc', 'n')
local constantArgs = {}
for _, num in ipairs(constantArgNums) do
local keyArg = 'pc' .. tostring(num) .. 'n'
local valArg = 'pc' .. tostring(num) .. 'v'
local key = args[keyArg]
key = tonumber(key) or key
local value = args[valArg]
constantArgs[key] = value
end
return constantArgs
end
function p.getVariableVals(args)
local variableVals = {}
if args.start or args.stop or args.by then
if args[2] then
error("Both start/stop/by and numbered parameters specified")
end
local start = tonumber(args.start or 1)
local stop = tonumber(args.stop or 1)
local by = tonumber(args.by or 1)
for i = start, stop, by do
variableVals [#variableVals + 1] = i
end
else
for i, v in ipairs(args) do
if i ~= 1 then
variableVals[i - 1] = v
end
end
end
return variableVals
end
function p.getArgNums(args, prefix, suffix)
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix and suffix.
local nums = {}
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
for k, _ in pairs(args) do
local num = tostring(k):match(pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
table.sort(nums)
return nums
end
function p.callTemplate(template, targs)
return mw.getCurrentFrame():expandTemplate{title = template, args = targs}
end
return p
3vczdtsoi79wslpamhz4wcf4ti3y68c
9439
9438
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Module:For_loop]]
9438
Scribunto
text/plain
-- This module implements {{for loop}}.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local p = {}
function p.templatemain(frame)
return p.main(frame:newChild{title = "Template:For_loop"})
end
function p.main(frame)
local args = getArgs(frame, {
trim = false,
removeBlanks = false
})
return p._main(args)
end
function p._main(args)
local template = args['call'] or 'void'
local calltemplates = yesno(args.substall or "", true) or not mw.isSubsting()
local variableParam = args.pv
variableParam = tonumber(variableParam) or variableParam or 1 -- fix for positional parameters
local variableValPrefix = args.prefix or ''
local variableValPostfix = args.postfix or ''
local sep = args[1] or ''
local constantArgs = p.getConstants(args)
local variableVals = p.getVariableVals(args)
local result = ''
local addSeparator = false;
for _, v in ipairs(variableVals) do
v = mw.text.trim(v)
if #v > 0 or not yesno(args.skipBlanks) then
if addSeparator then
result = result .. sep
end
addSeparator = true;
local targs = constantArgs
targs[variableParam] = variableValPrefix .. v .. variableValPostfix
if calltemplates then
local output = p.callTemplate(template, targs)
if #mw.text.trim(output) == 0 then
addSeparator = false
end
result = result .. output
else
local makeTemplate = require('Module:Template invocation').invocation
result = result .. makeTemplate(template, targs)
end
end
end
return result
end
function p.getConstants(args)
local constantArgNums = p.getArgNums(args, 'pc', 'n')
local constantArgs = {}
for _, num in ipairs(constantArgNums) do
local keyArg = 'pc' .. tostring(num) .. 'n'
local valArg = 'pc' .. tostring(num) .. 'v'
local key = args[keyArg]
key = tonumber(key) or key
local value = args[valArg]
constantArgs[key] = value
end
return constantArgs
end
function p.getVariableVals(args)
local variableVals = {}
if args.start or args.stop or args.by then
if args[2] then
error("Both start/stop/by and numbered parameters specified")
end
local start = tonumber(args.start or 1)
local stop = tonumber(args.stop or 1)
local by = tonumber(args.by or 1)
for i = start, stop, by do
variableVals [#variableVals + 1] = i
end
else
for i, v in ipairs(args) do
if i ~= 1 then
variableVals[i - 1] = v
end
end
end
return variableVals
end
function p.getArgNums(args, prefix, suffix)
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix and suffix.
local nums = {}
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
for k, _ in pairs(args) do
local num = tostring(k):match(pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
table.sort(nums)
return nums
end
function p.callTemplate(template, targs)
return mw.getCurrentFrame():expandTemplate{title = template, args = targs}
end
return p
3vczdtsoi79wslpamhz4wcf4ti3y68c
Module:Template wrapper
828
1204
9440
2022-10-21T21:11:46Z
en>Legoktm
0
Replace [[Module:No globals]] with require( "strict" )
9440
Scribunto
text/plain
require('strict');
local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">|_template=</code> missing or empty</span>';
--[[--------------------------< I S _ I N _ T A B L E >--------------------------------------------------------
scan through tbl looking for value; return true if found, false else
]]
local function is_in_table (tbl, value)
for k, v in pairs (tbl) do
if v == value then return true end
end
return false;
end
--[[--------------------------< A D D _ P A R A M E T E R >----------------------------------------------------
adds parameter name and its value to args table according to the state of boolean list argument; kv pair for
template execution; k=v string for template listing.
]]
local function add_parameter (k, v, args, list)
if list then
table.insert( args, table.concat ({k, '=', v})); -- write parameter names and values to args table as string
else
args[k] = v; -- copy parameters to args table
end
end
--[[--------------------------< A L I A S _ M A P _ G E T >----------------------------------------------------
returns a table of local template (parent frame) parameter names and the target template names that match where
in [key]=<value> pairs where:
[key] is local template parameter name (an alias)
<value> is target template parameter name (the canonical parameter name used in the working template)
The parameter |_alias-map= has the form:
|_alias-map=<list>
where <list> is a comma-separated list of alias / canonical parameter name pairs in the form
<from> : <to>
where:
<from> is the local template's parameter name (alias)
<to> is the target template's parameter name (canonical)
for enumerated parameters place an octothorp (#) where the enumerator digits are placed in the parameter names:
<from#> : <to#>
]]
local function alias_map_get (_alias_map)
local T = mw.text.split (_alias_map, '%s*,%s*'); -- convert the comma-separated list into a table of alias pairs
local mapped_aliases = {}; -- mapped aliases will go here
local l_name, t_name; -- parameter names
for _, alias_pair in ipairs (T) do -- loop through the table of alias pairs
l_name, t_name = alias_pair:match ('(.-)%s*:%s*(.+)'); -- from each pair, get local and target parameter names
if l_name and t_name then -- if both are set
if tonumber (l_name) then
l_name = tonumber (l_name); -- convert number-as-text to a number
end
mapped_aliases[l_name] = t_name; -- add them to the map table
end
end
return mapped_aliases;
end
--[[--------------------------< F R A M E _ A R G S _ G E T >--------------------------------------------------
Fetch the wrapper template's 'default' and control parameters; adds default parameters to args
returns content of |_template= parameter (name of the working template); nil else
]]
local function frame_args_get (frame_args, args, list)
local template;
for k, v in pairs (frame_args) do -- here we get the wrapper template's 'default' parameters
if 'string' == type (k) and (v and ('' ~= v)) then -- do not pass along positional or empty parameters
if '_template' == k then
template = v; -- save the name of template that we are wrapping
elseif '_exclude' ~= k and '_reuse' ~= k and '_include-positional' ~= k and '_alias-map' ~= k then -- these already handled so ignore here;
add_parameter (k, v, args, list); -- add all other parameters to args in the style dictated by list
end
end
end
return template; -- return contents of |_template= parameter
end
--[=[--------------------------< P F R A M E _ A R G S _ G E T >------------------------------------------------
Fetches the wrapper template's 'live' parameters; adds live parameters that aren't members of the exclude table to
args table; positional parameters may not be excluded
no return value
]=]
local function pframe_args_get (pframe_args, args, exclude, _include_positional, list)
for k, v in pairs (pframe_args) do
if 'string' == type (k) and not is_in_table (exclude, k) then -- do not pass along excluded parameters
if v and ('' ~= v) then -- pass along only those parameters that have assigned values
if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template
v = ''; -- unset the value in the args table
end
add_parameter (k, v, args, list) -- add all other parameters to args in the style dictated by list; alias map only supported for local-template parameters
end
end
end
if _include_positional then
for i, v in ipairs (pframe_args) do -- pass along positional parameters
if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template
v = ''; -- unset the value in the args table
end
add_parameter (i, v, args, list);
end
end
end
--[[--------------------------< _ M A I N >--------------------------------------------------------------------
Collect the various default and live parameters into args styled according to boolean list.
returns name of the working or listed template or nil for an error message
]]
local function _main (frame, args, list)
local template;
local exclude = {}; -- table of parameter names for parameters that are not passed to the working template
local reuse_list = {}; -- table of pframe parameter names whose values are modified before they are passed to the working template as the same name
local alias_map = {}; -- table that maps parameter aliases to working template canonical parameter names
local _include_positional;
if frame.args._exclude and ('' ~= frame.args._exclude) then -- if there is |_exclude= and it's not empty
exclude = mw.text.split (frame.args._exclude, "%s*,%s*"); -- make a table from its contents
end
-- TODO: |_reuse= needs a better name (|_reuse=)
if frame.args._reuse and ('' ~= frame.args._reuse) then -- if there is |_reuse= and it's not empty
reuse_list = mw.text.split (frame.args._reuse, "%s*,%s*"); -- make a table from its contents
end
if frame.args['_alias-map'] and ('' ~= frame.args['_alias-map']) then -- if there is |_alias-map= and it's not empty
alias_map = alias_map_get (frame.args['_alias-map']); -- make a table from its contents
end
template = frame_args_get (frame.args, args, list); -- get parameters provided in the {{#invoke:template wrapper|...|...}}
if nil == template or '' == template then -- this is the one parameter that is required by this module
return nil; -- not present, tell calling function to emit an error message
end
_include_positional = 'yes' == frame.args['_include-positional']; -- when true pass all positional parameters along with non-excluded named parameters to ...
-- ... the working template; positional parameters are not excludable
local _pframe_args = frame:getParent().args; -- here we get the wrapper template's 'live' parameters from pframe.args
local pframe_args = {}; -- a local table that we can modify
for k, v in pairs (_pframe_args) do -- make a copy that we can modify
pframe_args[k] = v;
end
-- here we look for pframe parameters that are aliases of canonical parameter names; when found
-- we replace the alias with the canonical. We do this here because the reuse_list works on
-- canonical parameter names so first we convert alias parameter names to canonical names and then
-- we remove those canonical names from the pframe table that are reused (provided to the working
-- template through the frame args table)
for k, v in pairs (alias_map) do -- k is alias name, v is canonical name
if pframe_args[k] then -- if pframe_args has parameter with alias name
pframe_args[v] = _pframe_args[k]; -- create new canonical name with alias' value
pframe_args[k] = nil; -- unset the alias
end
end
for k, v in pairs (pframe_args) do -- do enumerated parameter alias -> canonical translation
if 'string' == type (k) then -- only named parameters can be enumerated
if alias_map[k..'#'] then -- non-enumerated alias matches enumerated parameter pattern? enumerator at end only
pframe_args[alias_map[k..'#']:gsub('#', '')] = v; -- remove '#' and copy parameter to pframe_args table
pframe_args[k] = nil; -- unset the alias
elseif k:match ('%d+') then -- if this parameter name contains digits
local temp = k:gsub ('%d+', '#'); -- make a copy; digits replaced with single '#'
local enum = k:match ('%d+'); -- get the enumerator
if alias_map[temp] then -- if this parameter is a recognized enumerated alias
pframe_args[alias_map[temp]:gsub('#', enum)] = v; -- use canonical name and replace '#' with enumerator and add to pframe_args
pframe_args[k] = nil; -- unset the alias
end
end
end
end
-- pframe parameters that are _reused are 'reused' have the form something like this:
-- |chapter=[[wikisource:{{{chapter}}}|{{{chapter}}}]]
-- where a parameter in the wrapping template is modified and then passed to the working template
-- using the same parameter name (in this example |chapter=)
-- remove parameters that will be reused
for k, v in ipairs (reuse_list) do -- k is numerical index, v is canonical parameter name to ignore
if pframe_args[v] then -- if pframe_args has parameter that should be ignored
pframe_args[v] = nil; -- unset the ignored parameter
end
end
pframe_args_get (pframe_args, args, exclude, _include_positional, list); -- add parameters and values to args that are not listed in the exclude table
return template; -- args now has all default and live parameters, return working template name
end
--[[--------------------------< W R A P >----------------------------------------------------------------------
Template entry point. Call this function to 'execute' the working template
]]
local function wrap (frame)
local args = {}; -- table of default and live parameters and their values to be passed to the wrapped template
local template; -- the name of the working template
template = _main (frame, args, false); -- get default and live parameters and the name of the working template
if not template then -- template name is required
return error_msg; -- emit error message and abandon if template name not present
end
return frame:expandTemplate {title=template, args=args}; -- render the working template
end
--[[--------------------------< L I S T >----------------------------------------------------------------------
Template entry point. Call this function to 'display' the source for the working template. This function added
as a result of a TfD here: Wikipedia:Templates_for_discussion/Log/2018_April_28#Module:PassArguments
This function replaces a similarly named function which was used in {{cite compare}} and {{cite compare2}}
Values in the args table are numerically indexed strings in the form 'name=value'
]]
local function list(frame, do_link)
local args = {}; -- table of default and live parameters and their values to be passed to the listed template
local template; -- the name of the listed template
template = _main (frame, args, true); -- get default and live parameters and the name of the listed template
if not template then -- template name is required
return error_msg; -- emit error message and abandon if template name not present
end
if do_link then
template = ('[[%s|%s]]'):format(frame:expandTemplate{ title='Transclude', args = {template} }, template)
end
table.sort(args)
for i = 1, #args do
local stripped = args[i]:match('^' .. i .. '=([^=]*)$')
if stripped then args[i] = stripped else break end
end
return frame:preprocess(table.concat({
'<code style="color:inherit; background:inherit; border:none;">{{',
template,
('<wbr><nowiki>|%s</nowiki>'):rep(#args):format(unpack(args)), '}}</code>'})); -- render the template
end
local function link (frame)
return list(frame, true)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
link = link,
list = list,
wrap = wrap,
};
b0ambjffywwcjy4rlrl344s9i200kdz
9441
9440
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Template_wrapper]]
9440
Scribunto
text/plain
require('strict');
local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">|_template=</code> missing or empty</span>';
--[[--------------------------< I S _ I N _ T A B L E >--------------------------------------------------------
scan through tbl looking for value; return true if found, false else
]]
local function is_in_table (tbl, value)
for k, v in pairs (tbl) do
if v == value then return true end
end
return false;
end
--[[--------------------------< A D D _ P A R A M E T E R >----------------------------------------------------
adds parameter name and its value to args table according to the state of boolean list argument; kv pair for
template execution; k=v string for template listing.
]]
local function add_parameter (k, v, args, list)
if list then
table.insert( args, table.concat ({k, '=', v})); -- write parameter names and values to args table as string
else
args[k] = v; -- copy parameters to args table
end
end
--[[--------------------------< A L I A S _ M A P _ G E T >----------------------------------------------------
returns a table of local template (parent frame) parameter names and the target template names that match where
in [key]=<value> pairs where:
[key] is local template parameter name (an alias)
<value> is target template parameter name (the canonical parameter name used in the working template)
The parameter |_alias-map= has the form:
|_alias-map=<list>
where <list> is a comma-separated list of alias / canonical parameter name pairs in the form
<from> : <to>
where:
<from> is the local template's parameter name (alias)
<to> is the target template's parameter name (canonical)
for enumerated parameters place an octothorp (#) where the enumerator digits are placed in the parameter names:
<from#> : <to#>
]]
local function alias_map_get (_alias_map)
local T = mw.text.split (_alias_map, '%s*,%s*'); -- convert the comma-separated list into a table of alias pairs
local mapped_aliases = {}; -- mapped aliases will go here
local l_name, t_name; -- parameter names
for _, alias_pair in ipairs (T) do -- loop through the table of alias pairs
l_name, t_name = alias_pair:match ('(.-)%s*:%s*(.+)'); -- from each pair, get local and target parameter names
if l_name and t_name then -- if both are set
if tonumber (l_name) then
l_name = tonumber (l_name); -- convert number-as-text to a number
end
mapped_aliases[l_name] = t_name; -- add them to the map table
end
end
return mapped_aliases;
end
--[[--------------------------< F R A M E _ A R G S _ G E T >--------------------------------------------------
Fetch the wrapper template's 'default' and control parameters; adds default parameters to args
returns content of |_template= parameter (name of the working template); nil else
]]
local function frame_args_get (frame_args, args, list)
local template;
for k, v in pairs (frame_args) do -- here we get the wrapper template's 'default' parameters
if 'string' == type (k) and (v and ('' ~= v)) then -- do not pass along positional or empty parameters
if '_template' == k then
template = v; -- save the name of template that we are wrapping
elseif '_exclude' ~= k and '_reuse' ~= k and '_include-positional' ~= k and '_alias-map' ~= k then -- these already handled so ignore here;
add_parameter (k, v, args, list); -- add all other parameters to args in the style dictated by list
end
end
end
return template; -- return contents of |_template= parameter
end
--[=[--------------------------< P F R A M E _ A R G S _ G E T >------------------------------------------------
Fetches the wrapper template's 'live' parameters; adds live parameters that aren't members of the exclude table to
args table; positional parameters may not be excluded
no return value
]=]
local function pframe_args_get (pframe_args, args, exclude, _include_positional, list)
for k, v in pairs (pframe_args) do
if 'string' == type (k) and not is_in_table (exclude, k) then -- do not pass along excluded parameters
if v and ('' ~= v) then -- pass along only those parameters that have assigned values
if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template
v = ''; -- unset the value in the args table
end
add_parameter (k, v, args, list) -- add all other parameters to args in the style dictated by list; alias map only supported for local-template parameters
end
end
end
if _include_positional then
for i, v in ipairs (pframe_args) do -- pass along positional parameters
if 'unset' == v:lower() then -- special keyword to unset 'default' parameters set in the wrapper template
v = ''; -- unset the value in the args table
end
add_parameter (i, v, args, list);
end
end
end
--[[--------------------------< _ M A I N >--------------------------------------------------------------------
Collect the various default and live parameters into args styled according to boolean list.
returns name of the working or listed template or nil for an error message
]]
local function _main (frame, args, list)
local template;
local exclude = {}; -- table of parameter names for parameters that are not passed to the working template
local reuse_list = {}; -- table of pframe parameter names whose values are modified before they are passed to the working template as the same name
local alias_map = {}; -- table that maps parameter aliases to working template canonical parameter names
local _include_positional;
if frame.args._exclude and ('' ~= frame.args._exclude) then -- if there is |_exclude= and it's not empty
exclude = mw.text.split (frame.args._exclude, "%s*,%s*"); -- make a table from its contents
end
-- TODO: |_reuse= needs a better name (|_reuse=)
if frame.args._reuse and ('' ~= frame.args._reuse) then -- if there is |_reuse= and it's not empty
reuse_list = mw.text.split (frame.args._reuse, "%s*,%s*"); -- make a table from its contents
end
if frame.args['_alias-map'] and ('' ~= frame.args['_alias-map']) then -- if there is |_alias-map= and it's not empty
alias_map = alias_map_get (frame.args['_alias-map']); -- make a table from its contents
end
template = frame_args_get (frame.args, args, list); -- get parameters provided in the {{#invoke:template wrapper|...|...}}
if nil == template or '' == template then -- this is the one parameter that is required by this module
return nil; -- not present, tell calling function to emit an error message
end
_include_positional = 'yes' == frame.args['_include-positional']; -- when true pass all positional parameters along with non-excluded named parameters to ...
-- ... the working template; positional parameters are not excludable
local _pframe_args = frame:getParent().args; -- here we get the wrapper template's 'live' parameters from pframe.args
local pframe_args = {}; -- a local table that we can modify
for k, v in pairs (_pframe_args) do -- make a copy that we can modify
pframe_args[k] = v;
end
-- here we look for pframe parameters that are aliases of canonical parameter names; when found
-- we replace the alias with the canonical. We do this here because the reuse_list works on
-- canonical parameter names so first we convert alias parameter names to canonical names and then
-- we remove those canonical names from the pframe table that are reused (provided to the working
-- template through the frame args table)
for k, v in pairs (alias_map) do -- k is alias name, v is canonical name
if pframe_args[k] then -- if pframe_args has parameter with alias name
pframe_args[v] = _pframe_args[k]; -- create new canonical name with alias' value
pframe_args[k] = nil; -- unset the alias
end
end
for k, v in pairs (pframe_args) do -- do enumerated parameter alias -> canonical translation
if 'string' == type (k) then -- only named parameters can be enumerated
if alias_map[k..'#'] then -- non-enumerated alias matches enumerated parameter pattern? enumerator at end only
pframe_args[alias_map[k..'#']:gsub('#', '')] = v; -- remove '#' and copy parameter to pframe_args table
pframe_args[k] = nil; -- unset the alias
elseif k:match ('%d+') then -- if this parameter name contains digits
local temp = k:gsub ('%d+', '#'); -- make a copy; digits replaced with single '#'
local enum = k:match ('%d+'); -- get the enumerator
if alias_map[temp] then -- if this parameter is a recognized enumerated alias
pframe_args[alias_map[temp]:gsub('#', enum)] = v; -- use canonical name and replace '#' with enumerator and add to pframe_args
pframe_args[k] = nil; -- unset the alias
end
end
end
end
-- pframe parameters that are _reused are 'reused' have the form something like this:
-- |chapter=[[wikisource:{{{chapter}}}|{{{chapter}}}]]
-- where a parameter in the wrapping template is modified and then passed to the working template
-- using the same parameter name (in this example |chapter=)
-- remove parameters that will be reused
for k, v in ipairs (reuse_list) do -- k is numerical index, v is canonical parameter name to ignore
if pframe_args[v] then -- if pframe_args has parameter that should be ignored
pframe_args[v] = nil; -- unset the ignored parameter
end
end
pframe_args_get (pframe_args, args, exclude, _include_positional, list); -- add parameters and values to args that are not listed in the exclude table
return template; -- args now has all default and live parameters, return working template name
end
--[[--------------------------< W R A P >----------------------------------------------------------------------
Template entry point. Call this function to 'execute' the working template
]]
local function wrap (frame)
local args = {}; -- table of default and live parameters and their values to be passed to the wrapped template
local template; -- the name of the working template
template = _main (frame, args, false); -- get default and live parameters and the name of the working template
if not template then -- template name is required
return error_msg; -- emit error message and abandon if template name not present
end
return frame:expandTemplate {title=template, args=args}; -- render the working template
end
--[[--------------------------< L I S T >----------------------------------------------------------------------
Template entry point. Call this function to 'display' the source for the working template. This function added
as a result of a TfD here: Wikipedia:Templates_for_discussion/Log/2018_April_28#Module:PassArguments
This function replaces a similarly named function which was used in {{cite compare}} and {{cite compare2}}
Values in the args table are numerically indexed strings in the form 'name=value'
]]
local function list(frame, do_link)
local args = {}; -- table of default and live parameters and their values to be passed to the listed template
local template; -- the name of the listed template
template = _main (frame, args, true); -- get default and live parameters and the name of the listed template
if not template then -- template name is required
return error_msg; -- emit error message and abandon if template name not present
end
if do_link then
template = ('[[%s|%s]]'):format(frame:expandTemplate{ title='Transclude', args = {template} }, template)
end
table.sort(args)
for i = 1, #args do
local stripped = args[i]:match('^' .. i .. '=([^=]*)$')
if stripped then args[i] = stripped else break end
end
return frame:preprocess(table.concat({
'<code style="color:inherit; background:inherit; border:none;">{{',
template,
('<wbr><nowiki>|%s</nowiki>'):rep(#args):format(unpack(args)), '}}</code>'})); -- render the template
end
local function link (frame)
return list(frame, true)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
link = link,
list = list,
wrap = wrap,
};
b0ambjffywwcjy4rlrl344s9i200kdz
Tempilet:!-
10
1205
9442
2013-11-17T11:54:04Z
en>Mr. Stradivarius
0
Changed protection level of Template:!-: [[WP:High-risk templates|Highly visible template]]: reinstate full-protection - this should never be edited ([Edit=Block all non-admin users] (indefinite) [Move=Block all non-admin users] (indefinite))
9442
wikitext
text/x-wiki
|-<noinclude>
{{documentation}}
</noinclude>
2zsavivng30v2w46mrxq9i40e1wnnr8
9443
9442
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Template:!-]]
9442
wikitext
text/x-wiki
|-<noinclude>
{{documentation}}
</noinclude>
2zsavivng30v2w46mrxq9i40e1wnnr8
Tempilet:Navbox bottom
10
1206
9444
2025-08-11T23:13:27Z
en>Pppery
0
Changed protection settings for "[[Template:Navbox bottom]]": [[WP:High-risk templates|High-risk template or module]]: top is already tpe ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9444
wikitext
text/x-wiki
<includeonly>{{#invoke:navbox top and bottom|bottom}}</includeonly><noinclude>
{{documentation|Template:Navbox top/doc}}</noinclude>
bwhjfft0rnpktg14lfnmvcypl0jjozg
9445
9444
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Navbox_bottom]]
9444
wikitext
text/x-wiki
<includeonly>{{#invoke:navbox top and bottom|bottom}}</includeonly><noinclude>
{{documentation|Template:Navbox top/doc}}</noinclude>
bwhjfft0rnpktg14lfnmvcypl0jjozg
Tempilet:Navbox top
10
1207
9446
2024-02-23T20:45:07Z
en>The Wordsmith
0
Adding {{pp-template}}
9446
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#invoke:navbox top and bottom|top}}</includeonly><noinclude>
{{documentation}}
</noinclude>
ewvk099kxtz3o1cy6yh0mx7d3fpta6v
9447
9446
2026-08-23T10:37:54Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Navbox_top]]
9446
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#invoke:navbox top and bottom|top}}</includeonly><noinclude>
{{documentation}}
</noinclude>
ewvk099kxtz3o1cy6yh0mx7d3fpta6v
Module:Navbox top and bottom
828
1208
9448
2024-03-19T04:03:41Z
en>Pppery
0
Changed protection settings for "[[Module:Navbox top and bottom]]": [[WP:High-risk templates|High-risk template or module]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9448
Scribunto
text/plain
-- This implements {{navbox top}} and {{navbox bottom}}
local p = {}
local function build_navbox(parentArgs, list)
local args = {}
for argName, value in pairs(parentArgs) do
if value ~= '' then
if type(argName) == 'string' then
args[argName] = value
end
end
end
args['bodystyle'] = 'display:table;' .. (args['bodystyle'] or '')
args['list1padding'] = '0'
args['list1style'] = 'border-width:0;'
args['list1'] = list
-- Note Navbox.navbox() has a kludge to order the parent frame's args
-- into a specific order. For now, this is omitted from this module.
local Navbox = require('Module:Navbox')
return Navbox._navbox(args)
end
function p.top(frame)
local args = frame:getParent().args
local parts = mw.text.split(build_navbox(args, '<ADD LIST HERE>'), '<ADD LIST HERE>')
return parts[1]
end
function p.bottom(frame)
local args = frame:getParent().args
local parts = mw.text.split(build_navbox(args, '<ADD LIST HERE>'), '<ADD LIST HERE>')
return parts[2]
end
return p
k4u6pww6woolztix1exofx2t2yk7vf6
9449
9448
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Navbox_top_and_bottom]]
9448
Scribunto
text/plain
-- This implements {{navbox top}} and {{navbox bottom}}
local p = {}
local function build_navbox(parentArgs, list)
local args = {}
for argName, value in pairs(parentArgs) do
if value ~= '' then
if type(argName) == 'string' then
args[argName] = value
end
end
end
args['bodystyle'] = 'display:table;' .. (args['bodystyle'] or '')
args['list1padding'] = '0'
args['list1style'] = 'border-width:0;'
args['list1'] = list
-- Note Navbox.navbox() has a kludge to order the parent frame's args
-- into a specific order. For now, this is omitted from this module.
local Navbox = require('Module:Navbox')
return Navbox._navbox(args)
end
function p.top(frame)
local args = frame:getParent().args
local parts = mw.text.split(build_navbox(args, '<ADD LIST HERE>'), '<ADD LIST HERE>')
return parts[1]
end
function p.bottom(frame)
local args = frame:getParent().args
local parts = mw.text.split(build_navbox(args, '<ADD LIST HERE>'), '<ADD LIST HERE>')
return parts[2]
end
return p
k4u6pww6woolztix1exofx2t2yk7vf6
Tempilet:Bulleted list
10
1209
9450
2015-12-26T16:25:12Z
en>Frietjes
0
documentation does this
9450
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|bulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
6i48hhgfh5fc81eswo5wmwb9rx7sypn
9451
9450
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Bulleted_list]]
9450
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|bulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
6i48hhgfh5fc81eswo5wmwb9rx7sypn
Tempilet:Pre
10
1210
9452
2026-06-29T14:46:36Z
en>ABreault (WMF)
0
For [[phab:T353697|T353697]]. See the talk page discussion
9452
wikitext
text/x-wiki
<templatestyles src="Pre/styles.css"/>{{#if:{{{space|}}}{{{width|}}}{{{style|}}}|{{#tag:pre|{{{1|<noinclude>Sample text</noinclude>}}}|format=wikitext|class=pre {{#ifeq:{{{border|}}}|no|pre-borderless}}|style={{#if:{{{space|}}}|white-space: {{{space}}};}} {{#if:{{{width|}}}|width: {{{width}}};}} {{{style|}}}}}|{{#tag:pre|{{{1|<noinclude>Sample text</noinclude>}}}|format=wikitext|class=pre {{#ifeq:{{{border|}}}|no|pre-borderless}}}}}}<noinclude>
{{Documentation}}
<!--
PLEASE ADD CATEGORIES AND INTERWIKIS
TO THE /doc SUBPAGE, THANKS
-->
</noinclude>
22sa1k0u2jf83124swp5gn7on8cvfol
9453
9452
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pre]]
9452
wikitext
text/x-wiki
<templatestyles src="Pre/styles.css"/>{{#if:{{{space|}}}{{{width|}}}{{{style|}}}|{{#tag:pre|{{{1|<noinclude>Sample text</noinclude>}}}|format=wikitext|class=pre {{#ifeq:{{{border|}}}|no|pre-borderless}}|style={{#if:{{{space|}}}|white-space: {{{space}}};}} {{#if:{{{width|}}}|width: {{{width}}};}} {{{style|}}}}}|{{#tag:pre|{{{1|<noinclude>Sample text</noinclude>}}}|format=wikitext|class=pre {{#ifeq:{{{border|}}}|no|pre-borderless}}}}}}<noinclude>
{{Documentation}}
<!--
PLEASE ADD CATEGORIES AND INTERWIKIS
TO THE /doc SUBPAGE, THANKS
-->
</noinclude>
22sa1k0u2jf83124swp5gn7on8cvfol
Tempilet:Pre/styles.css
10
1211
9454
2024-01-15T20:21:34Z
en>Pppery
0
Padlock
9454
sanitized-css
text/css
/* {{pp-template}} */
.pre-borderless {
border: none;
}
lr9ssbn3d1gy0eko4cg1ybqfok23ynd
9455
9454
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Pre/styles.css]]
9454
sanitized-css
text/css
/* {{pp-template}} */
.pre-borderless {
border: none;
}
lr9ssbn3d1gy0eko4cg1ybqfok23ynd
Tempilet:Ordered list
10
1212
9456
2015-12-14T10:30:21Z
en>The Earwig
0
Protected "[[Template:Ordered list]]": [[WP:High-risk templates|Highly visible template]]: thousands of mainspace transclusions; match siblings; unlikely to be edited ([Edit=Allow only template editors and admins] (indefinite) [Move=Allow only template...
9456
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|ordered}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
n9z3yrhcknctpjb3o8a5r4mv3ke55up
9457
9456
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Ordered_list]]
9456
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|ordered}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
n9z3yrhcknctpjb3o8a5r4mv3ke55up
Module:TNT
828
1213
9458
2020-08-30T07:28:25Z
en>Johnuniq
0
Changed protection level for "[[Module:TNT]]": [[WP:High-risk templates|High-risk Lua module]]: per request at [[WP:RFPP]] to match [[Module:Excerpt]] ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9458
Scribunto
text/plain
--
-- INTRO: (!!! DO NOT RENAME THIS PAGE !!!)
-- This module allows any template or module to be copy/pasted between
-- wikis without any translation changes. All translation text is stored
-- in the global Data:*.tab pages on Commons, and used everywhere.
--
-- SEE: https://www.mediawiki.org/wiki/Multilingual_Templates_and_Modules
--
-- ATTENTION:
-- Please do NOT rename this module - it has to be identical on all wikis.
-- This code is maintained at https://www.mediawiki.org/wiki/Module:TNT
-- Please do not modify it anywhere else, as it may get copied and override your changes.
-- Suggestions can be made at https://www.mediawiki.org/wiki/Module_talk:TNT
--
-- DESCRIPTION:
-- The "msg" function uses a Commons dataset to translate a message
-- with a given key (e.g. source-table), plus optional arguments
-- to the wiki markup in the current content language.
-- Use lang=xx to set language. Example:
--
-- {{#invoke:TNT | msg
-- | I18n/Template:Graphs.tab <!-- https://commons.wikimedia.org/wiki/Data:I18n/Template:Graphs.tab -->
-- | source-table <!-- uses a translation message with id = "source-table" -->
-- | param1 }} <!-- optional parameter -->
--
--
-- The "doc" function will generate the <templatedata> parameter documentation for templates.
-- This way all template parameters can be stored and localized in a single Commons dataset.
-- NOTE: "doc" assumes that all documentation is located in Data:Templatedata/* on Commons.
--
-- {{#invoke:TNT | doc | Graph:Lines }}
-- uses https://commons.wikimedia.org/wiki/Data:Templatedata/Graph:Lines.tab
-- if the current page is Template:Graph:Lines/doc
--
local p = {}
local i18nDataset = 'I18n/Module:TNT.tab'
-- Forward declaration of the local functions
local sanitizeDataset, loadData, link, formatMessage
function p.msg(frame)
local dataset, id
local params = {}
local lang = nil
for k, v in pairs(frame.args) do
if k == 1 then
dataset = mw.text.trim(v)
elseif k == 2 then
id = mw.text.trim(v)
elseif type(k) == 'number' then
table.insert(params, mw.text.trim(v))
elseif k == 'lang' and v ~= '_' then
lang = mw.text.trim(v)
end
end
return formatMessage(dataset, id, params, lang)
end
-- Identical to p.msg() above, but used from other lua modules
-- Parameters: name of dataset, message key, optional arguments
-- Example with 2 params: format('I18n/Module:TNT', 'error_bad_msgkey', 'my-key', 'my-dataset')
function p.format(dataset, key, ...)
local checkType = require('libraryUtil').checkType
checkType('format', 1, dataset, 'string')
checkType('format', 2, key, 'string')
return formatMessage(dataset, key, {...})
end
-- Identical to p.msg() above, but used from other lua modules with the language param
-- Parameters: language code, name of dataset, message key, optional arguments
-- Example with 2 params: formatInLanguage('es', I18n/Module:TNT', 'error_bad_msgkey', 'my-key', 'my-dataset')
function p.formatInLanguage(lang, dataset, key, ...)
local checkType = require('libraryUtil').checkType
checkType('formatInLanguage', 1, lang, 'string')
checkType('formatInLanguage', 2, dataset, 'string')
checkType('formatInLanguage', 3, key, 'string')
return formatMessage(dataset, key, {...}, lang)
end
-- Obsolete function that adds a 'c:' prefix to the first param.
-- "Sandbox/Sample.tab" -> 'c:Data:Sandbox/Sample.tab'
function p.link(frame)
return link(frame.args[1])
end
function p.doc(frame)
local dataset = 'Templatedata/' .. sanitizeDataset(frame.args[1])
return frame:extensionTag('templatedata', p.getTemplateData(dataset)) ..
formatMessage(i18nDataset, 'edit_doc', {link(dataset)})
end
function p.getTemplateData(dataset)
-- TODO: add '_' parameter once lua starts reindexing properly for "all" languages
local data = loadData(dataset)
local names = {}
for _, field in pairs(data.schema.fields) do
table.insert(names, field.name)
end
local params = {}
local paramOrder = {}
for _, row in pairs(data.data) do
local newVal = {}
local name = nil
for pos, val in pairs(row) do
local columnName = names[pos]
if columnName == 'name' then
name = val
else
newVal[columnName] = val
end
end
if name then
params[name] = newVal
table.insert(paramOrder, name)
end
end
-- Work around json encoding treating {"1":{...}} as an [{...}]
params['zzz123']=''
local json = mw.text.jsonEncode({
params=params,
paramOrder=paramOrder,
description=data.description
})
json = string.gsub(json,'"zzz123":"",?', "")
return json
end
-- Local functions
sanitizeDataset = function(dataset)
if not dataset then
return nil
end
dataset = mw.text.trim(dataset)
if dataset == '' then
return nil
elseif string.sub(dataset,-4) ~= '.tab' then
return dataset .. '.tab'
else
return dataset
end
end
loadData = function(dataset, lang)
dataset = sanitizeDataset(dataset)
if not dataset then
error(formatMessage(i18nDataset, 'error_no_dataset', {}))
end
-- Give helpful error to thirdparties who try and copy this module.
if not mw.ext or not mw.ext.data or not mw.ext.data.get then
error('Missing JsonConfig extension; Cannot load https://commons.wikimedia.org/wiki/Data:' .. dataset)
end
local data = mw.ext.data.get(dataset, lang)
if data == false then
if dataset == i18nDataset then
-- Prevent cyclical calls
error('Missing Commons dataset ' .. i18nDataset)
else
error(formatMessage(i18nDataset, 'error_bad_dataset', {link(dataset)}))
end
end
return data
end
-- Given a dataset name, convert it to a title with the 'commons:data:' prefix
link = function(dataset)
return 'c:Data:' .. mw.text.trim(dataset or '')
end
formatMessage = function(dataset, key, params, lang)
for _, row in pairs(loadData(dataset, lang).data) do
local id, msg = unpack(row)
if id == key then
local result = mw.message.newRawMessage(msg, unpack(params or {}))
return result:plain()
end
end
if dataset == i18nDataset then
-- Prevent cyclical calls
error('Invalid message key "' .. key .. '"')
else
error(formatMessage(i18nDataset, 'error_bad_msgkey', {key, link(dataset)}))
end
end
return p
icfixo3zxiew6gqg3s5h19xr03x3wkh
9459
9458
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Module:TNT]]
9458
Scribunto
text/plain
--
-- INTRO: (!!! DO NOT RENAME THIS PAGE !!!)
-- This module allows any template or module to be copy/pasted between
-- wikis without any translation changes. All translation text is stored
-- in the global Data:*.tab pages on Commons, and used everywhere.
--
-- SEE: https://www.mediawiki.org/wiki/Multilingual_Templates_and_Modules
--
-- ATTENTION:
-- Please do NOT rename this module - it has to be identical on all wikis.
-- This code is maintained at https://www.mediawiki.org/wiki/Module:TNT
-- Please do not modify it anywhere else, as it may get copied and override your changes.
-- Suggestions can be made at https://www.mediawiki.org/wiki/Module_talk:TNT
--
-- DESCRIPTION:
-- The "msg" function uses a Commons dataset to translate a message
-- with a given key (e.g. source-table), plus optional arguments
-- to the wiki markup in the current content language.
-- Use lang=xx to set language. Example:
--
-- {{#invoke:TNT | msg
-- | I18n/Template:Graphs.tab <!-- https://commons.wikimedia.org/wiki/Data:I18n/Template:Graphs.tab -->
-- | source-table <!-- uses a translation message with id = "source-table" -->
-- | param1 }} <!-- optional parameter -->
--
--
-- The "doc" function will generate the <templatedata> parameter documentation for templates.
-- This way all template parameters can be stored and localized in a single Commons dataset.
-- NOTE: "doc" assumes that all documentation is located in Data:Templatedata/* on Commons.
--
-- {{#invoke:TNT | doc | Graph:Lines }}
-- uses https://commons.wikimedia.org/wiki/Data:Templatedata/Graph:Lines.tab
-- if the current page is Template:Graph:Lines/doc
--
local p = {}
local i18nDataset = 'I18n/Module:TNT.tab'
-- Forward declaration of the local functions
local sanitizeDataset, loadData, link, formatMessage
function p.msg(frame)
local dataset, id
local params = {}
local lang = nil
for k, v in pairs(frame.args) do
if k == 1 then
dataset = mw.text.trim(v)
elseif k == 2 then
id = mw.text.trim(v)
elseif type(k) == 'number' then
table.insert(params, mw.text.trim(v))
elseif k == 'lang' and v ~= '_' then
lang = mw.text.trim(v)
end
end
return formatMessage(dataset, id, params, lang)
end
-- Identical to p.msg() above, but used from other lua modules
-- Parameters: name of dataset, message key, optional arguments
-- Example with 2 params: format('I18n/Module:TNT', 'error_bad_msgkey', 'my-key', 'my-dataset')
function p.format(dataset, key, ...)
local checkType = require('libraryUtil').checkType
checkType('format', 1, dataset, 'string')
checkType('format', 2, key, 'string')
return formatMessage(dataset, key, {...})
end
-- Identical to p.msg() above, but used from other lua modules with the language param
-- Parameters: language code, name of dataset, message key, optional arguments
-- Example with 2 params: formatInLanguage('es', I18n/Module:TNT', 'error_bad_msgkey', 'my-key', 'my-dataset')
function p.formatInLanguage(lang, dataset, key, ...)
local checkType = require('libraryUtil').checkType
checkType('formatInLanguage', 1, lang, 'string')
checkType('formatInLanguage', 2, dataset, 'string')
checkType('formatInLanguage', 3, key, 'string')
return formatMessage(dataset, key, {...}, lang)
end
-- Obsolete function that adds a 'c:' prefix to the first param.
-- "Sandbox/Sample.tab" -> 'c:Data:Sandbox/Sample.tab'
function p.link(frame)
return link(frame.args[1])
end
function p.doc(frame)
local dataset = 'Templatedata/' .. sanitizeDataset(frame.args[1])
return frame:extensionTag('templatedata', p.getTemplateData(dataset)) ..
formatMessage(i18nDataset, 'edit_doc', {link(dataset)})
end
function p.getTemplateData(dataset)
-- TODO: add '_' parameter once lua starts reindexing properly for "all" languages
local data = loadData(dataset)
local names = {}
for _, field in pairs(data.schema.fields) do
table.insert(names, field.name)
end
local params = {}
local paramOrder = {}
for _, row in pairs(data.data) do
local newVal = {}
local name = nil
for pos, val in pairs(row) do
local columnName = names[pos]
if columnName == 'name' then
name = val
else
newVal[columnName] = val
end
end
if name then
params[name] = newVal
table.insert(paramOrder, name)
end
end
-- Work around json encoding treating {"1":{...}} as an [{...}]
params['zzz123']=''
local json = mw.text.jsonEncode({
params=params,
paramOrder=paramOrder,
description=data.description
})
json = string.gsub(json,'"zzz123":"",?', "")
return json
end
-- Local functions
sanitizeDataset = function(dataset)
if not dataset then
return nil
end
dataset = mw.text.trim(dataset)
if dataset == '' then
return nil
elseif string.sub(dataset,-4) ~= '.tab' then
return dataset .. '.tab'
else
return dataset
end
end
loadData = function(dataset, lang)
dataset = sanitizeDataset(dataset)
if not dataset then
error(formatMessage(i18nDataset, 'error_no_dataset', {}))
end
-- Give helpful error to thirdparties who try and copy this module.
if not mw.ext or not mw.ext.data or not mw.ext.data.get then
error('Missing JsonConfig extension; Cannot load https://commons.wikimedia.org/wiki/Data:' .. dataset)
end
local data = mw.ext.data.get(dataset, lang)
if data == false then
if dataset == i18nDataset then
-- Prevent cyclical calls
error('Missing Commons dataset ' .. i18nDataset)
else
error(formatMessage(i18nDataset, 'error_bad_dataset', {link(dataset)}))
end
end
return data
end
-- Given a dataset name, convert it to a title with the 'commons:data:' prefix
link = function(dataset)
return 'c:Data:' .. mw.text.trim(dataset or '')
end
formatMessage = function(dataset, key, params, lang)
for _, row in pairs(loadData(dataset, lang).data) do
local id, msg = unpack(row)
if id == key then
local result = mw.message.newRawMessage(msg, unpack(params or {}))
return result:plain()
end
end
if dataset == i18nDataset then
-- Prevent cyclical calls
error('Invalid message key "' .. key .. '"')
else
error(formatMessage(i18nDataset, 'error_bad_msgkey', {key, link(dataset)}))
end
end
return p
icfixo3zxiew6gqg3s5h19xr03x3wkh
Tempilet:Columns-list
10
1214
9460
2026-08-03T09:49:49Z
en>RMCD bot
0
Notifying subject page of move discussion on [[Template talk:Hlist#Requested move 3 August 2026|Template talk:Hlist]]
9460
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Columns list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude>{{<includeonly>safesubst:</includeonly>#if:{{{1|}}}|{{<includeonly>safesubst:</includeonly>#invoke:Template wrapper|wrap|_template=div col|_alias-map=1:content|colwidth=30em}}}}{{<includeonly>safesubst:</includeonly>#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using columns-list with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Columns-list]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | class | content | colwidth | gap | rules | small | style }}<noinclude>
{{documentation}}
</noinclude>
90o7mmc9j4xxvpgdp1emyub3c8xfidy
9461
9460
2026-08-23T10:37:55Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Columns-list]]
9460
wikitext
text/x-wiki
<noinclude>{{Requested move notice|1=Template:Columns list|2=Template talk:Hlist#Requested move 3 August 2026}}
</noinclude>{{<includeonly>safesubst:</includeonly>#if:{{{1|}}}|{{<includeonly>safesubst:</includeonly>#invoke:Template wrapper|wrap|_template=div col|_alias-map=1:content|colwidth=30em}}}}{{<includeonly>safesubst:</includeonly>#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using columns-list with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Columns-list]] with unknown parameter "_VALUE_"|ignoreblank=y| 1 | class | content | colwidth | gap | rules | small | style }}<noinclude>
{{documentation}}
</noinclude>
90o7mmc9j4xxvpgdp1emyub3c8xfidy
Tempilet:Section link
10
1215
9462
2025-09-07T10:05:45Z
en>Est. 2021
0
[[Template talk:Section link#Template-protected edit request on 2 September 2025: Don't render on the template page if it's going to show an error|Template-protected edit request on 2 September 2025: Don't render on the template page if it's going to show an error]]
9462
wikitext
text/x-wiki
<includeonly>{{SAFESUBST:<noinclude />#invoke:Section link|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
1zn34l15s46h6jh7fuzndshkdprqxst
9463
9462
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Section_link]]
9462
wikitext
text/x-wiki
<includeonly>{{SAFESUBST:<noinclude />#invoke:Section link|main}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
1zn34l15s46h6jh7fuzndshkdprqxst
Module:Section link
828
1216
9464
2024-06-02T14:36:41Z
en>Trappist the monk
0
sync from sandbox;
9464
Scribunto
text/plain
-- This module implements {{section link}}.
require('strict');
local checkType = require('libraryUtil').checkType
local p = {}
local function makeSectionLink(page, section, display)
display = display or section
page = page or ''
-- MediaWiki doesn't allow these in 'page', so only need to do for 'section'
if type(section) == 'string' then
section = string.gsub(section, "{", "{")
section = string.gsub(section, "}", "}")
end
return string.format('[[%s#%s|%s]]', page, section, display)
end
local function normalizeTitle(title)
title = mw.ustring.gsub(mw.ustring.gsub(title, "'", ""), '"', '')
title = mw.ustring.gsub(title, "%b<>", "")
return mw.title.new(title).prefixedText
end
function p._main(page, sections, options, title)
-- Validate input.
checkType('_main', 1, page, 'string', true)
checkType('_main', 3, options, 'table', true)
if sections == nil then
sections = {}
elseif type(sections) == 'string' then
sections = {sections}
elseif type(sections) ~= 'table' then
error(string.format(
"type error in argument #2 to '_main' " ..
"(string, table or nil expected, got %s)",
type(sections)
), 2)
end
options = options or {}
title = title or mw.title.getCurrentTitle()
-- Deal with blank page names elegantly
if page and not page:find('%S') then
page = nil
options.nopage = true
end
-- Make the link(s).
local isShowingPage = not options.nopage
if #sections <= 1 then
local linkPage = page or ''
if options.permalink then -- when oldid provided
linkPage = 'Special:Permalink/' .. options.permalink; -- make Special:Permalink/oldid wikilink
end
local section = sections[1]; -- sections[1] must have a value
local display = '§ ' .. section
if isShowingPage then
page = page or title.prefixedText
if options.display and options.display ~= '' then
if normalizeTitle(options.display) == normalizeTitle(page) then
display = options.display .. ' ' .. display
else
error(string.format(
'Display title "%s" was ignored since it is ' ..
"not equivalent to the page's actual title",
options.display
), 0)
end
else
display = page .. ' ' .. display
end
end
return makeSectionLink(linkPage, section, display)
else
-- Multiple sections. First, make a list of the links to display.
local ret = {}
for i, section in ipairs(sections) do
ret[i] = makeSectionLink(page, section)
end
-- Assemble the list of links into a string with mw.text.listToText.
-- We use the default separator for mw.text.listToText, but a custom
-- conjunction. There is also a special case conjunction if we only
-- have two links.
local conjunction
if #sections == 2 then
conjunction = '​ and '
else
conjunction = ', and '
end
ret = mw.text.listToText(ret, nil, conjunction)
-- Add the intro text.
local intro = '§§ '
if isShowingPage then
intro = (page or title.prefixedText) .. ' ' .. intro
end
ret = intro .. ret
return ret
end
end
function p.main(frame)
local yesno = require('Module:Yesno')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Section link',
valueFunc = function (key, value)
value = value:match('^%s*(.-)%s*$') -- Trim whitespace
-- Allow blank first parameters, as the wikitext template does this.
if value ~= '' or key == 1 then
return value
end
end
})
for k, v in pairs(args) do -- replace underscores in the positional parameter values
if 'number' == type(k) then
if not yesno (args['keep-underscores']) then -- unless |keep-underscores=yes
args[k] = mw.uri.decode (v, 'WIKI'); -- percent-decode; replace underscores with space characters
else
args[k] = mw.uri.decode (v, 'PATH'); -- percent-decode; retain underscores
end
end
end
-- Sort the arguments.
local page
local sections, options = {}, {}
for k, v in pairs(args) do
if k == 1 then
-- Doing this in the loop because of a bug in [[Module:Arguments]]
-- when using pairs with deleted arguments.
page = mw.text.decode(v, true)
elseif type(k) == 'number' then
sections[k] = v
else
options[k] = v
end
end
options.nopage = yesno (options.nopage); -- make boolean
-- Extract section from page, if present
if page then
local p, s = page:match('^(.-)#(.*)$')
if p then page, sections[1] = p, s end
end
-- Compress the sections array.
local function compressArray(t)
local nums, ret = {}, {}
for num in pairs(t) do
nums[#nums + 1] = num
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
sections = compressArray(sections)
if not sections[1] then -- empty section parameter makes {{Section link}} meaningless
return ('<span style="color:#d33"><span style="font-family:monospace">{{[[Template:Section link|Section link]]}}</span>: required section parameter(s) missing</span>'); -- emit error message and abandon
end
return p._main(page, sections, options)
end
return p
p8mwfbn5hl8c82dtswdvddooi11c3f1
9465
9464
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Section_link]]
9464
Scribunto
text/plain
-- This module implements {{section link}}.
require('strict');
local checkType = require('libraryUtil').checkType
local p = {}
local function makeSectionLink(page, section, display)
display = display or section
page = page or ''
-- MediaWiki doesn't allow these in 'page', so only need to do for 'section'
if type(section) == 'string' then
section = string.gsub(section, "{", "{")
section = string.gsub(section, "}", "}")
end
return string.format('[[%s#%s|%s]]', page, section, display)
end
local function normalizeTitle(title)
title = mw.ustring.gsub(mw.ustring.gsub(title, "'", ""), '"', '')
title = mw.ustring.gsub(title, "%b<>", "")
return mw.title.new(title).prefixedText
end
function p._main(page, sections, options, title)
-- Validate input.
checkType('_main', 1, page, 'string', true)
checkType('_main', 3, options, 'table', true)
if sections == nil then
sections = {}
elseif type(sections) == 'string' then
sections = {sections}
elseif type(sections) ~= 'table' then
error(string.format(
"type error in argument #2 to '_main' " ..
"(string, table or nil expected, got %s)",
type(sections)
), 2)
end
options = options or {}
title = title or mw.title.getCurrentTitle()
-- Deal with blank page names elegantly
if page and not page:find('%S') then
page = nil
options.nopage = true
end
-- Make the link(s).
local isShowingPage = not options.nopage
if #sections <= 1 then
local linkPage = page or ''
if options.permalink then -- when oldid provided
linkPage = 'Special:Permalink/' .. options.permalink; -- make Special:Permalink/oldid wikilink
end
local section = sections[1]; -- sections[1] must have a value
local display = '§ ' .. section
if isShowingPage then
page = page or title.prefixedText
if options.display and options.display ~= '' then
if normalizeTitle(options.display) == normalizeTitle(page) then
display = options.display .. ' ' .. display
else
error(string.format(
'Display title "%s" was ignored since it is ' ..
"not equivalent to the page's actual title",
options.display
), 0)
end
else
display = page .. ' ' .. display
end
end
return makeSectionLink(linkPage, section, display)
else
-- Multiple sections. First, make a list of the links to display.
local ret = {}
for i, section in ipairs(sections) do
ret[i] = makeSectionLink(page, section)
end
-- Assemble the list of links into a string with mw.text.listToText.
-- We use the default separator for mw.text.listToText, but a custom
-- conjunction. There is also a special case conjunction if we only
-- have two links.
local conjunction
if #sections == 2 then
conjunction = '​ and '
else
conjunction = ', and '
end
ret = mw.text.listToText(ret, nil, conjunction)
-- Add the intro text.
local intro = '§§ '
if isShowingPage then
intro = (page or title.prefixedText) .. ' ' .. intro
end
ret = intro .. ret
return ret
end
end
function p.main(frame)
local yesno = require('Module:Yesno')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Section link',
valueFunc = function (key, value)
value = value:match('^%s*(.-)%s*$') -- Trim whitespace
-- Allow blank first parameters, as the wikitext template does this.
if value ~= '' or key == 1 then
return value
end
end
})
for k, v in pairs(args) do -- replace underscores in the positional parameter values
if 'number' == type(k) then
if not yesno (args['keep-underscores']) then -- unless |keep-underscores=yes
args[k] = mw.uri.decode (v, 'WIKI'); -- percent-decode; replace underscores with space characters
else
args[k] = mw.uri.decode (v, 'PATH'); -- percent-decode; retain underscores
end
end
end
-- Sort the arguments.
local page
local sections, options = {}, {}
for k, v in pairs(args) do
if k == 1 then
-- Doing this in the loop because of a bug in [[Module:Arguments]]
-- when using pairs with deleted arguments.
page = mw.text.decode(v, true)
elseif type(k) == 'number' then
sections[k] = v
else
options[k] = v
end
end
options.nopage = yesno (options.nopage); -- make boolean
-- Extract section from page, if present
if page then
local p, s = page:match('^(.-)#(.*)$')
if p then page, sections[1] = p, s end
end
-- Compress the sections array.
local function compressArray(t)
local nums, ret = {}, {}
for num in pairs(t) do
nums[#nums + 1] = num
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
sections = compressArray(sections)
if not sections[1] then -- empty section parameter makes {{Section link}} meaningless
return ('<span style="color:#d33"><span style="font-family:monospace">{{[[Template:Section link|Section link]]}}</span>: required section parameter(s) missing</span>'); -- emit error message and abandon
end
return p._main(page, sections, options)
end
return p
p8mwfbn5hl8c82dtswdvddooi11c3f1
Tempilet:Category link
10
1217
9466
2026-03-28T17:08:14Z
en>HouseBlaster
0
handle different namespace prefixes correctly
9466
wikitext
text/x-wiki
{{Category link/core|1={{#ifeq:{{NAMESPACE:{{{1}}} }}|Category|{{PAGENAME:{{{1}}} }}|{{{1}}} }}|2={{{2|Category:{{#ifeq:{{NAMESPACE:{{{1}}} }}|Category|{{PAGENAME:{{{1}}} }}|{{{1}}} }}}}}|count={{{count|no}}}|page_count={{PAGESINCAT:{{PAGENAME:{{{1}}}}}|{{UC:{{{count_type|ALL}}}}}|R}}|backlog={{{backlog|{{formatnum:{{NUMBEROFPAGES}}|R}}}}}}}<noinclude>
{{Documentation}}
</noinclude>
shagm99jmb6xamiwd9dlpct8cch8cvp
9467
9466
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Category_link]]
9466
wikitext
text/x-wiki
{{Category link/core|1={{#ifeq:{{NAMESPACE:{{{1}}} }}|Category|{{PAGENAME:{{{1}}} }}|{{{1}}} }}|2={{{2|Category:{{#ifeq:{{NAMESPACE:{{{1}}} }}|Category|{{PAGENAME:{{{1}}} }}|{{{1}}} }}}}}|count={{{count|no}}}|page_count={{PAGESINCAT:{{PAGENAME:{{{1}}}}}|{{UC:{{{count_type|ALL}}}}}|R}}|backlog={{{backlog|{{formatnum:{{NUMBEROFPAGES}}|R}}}}}}}<noinclude>
{{Documentation}}
</noinclude>
shagm99jmb6xamiwd9dlpct8cch8cvp
Tempilet:Cl
10
1218
9468
2019-04-24T04:30:48Z
en>JJMC89
0
actual template is in the category
9468
wikitext
text/x-wiki
#REDIRECT [[Template:Category link]]
{{R from move}}
sxb6uqb5pxx7i9ck11lxcop05gxni7w
9469
9468
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cl]]
9468
wikitext
text/x-wiki
#REDIRECT [[Template:Category link]]
{{R from move}}
sxb6uqb5pxx7i9ck11lxcop05gxni7w
Tempilet:No
10
1219
9470
2026-07-11T17:02:17Z
en>HouseBlaster
0
Undid revision [[Special:Diff/1363534438|1363534438]] by [[Special:Contributions/HouseBlaster|HouseBlaster]] ([[User talk:HouseBlaster|talk]]) see talk of [[TM:yes]]
9470
wikitext
text/x-wiki
<noinclude>{| class="wikitable"
|-
|</noinclude>style="background:#FFC7C7;color:black;vertical-align:middle;text-align:{{{align|center}}};{{{style|}}}" class="table-no"|{{{1|No}}}<noinclude>
|}
{{documentation}}
</noinclude>
nghoiochp86tws0qygulg4wjodf0sse
9471
9470
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Template:No]]
9470
wikitext
text/x-wiki
<noinclude>{| class="wikitable"
|-
|</noinclude>style="background:#FFC7C7;color:black;vertical-align:middle;text-align:{{{align|center}}};{{{style|}}}" class="table-no"|{{{1|No}}}<noinclude>
|}
{{documentation}}
</noinclude>
nghoiochp86tws0qygulg4wjodf0sse
Tempilet:Yes
10
1220
9472
2026-07-11T17:01:56Z
en>HouseBlaster
0
Undid revision [[Special:Diff/1363534284|1363534284]] by [[Special:Contributions/HouseBlaster|HouseBlaster]] ([[User talk:HouseBlaster|talk]]) see talk
9472
wikitext
text/x-wiki
<noinclude>
{| class="wikitable"
|-
|</noinclude>style="background:#9EFF9E;color:black;vertical-align:middle;text-align:{{{align|center}}};{{{style|}}}" class="table-yes"|{{{1|Yes}}}<noinclude>
|}
{{documentation}}
</noinclude>
bgtt7vrln31bhly7j9zj7qq9axxg01v
9473
9472
2026-08-23T10:37:56Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Yes]]
9472
wikitext
text/x-wiki
<noinclude>
{| class="wikitable"
|-
|</noinclude>style="background:#9EFF9E;color:black;vertical-align:middle;text-align:{{{align|center}}};{{{style|}}}" class="table-yes"|{{{1|Yes}}}<noinclude>
|}
{{documentation}}
</noinclude>
bgtt7vrln31bhly7j9zj7qq9axxg01v
Tempilet:Cslist
10
1221
9474
2026-08-03T09:13:54Z
en>FaviFake
0
FaviFake moved page [[Template:Cslist]] to [[Template:Comma-separated list]]: Moving for the reason explained at [[Template talk:Hlist#c-FaviFake-20260803091300-Requested_move_3_August_2026]]
9474
wikitext
text/x-wiki
#REDIRECT [[Template:Comma-separated list]]
{{Redirect category shell|
{{R from move}}
}}
hzbg0tyo6fy6je1kh5ycuvxvldhoc10
9475
9474
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Cslist]]
9474
wikitext
text/x-wiki
#REDIRECT [[Template:Comma-separated list]]
{{Redirect category shell|
{{R from move}}
}}
hzbg0tyo6fy6je1kh5ycuvxvldhoc10
Module:Cslist
828
1222
9476
2026-08-03T09:25:53Z
en>FaviFake
0
FaviFake moved page [[Module:Cslist]] to [[Module:Comma-separated list]]: Moving for the reasons explained at [[Template talk:Hlist#c-FaviFake-20260803091300-Requested_move_3_August_2026|this comment]]
9476
Scribunto
text/plain
return require [[Module:Comma-separated list]]
44wv2te3nhv8dab4sy9da0uluqjwpr4
9477
9476
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Cslist]]
9476
Scribunto
text/plain
return require [[Module:Comma-separated list]]
44wv2te3nhv8dab4sy9da0uluqjwpr4
Tempilet:Flowlist
10
1223
9478
2026-08-14T18:00:11Z
en>MusikBot II
0
Protected "[[Template:Flowlist]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 250 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9478
wikitext
text/x-wiki
#REDIRECT [[Template:Flowing list]]
{{Redirect category shell|
{{R from move}}
}}
gnisr91x8eicb3jf6nzd0trfhu3vu09
9479
9478
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Flowlist]]
9478
wikitext
text/x-wiki
#REDIRECT [[Template:Flowing list]]
{{Redirect category shell|
{{R from move}}
}}
gnisr91x8eicb3jf6nzd0trfhu3vu09
Tempilet:Defn
10
1224
9480
2025-02-19T00:15:14Z
en>Shkuru Afshar
0
9480
wikitext
text/x-wiki
<dd {{safesubst<noinclude/>:#if:{{{class|}}}|class="{{{class}}}"|}} {{safesubst<noinclude/>:#if:{{{id|}}}|id="{{{id}}}"|{{safesubst<noinclude/>:#if:{{{term|}}}|id="{{{term}}}-defn{{{2|{{{no|1}}}}}}"|}}|}} {{safesubst<noinclude/>:#if:{{{style|}}}|style="{{{style}}}"|}}>{{safesubst<noinclude/>:#if:{{{2|{{{no|}}}}}}|{{{2|{{{no}}}}}}. |}}{{{defn|{{{1|{{{content}}}}}}}}}</dd><noinclude>
{{documentation}}<!--Please add this template's categories to the /doc subpage, interwikis to Wikidata, not here - thanks!-->
</noinclude>
bvqehh4plupnmplm9g048aerxirkcba
9481
9480
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Defn]]
9480
wikitext
text/x-wiki
<dd {{safesubst<noinclude/>:#if:{{{class|}}}|class="{{{class}}}"|}} {{safesubst<noinclude/>:#if:{{{id|}}}|id="{{{id}}}"|{{safesubst<noinclude/>:#if:{{{term|}}}|id="{{{term}}}-defn{{{2|{{{no|1}}}}}}"|}}|}} {{safesubst<noinclude/>:#if:{{{style|}}}|style="{{{style}}}"|}}>{{safesubst<noinclude/>:#if:{{{2|{{{no|}}}}}}|{{{2|{{{no}}}}}}. |}}{{{defn|{{{1|{{{content}}}}}}}}}</dd><noinclude>
{{documentation}}<!--Please add this template's categories to the /doc subpage, interwikis to Wikidata, not here - thanks!-->
</noinclude>
bvqehh4plupnmplm9g048aerxirkcba
Tempilet:Glossary
10
1225
9482
2024-06-13T03:21:28Z
en>Pppery
0
Oops ...
9482
wikitext
text/x-wiki
<templatestyles src="Glossary/styles.css" />
<dl class="glossary {{{class|}}}" {{#if:{{{style|}}}|style="{{{style}}}"|}} {{#if:{{{id|}}}|id="{{{id}}}"|}}><noinclude>{{glossary end}}
<!--Categories and interwikis go on the /doc page.-->
{{Documentation}}
</noinclude>
ozlm5ph8y8992ad0benlm98j0pt7t65
9483
9482
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Glossary]]
9482
wikitext
text/x-wiki
<templatestyles src="Glossary/styles.css" />
<dl class="glossary {{{class|}}}" {{#if:{{{style|}}}|style="{{{style}}}"|}} {{#if:{{{id|}}}|id="{{{id}}}"|}}><noinclude>{{glossary end}}
<!--Categories and interwikis go on the /doc page.-->
{{Documentation}}
</noinclude>
ozlm5ph8y8992ad0benlm98j0pt7t65
Tempilet:Glossary end
10
1226
9484
2021-05-14T06:45:23Z
en>ಮಲ್ನಾಡಾಚ್ ಕೊಂಕ್ಣೊ
0
Balance tag using noinclude to remove page from Linter report
9484
wikitext
text/x-wiki
<noinclude><dl></noinclude></dl><!--end glossary--><noinclude>
{{Documentation|Template:Glossary/doc}}<!--Categories go in the /doc subpage.-->
</noinclude>
rp0c9akprcgq2q7txzo5i78zwqs12xh
9485
9484
2026-08-23T10:37:57Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Glossary_end]]
9484
wikitext
text/x-wiki
<noinclude><dl></noinclude></dl><!--end glossary--><noinclude>
{{Documentation|Template:Glossary/doc}}<!--Categories go in the /doc subpage.-->
</noinclude>
rp0c9akprcgq2q7txzo5i78zwqs12xh
Tempilet:Term
10
1227
9486
2024-06-10T02:13:17Z
en>Sbb
0
rmv "class=glossary" (unnecessary, containing <dl> has the class; CSS will cascade); rmv "multi=" option (handled automatically by {{glossary}}'s CSS now.
9486
wikitext
text/x-wiki
<dt {{safesubst<noinclude/>:#if:{{{class|}}}|class="{{{class}}}"|}} {{safesubst<noinclude/>:#if: {{{noid|}}}||id="{{safesubst<noinclude/>:#invoke:delink|delink|{{safesubst<noinclude/>:#invoke:String|replace|source={{safesubst<noinclude/>:lc:{{{id|{{{term|{{{1}}}}}}}}}}}|"|<!--blank to strip out double quote mark-->}}}}"}} {{safesubst<noinclude/>:#if:{{{style|}}}|style="{{{style}}}"|}}>{{safesubst<noinclude/>:#if:{{{nondefining|}}}||<dfn>}}{{{content|{{{2|{{{term|{{{1}}}}}}}}}}}}{{safesubst<noinclude/>:#if:{{{nondefining|}}}||</dfn>}}</dt><noinclude>
{{Documentation}}
</noinclude>
98pjzofxvoj3fs4l0jfsto5414hwshs
9487
9486
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Term]]
9486
wikitext
text/x-wiki
<dt {{safesubst<noinclude/>:#if:{{{class|}}}|class="{{{class}}}"|}} {{safesubst<noinclude/>:#if: {{{noid|}}}||id="{{safesubst<noinclude/>:#invoke:delink|delink|{{safesubst<noinclude/>:#invoke:String|replace|source={{safesubst<noinclude/>:lc:{{{id|{{{term|{{{1}}}}}}}}}}}|"|<!--blank to strip out double quote mark-->}}}}"}} {{safesubst<noinclude/>:#if:{{{style|}}}|style="{{{style}}}"|}}>{{safesubst<noinclude/>:#if:{{{nondefining|}}}||<dfn>}}{{{content|{{{2|{{{term|{{{1}}}}}}}}}}}}{{safesubst<noinclude/>:#if:{{{nondefining|}}}||</dfn>}}</dt><noinclude>
{{Documentation}}
</noinclude>
98pjzofxvoj3fs4l0jfsto5414hwshs
Tempilet:Format item
10
1228
9488
2018-12-07T07:48:58Z
en>MusikAnimal
0
Protected "[[Template:Format item]]": [[Wikipedia:High-risk templates|High-risk template]] ([Edit=Require autoconfirmed or confirmed access] (indefinite) [Move=Require autoconfirmed or confirmed access] (indefinite))
9488
wikitext
text/x-wiki
<includeonly>{{#invoke:Item|format}}</includeonly><noinclude>
{{doc}}
</noinclude>
1megg2u367ueqv830p62lg0r5u64yqk
9489
9488
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Format_item]]
9488
wikitext
text/x-wiki
<includeonly>{{#invoke:Item|format}}</includeonly><noinclude>
{{doc}}
</noinclude>
1megg2u367ueqv830p62lg0r5u64yqk
Tempilet:Item
10
1229
9490
2026-05-07T22:38:03Z
en>Tbhotch
0
Reverted edit by [[Special:Contribs/HelloMyNameIsAlphabet|HelloMyNameIsAlphabet]] ([[User talk:HelloMyNameIsAlphabet|talk]]) to last version by MusikAnimal
9490
wikitext
text/x-wiki
<includeonly>{{#invoke:Item|pack}}</includeonly><noinclude>
{{doc}}
</noinclude>
4yxtdqre2hvr0k40m6udmgyrmmjsq51
9491
9490
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Item]]
9490
wikitext
text/x-wiki
<includeonly>{{#invoke:Item|pack}}</includeonly><noinclude>
{{doc}}
</noinclude>
4yxtdqre2hvr0k40m6udmgyrmmjsq51
Tempilet:Markup
10
1230
9492
2025-09-23T01:47:39Z
en>Izno
0
-padding setting
9492
wikitext
text/x-wiki
<includeonly><templatestyles src="Markup/styles.css" />
{| class="markup" style="{{#if:{{{width|}}}|width:{{{width}}};}} {{#if:{{{margin-left|{{{margin|}}}}}}|margin-left:{{{margin-left|{{{margin}}}}}};}} {{{style|}}}"
{{#if:{{{title|}}} |{{!}}+ {{{title}}}}}
{{#if:{{{noheaders|}}}{{{notitle|}}} |
|! scope="col" style="{{{colheaderstyle|}}}{{{col1headerstyle|}}}"{{!}} {{{col1|{{{t1|Markup}}}}}} {{!!}}<!--
-->scope="col" style="{{{colheaderstyle|}}}{{{col2headerstyle|}}}"{{!}} {{{col2|{{{t2|Renders as}}}}}}
}}<!--
-->{{For loop||call=format item|pc1n=template|pc1v=Markup/row|pc2n=col1style|pc2v={{{col1style|}}}|pc3n=col2style|pc3v={{{col2style|}}}|pc4n=c1style|pc4v={{{codestyle|{{{markupstyle|}}}}}}|pc5n=c2style|pc5v={{{outputstyle|}}}|pc6n=tag|pc6v={{{tag|}}}|pc7n=padding|pc7v={{{padding|}}}|pv=item|{{item|c1={{{1|}}}|c2={{{2|}}}}}|{{item|c1={{{3|}}}|c2={{{4|}}}}}|{{item|c1={{{5|}}}|c2={{{6|}}}}}|{{item|c1={{{7|}}}|c2={{{8|}}}}}|{{item|c1={{{9|}}}|c2={{{10|}}}}}|{{item|c1={{{11|}}}|c2={{{12|}}}}}|{{item|c1={{{13|}}}|c2={{{14|}}}}}|{{item|c1={{{15|}}}|c2={{{16|}}}}}|{{item|c1={{{17|}}}|c2={{{18|}}}}}|{{item|c1={{{19|}}}|c2={{{20|}}}}}|{{item|c1={{{21|}}}|c2={{{22|}}}}}|{{item|c1={{{23|}}}|c2={{{24|}}}}}|{{item|c1={{{25|}}}|c2={{{26|}}}}}|{{item|c1={{{27|}}}|c2={{{28|}}}}}|{{item|c1={{{29|}}}|c2={{{30|}}}}}|{{item|c1={{{31|}}}|c2={{{32|}}}}}|{{item|c1={{{33|}}}|c2={{{34|}}}}}|{{item|c1={{{35|}}}|c2={{{36|}}}}}|{{item|c1={{{37|}}}|c2={{{38|}}}}}|{{item|c1={{{39|}}}|c2={{{40|}}}}}}}
|}</includeonly><noinclude>
{{Documentation}}
</noinclude>
jw6x789hojdw59vhx0jcoqy2ni1jdsi
9493
9492
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Markup]]
9492
wikitext
text/x-wiki
<includeonly><templatestyles src="Markup/styles.css" />
{| class="markup" style="{{#if:{{{width|}}}|width:{{{width}}};}} {{#if:{{{margin-left|{{{margin|}}}}}}|margin-left:{{{margin-left|{{{margin}}}}}};}} {{{style|}}}"
{{#if:{{{title|}}} |{{!}}+ {{{title}}}}}
{{#if:{{{noheaders|}}}{{{notitle|}}} |
|! scope="col" style="{{{colheaderstyle|}}}{{{col1headerstyle|}}}"{{!}} {{{col1|{{{t1|Markup}}}}}} {{!!}}<!--
-->scope="col" style="{{{colheaderstyle|}}}{{{col2headerstyle|}}}"{{!}} {{{col2|{{{t2|Renders as}}}}}}
}}<!--
-->{{For loop||call=format item|pc1n=template|pc1v=Markup/row|pc2n=col1style|pc2v={{{col1style|}}}|pc3n=col2style|pc3v={{{col2style|}}}|pc4n=c1style|pc4v={{{codestyle|{{{markupstyle|}}}}}}|pc5n=c2style|pc5v={{{outputstyle|}}}|pc6n=tag|pc6v={{{tag|}}}|pc7n=padding|pc7v={{{padding|}}}|pv=item|{{item|c1={{{1|}}}|c2={{{2|}}}}}|{{item|c1={{{3|}}}|c2={{{4|}}}}}|{{item|c1={{{5|}}}|c2={{{6|}}}}}|{{item|c1={{{7|}}}|c2={{{8|}}}}}|{{item|c1={{{9|}}}|c2={{{10|}}}}}|{{item|c1={{{11|}}}|c2={{{12|}}}}}|{{item|c1={{{13|}}}|c2={{{14|}}}}}|{{item|c1={{{15|}}}|c2={{{16|}}}}}|{{item|c1={{{17|}}}|c2={{{18|}}}}}|{{item|c1={{{19|}}}|c2={{{20|}}}}}|{{item|c1={{{21|}}}|c2={{{22|}}}}}|{{item|c1={{{23|}}}|c2={{{24|}}}}}|{{item|c1={{{25|}}}|c2={{{26|}}}}}|{{item|c1={{{27|}}}|c2={{{28|}}}}}|{{item|c1={{{29|}}}|c2={{{30|}}}}}|{{item|c1={{{31|}}}|c2={{{32|}}}}}|{{item|c1={{{33|}}}|c2={{{34|}}}}}|{{item|c1={{{35|}}}|c2={{{36|}}}}}|{{item|c1={{{37|}}}|c2={{{38|}}}}}|{{item|c1={{{39|}}}|c2={{{40|}}}}}}}
|}</includeonly><noinclude>
{{Documentation}}
</noinclude>
jw6x789hojdw59vhx0jcoqy2ni1jdsi
Tempilet:Markup/row
10
1231
9494
2026-07-06T19:06:00Z
en>ABreault (WMF)
0
Remove no longer needed category
9494
wikitext
text/x-wiki
<noinclude>{|</noinclude><includeonly>{{#if:{{{c1|value}}}| 
{{!-}}
{{!}} style="{{#if:{{{padding|}}}|padding:{{{padding}}};}} {{{col1style|}}}"{{!}} <!--
--><div class="markup-wrapper">{{#switch:{{{tag|}}}
|none = {{{c1|[markup]}}}<!-- mark up -->
|syntaxhighlight = {{#tag:syntaxhighlight |{{{c1|[markup]}}}<!-- mark up -->|lang="wikitext"|style="{{{c1style|}}}"|class="markup-markup"}}
||pre = {{#tag:pre |{{{c1|[markup]}}}<!-- mark up -->|style="{{{c1style|}}}"|class="markup-markup"}}
|#default = {{#tag:{{{tag}}} |{{{c1|[markup]}}}<!-- mark up -->|style="{{{c1style|}}}"}}
}}</div>
{{!}}style{{=}}"{{#if:{{{padding|}}}|padding:{{{padding}}};}} {{{col2style|}}}"{{!}} <!--
--><div class="markup-wrapper" style="{{{c2style|}}}"><!-- renders as -->
{{{c2|[''rendering'']}}}
</div>
}}</includeonly><noinclude>
|}
{{Documentation}}
</noinclude>
44q18stn8xpy9nc7o1obfnqjncmdy65
9495
9494
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Markup/row]]
9494
wikitext
text/x-wiki
<noinclude>{|</noinclude><includeonly>{{#if:{{{c1|value}}}| 
{{!-}}
{{!}} style="{{#if:{{{padding|}}}|padding:{{{padding}}};}} {{{col1style|}}}"{{!}} <!--
--><div class="markup-wrapper">{{#switch:{{{tag|}}}
|none = {{{c1|[markup]}}}<!-- mark up -->
|syntaxhighlight = {{#tag:syntaxhighlight |{{{c1|[markup]}}}<!-- mark up -->|lang="wikitext"|style="{{{c1style|}}}"|class="markup-markup"}}
||pre = {{#tag:pre |{{{c1|[markup]}}}<!-- mark up -->|style="{{{c1style|}}}"|class="markup-markup"}}
|#default = {{#tag:{{{tag}}} |{{{c1|[markup]}}}<!-- mark up -->|style="{{{c1style|}}}"}}
}}</div>
{{!}}style{{=}}"{{#if:{{{padding|}}}|padding:{{{padding}}};}} {{{col2style|}}}"{{!}} <!--
--><div class="markup-wrapper" style="{{{c2style|}}}"><!-- renders as -->
{{{c2|[''rendering'']}}}
</div>
}}</includeonly><noinclude>
|}
{{Documentation}}
</noinclude>
44q18stn8xpy9nc7o1obfnqjncmdy65
Module:Item
828
1232
9496
2019-01-24T21:24:24Z
en>MusikAnimal
0
Protected "[[Module:Item]]": [[Wikipedia:High-risk templates|High-risk module]] ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9496
Scribunto
text/plain
local p = {}
local function escape(str)
return str:gsub("[|\\]", function (c) return string.format("\\%03d", c:byte()) end)
end
local function unescape(str)
return str:gsub("\\(%d%d%d)", function (d) return string.char(d) end)
end
-- Implements [[Template:Item]]
function p.pack(frame)
local parent = frame:getParent()
local result = ''
for key, value in pairs(parent.args) do
result = result .. "|" .. escape(tostring(key)) .. "|" .. escape(value)
end
return result .. "|";
end
local function unpack(str)
local result = { }
for key, value in str:gfind("|([^|]*)|([^|]*)") do
result[unescape(key)] = unescape(value)
end
return result
end
-- Implements [[Template:Component]]
function p.component(frame)
return unpack(frame.args[1])[frame.args[2]]
end
local function getItems(frame)
return frame:getParent().args
end
local function invert(tbl)
local result = { }
for key, value in pairs(tbl) do
result[value] = key
end
return result
end
-- Add args into item as appropriate (see [[Template:Format item]])
local function addArgs(
item, -- unpacked item to modify
args, -- arguments for adding into item
ignore, -- pass in invert{keys to ignore}
shift -- for numbered arguments, args[key+shift] is assigned to item[key]
-- returns: item
)
for key, value in pairs(args) do
if not ignore[key] then
local _, _, paramKey = string.find(key, "^param (.*)")
local _, _, importantKey = string.find(key, "^important (.*)")
paramKey = paramKey or importantKey or key
if shift and type(paramKey) == "number" then
paramKey = paramKey - shift
if paramKey < 1 then paramKey = nil end
end
if paramKey and (importantKey or item[paramKey] == nil) then
item[paramKey] = value
end
end
end
return item
end
-- Implements [[Template:Format item]]
function p.format(frame)
local args = frame:getParent().args
local ignore = invert{ "template", "item" }
local templateArgs = addArgs(unpack(args.item), args, ignore)
return frame:expandTemplate{ title = args.template, args = templateArgs }
end
-- See [[Template:Item#Format each item using a template]]
function p.each(frame)
local args = frame.args
local items = getItems(frame)
local separator = args[1] or ""
local prepend = args[2] or ""
local append = args[3] or ""
local ignore = invert{ "template" }
local shift = 3
local result = ""
for i, item in ipairs(items) do
local templateArgs = addArgs(unpack(item), args, ignore, shift)
result = result .. prepend .. frame:expandTemplate{ title = args.template, args = templateArgs } .. append
if items[i + 1] then
result = result .. separator
end
end
return result
end
-- See [[Template:Item#Gather given parameter from all items]]
function p.gather(frame)
local args = frame.args
local items = getItems(frame)
local parameter = args.parameter or "1"
local templateArgs = { }
for i, item in ipairs(items) do
templateArgs[i] = unpack(item)[parameter]
end
return frame:expandTemplate{ title = args.template, args = templateArgs }
end
return p
8a56kjxfu3plv66z6z732hkase6suqc
9497
9496
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Item]]
9496
Scribunto
text/plain
local p = {}
local function escape(str)
return str:gsub("[|\\]", function (c) return string.format("\\%03d", c:byte()) end)
end
local function unescape(str)
return str:gsub("\\(%d%d%d)", function (d) return string.char(d) end)
end
-- Implements [[Template:Item]]
function p.pack(frame)
local parent = frame:getParent()
local result = ''
for key, value in pairs(parent.args) do
result = result .. "|" .. escape(tostring(key)) .. "|" .. escape(value)
end
return result .. "|";
end
local function unpack(str)
local result = { }
for key, value in str:gfind("|([^|]*)|([^|]*)") do
result[unescape(key)] = unescape(value)
end
return result
end
-- Implements [[Template:Component]]
function p.component(frame)
return unpack(frame.args[1])[frame.args[2]]
end
local function getItems(frame)
return frame:getParent().args
end
local function invert(tbl)
local result = { }
for key, value in pairs(tbl) do
result[value] = key
end
return result
end
-- Add args into item as appropriate (see [[Template:Format item]])
local function addArgs(
item, -- unpacked item to modify
args, -- arguments for adding into item
ignore, -- pass in invert{keys to ignore}
shift -- for numbered arguments, args[key+shift] is assigned to item[key]
-- returns: item
)
for key, value in pairs(args) do
if not ignore[key] then
local _, _, paramKey = string.find(key, "^param (.*)")
local _, _, importantKey = string.find(key, "^important (.*)")
paramKey = paramKey or importantKey or key
if shift and type(paramKey) == "number" then
paramKey = paramKey - shift
if paramKey < 1 then paramKey = nil end
end
if paramKey and (importantKey or item[paramKey] == nil) then
item[paramKey] = value
end
end
end
return item
end
-- Implements [[Template:Format item]]
function p.format(frame)
local args = frame:getParent().args
local ignore = invert{ "template", "item" }
local templateArgs = addArgs(unpack(args.item), args, ignore)
return frame:expandTemplate{ title = args.template, args = templateArgs }
end
-- See [[Template:Item#Format each item using a template]]
function p.each(frame)
local args = frame.args
local items = getItems(frame)
local separator = args[1] or ""
local prepend = args[2] or ""
local append = args[3] or ""
local ignore = invert{ "template" }
local shift = 3
local result = ""
for i, item in ipairs(items) do
local templateArgs = addArgs(unpack(item), args, ignore, shift)
result = result .. prepend .. frame:expandTemplate{ title = args.template, args = templateArgs } .. append
if items[i + 1] then
result = result .. separator
end
end
return result
end
-- See [[Template:Item#Gather given parameter from all items]]
function p.gather(frame)
local args = frame.args
local items = getItems(frame)
local parameter = args.parameter or "1"
local templateArgs = { }
for i, item in ipairs(items) do
templateArgs[i] = unpack(item)[parameter]
end
return frame:expandTemplate{ title = args.template, args = templateArgs }
end
return p
8a56kjxfu3plv66z6z732hkase6suqc
Module:Uses TemplateStyles
828
1233
9500
2026-02-16T01:11:16Z
en>JPxG
0
copy slopped edit from sandbox to provide a link to Special:EditPage for the linked pages; looks great to me on all the testcases, i dont think this will bust anything but yolo [[User:Pppery]] feel free to shoot me if i break anything
9500
Scribunto
text/plain
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local TNT = require('Module:TNT')
local p = {}
local function format(msg, ...)
return TNT.format('I18n/Uses TemplateStyles', msg, ...)
end
local function getConfig()
return mw.loadData('Module:Uses TemplateStyles/config')
end
local function makeEditSup(pageName)
return string.format('<sup>[[[Special:Edit/%s|e]]]</sup>', pageName)
end
-- Build just the "(sandbox)" suffix using the i18n message, without duplicating the main link.
local function makeSandboxSuffix(tsSandboxPrefixed)
-- i18n message is: "$1 ([[$2|sandbox]])"
-- Passing empty $1 yields " ([[:...|sandbox]])" -> trim leading whitespace to get "(sandbox)" portion.
local s = format('sandboxlink', '', ':' .. tsSandboxPrefixed)
return (s:gsub('^%s+', ''))
end
local function renderBox(tStyles)
local boxArgs = {
type = 'notice',
small = true,
image = string.format('[[File:Farm-Fresh css add.svg|32px|alt=%s]]', format('logo-alt'))
}
if #tStyles < 1 then
boxArgs.text = string.format('<strong class="error">%s</strong>', format('error-emptylist'))
else
local cfg = getConfig()
local tStylesLinks = {}
for i, ts in ipairs(tStyles) do
local viewLink = string.format('[[:%s]]', ts)
local editSup = makeEditSup(ts)
local out = viewLink .. editSup
-- Optional sandbox link + sandbox edit link
local tsTitle = mw.title.new(ts)
if tsTitle and cfg['sandbox_title'] then
local tsSandboxTitle = mw.title.new(string.format(
'%s:%s/%s/%s',
tsTitle.nsText,
tsTitle.baseText,
cfg['sandbox_title'],
tsTitle.subpageText
))
if tsSandboxTitle and tsSandboxTitle.exists then
local sandboxSuffix = makeSandboxSuffix(tsSandboxTitle.prefixedText)
local sandboxEditSup = makeEditSup(tsSandboxTitle.prefixedText)
out = out .. ' ' .. sandboxSuffix .. ' ' .. sandboxEditSup
end
end
tStylesLinks[i] = out
end
local tStylesList = mList.makeList('bulleted', tStylesLinks)
boxArgs.text = format(
mw.title.getCurrentTitle():inNamespaces(828, 829) and 'header-module' or 'header-template'
) .. '\n' .. tStylesList
end
return mMessageBox.main('mbox', boxArgs)
end
local function renderTrackingCategories(args, tStyles, titleObj)
if yesno(args.nocat) then
return ''
end
local cfg = getConfig()
local cats = {}
-- Error category
if #tStyles < 1 and cfg['error_category'] then
cats[#cats + 1] = cfg['error_category']
end
-- TemplateStyles category
titleObj = titleObj or mw.title.getCurrentTitle()
if (titleObj.namespace == 10 or titleObj.namespace == 828)
and not cfg['subpage_blacklist'][titleObj.subpageText]
then
local category = args.category or cfg['default_category']
if category then
cats[#cats + 1] = category
end
if not yesno(args.noprotcat) and (cfg['protection_conflict_category'] or cfg['padlock_pattern']) then
local currentProt = titleObj.protectionLevels["edit"] and titleObj.protectionLevels["edit"][1] or nil
local addedLevelCat = false
local addedPadlockCat = false
for _, ts in ipairs(tStyles) do
local tsTitleObj = mw.title.new(ts)
local tsProt = tsTitleObj.protectionLevels["edit"] and tsTitleObj.protectionLevels["edit"][1] or nil
if cfg['padlock_pattern'] and tsProt and not addedPadlockCat then
local content = tsTitleObj:getContent()
if not content:find(cfg['padlock_pattern']) then
cats[#cats + 1] = cfg['missing_padlock_category']
addedPadlockCat = true
end
end
if cfg['protection_conflict_category'] and currentProt and tsProt ~= currentProt and not addedLevelCat then
currentProt = cfg['protection_hierarchy'][currentProt] or 0
tsProt = cfg['protection_hierarchy'][tsProt] or 0
if tsProt < currentProt then
addedLevelCat = true
cats[#cats + 1] = cfg['protection_conflict_category']
end
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.format('[[Category:%s]]', cat)
end
return table.concat(cats)
end
function p._main(args)
local cfg = getConfig()
if #args == 0 then
local prefixed = mw.title.getCurrentTitle().prefixedText
prefixed = prefixed:gsub("/doc", "")
args[1] = prefixed .. "/" .. cfg["default_subpage_name"]
end
local tStyles = mTableTools.compressSparseArray(args)
local box = renderBox(tStyles)
local trackingCategories = renderTrackingCategories(args, tStyles)
return box .. trackingCategories
end
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(args)
end
return p
fzxzfes95mnfacwuhc6k9zeaixdtemr
9501
9500
2026-08-23T10:37:58Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Uses_TemplateStyles]]
9500
Scribunto
text/plain
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local TNT = require('Module:TNT')
local p = {}
local function format(msg, ...)
return TNT.format('I18n/Uses TemplateStyles', msg, ...)
end
local function getConfig()
return mw.loadData('Module:Uses TemplateStyles/config')
end
local function makeEditSup(pageName)
return string.format('<sup>[[[Special:Edit/%s|e]]]</sup>', pageName)
end
-- Build just the "(sandbox)" suffix using the i18n message, without duplicating the main link.
local function makeSandboxSuffix(tsSandboxPrefixed)
-- i18n message is: "$1 ([[$2|sandbox]])"
-- Passing empty $1 yields " ([[:...|sandbox]])" -> trim leading whitespace to get "(sandbox)" portion.
local s = format('sandboxlink', '', ':' .. tsSandboxPrefixed)
return (s:gsub('^%s+', ''))
end
local function renderBox(tStyles)
local boxArgs = {
type = 'notice',
small = true,
image = string.format('[[File:Farm-Fresh css add.svg|32px|alt=%s]]', format('logo-alt'))
}
if #tStyles < 1 then
boxArgs.text = string.format('<strong class="error">%s</strong>', format('error-emptylist'))
else
local cfg = getConfig()
local tStylesLinks = {}
for i, ts in ipairs(tStyles) do
local viewLink = string.format('[[:%s]]', ts)
local editSup = makeEditSup(ts)
local out = viewLink .. editSup
-- Optional sandbox link + sandbox edit link
local tsTitle = mw.title.new(ts)
if tsTitle and cfg['sandbox_title'] then
local tsSandboxTitle = mw.title.new(string.format(
'%s:%s/%s/%s',
tsTitle.nsText,
tsTitle.baseText,
cfg['sandbox_title'],
tsTitle.subpageText
))
if tsSandboxTitle and tsSandboxTitle.exists then
local sandboxSuffix = makeSandboxSuffix(tsSandboxTitle.prefixedText)
local sandboxEditSup = makeEditSup(tsSandboxTitle.prefixedText)
out = out .. ' ' .. sandboxSuffix .. ' ' .. sandboxEditSup
end
end
tStylesLinks[i] = out
end
local tStylesList = mList.makeList('bulleted', tStylesLinks)
boxArgs.text = format(
mw.title.getCurrentTitle():inNamespaces(828, 829) and 'header-module' or 'header-template'
) .. '\n' .. tStylesList
end
return mMessageBox.main('mbox', boxArgs)
end
local function renderTrackingCategories(args, tStyles, titleObj)
if yesno(args.nocat) then
return ''
end
local cfg = getConfig()
local cats = {}
-- Error category
if #tStyles < 1 and cfg['error_category'] then
cats[#cats + 1] = cfg['error_category']
end
-- TemplateStyles category
titleObj = titleObj or mw.title.getCurrentTitle()
if (titleObj.namespace == 10 or titleObj.namespace == 828)
and not cfg['subpage_blacklist'][titleObj.subpageText]
then
local category = args.category or cfg['default_category']
if category then
cats[#cats + 1] = category
end
if not yesno(args.noprotcat) and (cfg['protection_conflict_category'] or cfg['padlock_pattern']) then
local currentProt = titleObj.protectionLevels["edit"] and titleObj.protectionLevels["edit"][1] or nil
local addedLevelCat = false
local addedPadlockCat = false
for _, ts in ipairs(tStyles) do
local tsTitleObj = mw.title.new(ts)
local tsProt = tsTitleObj.protectionLevels["edit"] and tsTitleObj.protectionLevels["edit"][1] or nil
if cfg['padlock_pattern'] and tsProt and not addedPadlockCat then
local content = tsTitleObj:getContent()
if not content:find(cfg['padlock_pattern']) then
cats[#cats + 1] = cfg['missing_padlock_category']
addedPadlockCat = true
end
end
if cfg['protection_conflict_category'] and currentProt and tsProt ~= currentProt and not addedLevelCat then
currentProt = cfg['protection_hierarchy'][currentProt] or 0
tsProt = cfg['protection_hierarchy'][tsProt] or 0
if tsProt < currentProt then
addedLevelCat = true
cats[#cats + 1] = cfg['protection_conflict_category']
end
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.format('[[Category:%s]]', cat)
end
return table.concat(cats)
end
function p._main(args)
local cfg = getConfig()
if #args == 0 then
local prefixed = mw.title.getCurrentTitle().prefixedText
prefixed = prefixed:gsub("/doc", "")
args[1] = prefixed .. "/" .. cfg["default_subpage_name"]
end
local tStyles = mTableTools.compressSparseArray(args)
local box = renderBox(tStyles)
local trackingCategories = renderTrackingCategories(args, tStyles)
return box .. trackingCategories
end
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(args)
end
return p
fzxzfes95mnfacwuhc6k9zeaixdtemr
Module:Uses TemplateStyles/config
828
1234
9502
2024-07-07T01:05:12Z
en>Pppery
0
9502
Scribunto
text/plain
local cfg = {} -- Don’t touch this line.
-- Subpage blacklist: these subpages will not be categorized (except for the
-- error category, which is always added if there is an error).
-- For example “Template:Foo/doc” matches the `doc = true` rule, so it will have
-- no categories. “Template:Foo” and “Template:Foo/documentation” match no rules,
-- so they *will* have categories. All rules should be in the
-- ['<subpage name>'] = true,
-- format.
cfg['subpage_blacklist'] = {
['doc'] = true,
['sandbox'] = true,
['sandbox2'] = true,
['testcases'] = true,
}
-- Sandbox title: if the stylesheet’s title is <template>/<stylesheet>.css, the
-- stylesheet’s sandbox is expected to be at <template>/<sandbox_title>/<stylesheet>.css
-- Set to nil to disable sandbox links.
cfg['sandbox_title'] = 'sandbox'
-- Error category: this category is added if the module call contains errors
-- (e.g. no stylesheet listed). A category name without namespace, or nil
-- to disable categorization (not recommended).
cfg['error_category'] = 'Uses TemplateStyles templates with errors'
-- Default category: this category is added if no custom category is specified
-- in module/template call. A category name without namespace, or nil
-- to disable categorization.
cfg['default_category'] = 'Templates using TemplateStyles'
-- Protection conflict category: this category is added if the protection level
-- of any stylesheet is lower than the protection level of the template. A category name
-- without namespace, or nil to disable categorization (not recommended).
cfg['protection_conflict_category'] = 'Templates using TemplateStyles with a different protection level'
-- Hierarchy of protection levels, used to determine whether one protection level is lower
-- than another and thus should populate protection_conflict_category. No protection is treated as zero
cfg['protection_hierarchy'] = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
-- Padlock pattern: Lua pattern to search on protected stylesheets for, or nil
-- to disable padlock check.
cfg['padlock_pattern'] = '{{pp-'
-- Missing padlock category: this category is added if a protected stylesheet
-- doesn’t contain any padlock template (specified by the above Lua pattern).
-- A category name without namespace (no nil allowed) if the pattern is not nil,
-- unused (and thus may be nil) otherwise.
cfg['missing_padlock_category'] = 'Templates using TemplateStyles without padlocks'
-- Default subpage for the stylesheet if none is given
cfg['default_subpage_name'] = 'styles.css'
return cfg -- Don’t touch this line.
jobuplor7csgdjcx4c6xrtnslslvft4
9503
9502
2026-08-23T10:37:59Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Uses_TemplateStyles/config]]
9502
Scribunto
text/plain
local cfg = {} -- Don’t touch this line.
-- Subpage blacklist: these subpages will not be categorized (except for the
-- error category, which is always added if there is an error).
-- For example “Template:Foo/doc” matches the `doc = true` rule, so it will have
-- no categories. “Template:Foo” and “Template:Foo/documentation” match no rules,
-- so they *will* have categories. All rules should be in the
-- ['<subpage name>'] = true,
-- format.
cfg['subpage_blacklist'] = {
['doc'] = true,
['sandbox'] = true,
['sandbox2'] = true,
['testcases'] = true,
}
-- Sandbox title: if the stylesheet’s title is <template>/<stylesheet>.css, the
-- stylesheet’s sandbox is expected to be at <template>/<sandbox_title>/<stylesheet>.css
-- Set to nil to disable sandbox links.
cfg['sandbox_title'] = 'sandbox'
-- Error category: this category is added if the module call contains errors
-- (e.g. no stylesheet listed). A category name without namespace, or nil
-- to disable categorization (not recommended).
cfg['error_category'] = 'Uses TemplateStyles templates with errors'
-- Default category: this category is added if no custom category is specified
-- in module/template call. A category name without namespace, or nil
-- to disable categorization.
cfg['default_category'] = 'Templates using TemplateStyles'
-- Protection conflict category: this category is added if the protection level
-- of any stylesheet is lower than the protection level of the template. A category name
-- without namespace, or nil to disable categorization (not recommended).
cfg['protection_conflict_category'] = 'Templates using TemplateStyles with a different protection level'
-- Hierarchy of protection levels, used to determine whether one protection level is lower
-- than another and thus should populate protection_conflict_category. No protection is treated as zero
cfg['protection_hierarchy'] = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
-- Padlock pattern: Lua pattern to search on protected stylesheets for, or nil
-- to disable padlock check.
cfg['padlock_pattern'] = '{{pp-'
-- Missing padlock category: this category is added if a protected stylesheet
-- doesn’t contain any padlock template (specified by the above Lua pattern).
-- A category name without namespace (no nil allowed) if the pattern is not nil,
-- unused (and thus may be nil) otherwise.
cfg['missing_padlock_category'] = 'Templates using TemplateStyles without padlocks'
-- Default subpage for the stylesheet if none is given
cfg['default_subpage_name'] = 'styles.css'
return cfg -- Don’t touch this line.
jobuplor7csgdjcx4c6xrtnslslvft4
Module:Transclusion count/data/H
828
1235
9504
2026-08-23T05:08:35Z
en>Ahechtbot
0
[[Wikipedia:BOT|Bot]]: Updated page.
9504
Scribunto
text/plain
return {
["H-phrases"] = 4300,
["HABS"] = 2700,
["HAER"] = 2500,
["HDS"] = 4600,
["HD_Radio"] = 2200,
["HD_color"] = 2900,
["HKG"] = 3600,
["HMAS"] = 6700,
["HMCS"] = 5300,
["HMS"] = 38000,
["HNLMS"] = 3300,
["HOUR"] = 2300,
["HRV"] = 7100,
["HUN"] = 12000,
["HWYACR"] = 59000,
["Hab"] = 14000,
["Hair_space"] = 7800,
["HanCinema_person"] = 2000,
["Handbook_of_Texas"] = 2100,
["Hansard-contribs"] = 9400,
["Harv"] = 6000,
["Harvard_citation"] = 6300,
["Harvard_citation_no_brackets"] = 55000,
["Harvard_citation_text"] = 7900,
["Harvard_citation_year_brackets"] = 6200,
["Harvid"] = 77000,
["Harvnb"] = 53000,
["Harvp"] = 6100,
["Harvtxt"] = 7200,
["HasTemplate"] = 115000,
["Has_short_description"] = 803000,
["Hat"] = 14000,
["Hatnote"] = 806000,
["Hatnote_group"] = 2300,
["Hatnote_inline"] = 3000,
["Height"] = 88000,
["Help_me-helped"] = 16000,
["Helpbox"] = 3100,
["Helpbox/styles.css"] = 3100,
["Helpme-helped"] = 2100,
["Hex2dec"] = 2200,
["Hidden"] = 286000,
["Hidden/FC"] = 3700,
["Hidden_archive_bottom"] = 14000,
["Hidden_archive_top"] = 14000,
["Hidden_archive_top/styles.css"] = 14000,
["Hidden_begin"] = 342000,
["Hidden_begin/styles.css"] = 342000,
["Hidden_category"] = 6800,
["Hidden_end"] = 342000,
["Hidden_ping"] = 5400,
["Hidden_sort_key"] = 22000,
["High-Class"] = 15000,
["High-importance"] = 16000,
["High-use"] = 13000,
["Highlight"] = 8200,
["Highlight/core"] = 8300,
["Highlight_round"] = 4400,
["Highlight_round/styles.css"] = 4400,
["Hilite"] = 2300,
["Historic_Environment_Scotland"] = 3800,
["Historical"] = 25000,
["Historical_Dictionary_of_Switzerland"] = 5100,
["Historical_populations"] = 61000,
["History"] = 7600,
["History_icon"] = 8500,
["History_icon2"] = 8500,
["Hlist"] = 309000,
["Hlist/styles.css"] = 9220000,
["Hmbox"] = 30000,
["Hmbox/styles.css"] = 30000,
["Hndis"] = 77000,
["Hong_Kong_English"] = 3600,
["Horizontal_TOC"] = 7400,
["Horizontal_TOC/styles.css"] = 7400,
["HoursElapsed"] = 35000,
["Hours_elapsed"] = 35000,
["How_to_request_photo_in"] = 3000,
["Howtoreqphotoin"] = 2800,
["Hr"] = 6900,
["Hs"] = 22000,
["Hsp"] = 5000,
["Huge"] = 2200,
["Hugman"] = 7600,
["Human_name_disambiguation"] = 82000,
["Human_readable_duration"] = 35000,
["Humor"] = 4400,
["Hurricane_season_bar"] = 2400,
["Hurricane_season_bar/button"] = 2400,
["Hurricane_season_bar/styles.css"] = 2400,
["Hurricane_status_small"] = 2400,
["Module:HTMLDecode"] = 865000,
["Module:Hatnote"] = 2200000,
["Module:Hatnote/styles.css"] = 2200000,
["Module:Hatnote_group"] = 2300,
["Module:Hatnote_inline"] = 3100,
["Module:Hatnote_list"] = 1280000,
["Module:Hidden_ping"] = 5400,
["Module:High-use"] = 64000,
["Module:Highest_archive_number"] = 346000,
["Module:Historical_populations"] = 61000,
["Module:Historical_populations/styles.css"] = 61000,
["Module:Hms"] = 252000,
}
6zosp25bllcwmwu8q6tdlxou41sfizb
9505
9504
2026-08-23T10:37:59Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Transclusion_count/data/H]]
9504
Scribunto
text/plain
return {
["H-phrases"] = 4300,
["HABS"] = 2700,
["HAER"] = 2500,
["HDS"] = 4600,
["HD_Radio"] = 2200,
["HD_color"] = 2900,
["HKG"] = 3600,
["HMAS"] = 6700,
["HMCS"] = 5300,
["HMS"] = 38000,
["HNLMS"] = 3300,
["HOUR"] = 2300,
["HRV"] = 7100,
["HUN"] = 12000,
["HWYACR"] = 59000,
["Hab"] = 14000,
["Hair_space"] = 7800,
["HanCinema_person"] = 2000,
["Handbook_of_Texas"] = 2100,
["Hansard-contribs"] = 9400,
["Harv"] = 6000,
["Harvard_citation"] = 6300,
["Harvard_citation_no_brackets"] = 55000,
["Harvard_citation_text"] = 7900,
["Harvard_citation_year_brackets"] = 6200,
["Harvid"] = 77000,
["Harvnb"] = 53000,
["Harvp"] = 6100,
["Harvtxt"] = 7200,
["HasTemplate"] = 115000,
["Has_short_description"] = 803000,
["Hat"] = 14000,
["Hatnote"] = 806000,
["Hatnote_group"] = 2300,
["Hatnote_inline"] = 3000,
["Height"] = 88000,
["Help_me-helped"] = 16000,
["Helpbox"] = 3100,
["Helpbox/styles.css"] = 3100,
["Helpme-helped"] = 2100,
["Hex2dec"] = 2200,
["Hidden"] = 286000,
["Hidden/FC"] = 3700,
["Hidden_archive_bottom"] = 14000,
["Hidden_archive_top"] = 14000,
["Hidden_archive_top/styles.css"] = 14000,
["Hidden_begin"] = 342000,
["Hidden_begin/styles.css"] = 342000,
["Hidden_category"] = 6800,
["Hidden_end"] = 342000,
["Hidden_ping"] = 5400,
["Hidden_sort_key"] = 22000,
["High-Class"] = 15000,
["High-importance"] = 16000,
["High-use"] = 13000,
["Highlight"] = 8200,
["Highlight/core"] = 8300,
["Highlight_round"] = 4400,
["Highlight_round/styles.css"] = 4400,
["Hilite"] = 2300,
["Historic_Environment_Scotland"] = 3800,
["Historical"] = 25000,
["Historical_Dictionary_of_Switzerland"] = 5100,
["Historical_populations"] = 61000,
["History"] = 7600,
["History_icon"] = 8500,
["History_icon2"] = 8500,
["Hlist"] = 309000,
["Hlist/styles.css"] = 9220000,
["Hmbox"] = 30000,
["Hmbox/styles.css"] = 30000,
["Hndis"] = 77000,
["Hong_Kong_English"] = 3600,
["Horizontal_TOC"] = 7400,
["Horizontal_TOC/styles.css"] = 7400,
["HoursElapsed"] = 35000,
["Hours_elapsed"] = 35000,
["How_to_request_photo_in"] = 3000,
["Howtoreqphotoin"] = 2800,
["Hr"] = 6900,
["Hs"] = 22000,
["Hsp"] = 5000,
["Huge"] = 2200,
["Hugman"] = 7600,
["Human_name_disambiguation"] = 82000,
["Human_readable_duration"] = 35000,
["Humor"] = 4400,
["Hurricane_season_bar"] = 2400,
["Hurricane_season_bar/button"] = 2400,
["Hurricane_season_bar/styles.css"] = 2400,
["Hurricane_status_small"] = 2400,
["Module:HTMLDecode"] = 865000,
["Module:Hatnote"] = 2200000,
["Module:Hatnote/styles.css"] = 2200000,
["Module:Hatnote_group"] = 2300,
["Module:Hatnote_inline"] = 3100,
["Module:Hatnote_list"] = 1280000,
["Module:Hidden_ping"] = 5400,
["Module:High-use"] = 64000,
["Module:Highest_archive_number"] = 346000,
["Module:Historical_populations"] = 61000,
["Module:Historical_populations/styles.css"] = 61000,
["Module:Hms"] = 252000,
}
6zosp25bllcwmwu8q6tdlxou41sfizb
Tempilet:HTML lists
10
1236
9506
2025-12-19T03:58:01Z
en>Sbb
0
{{tlx}} for {{glossary end}}
9506
wikitext
text/x-wiki
{{navbox top
|name= HTML lists
|title=HTML lists
|state=<includeonly>collapsed</includeonly>
|above = More information — {{hlist|class=inline
| [[Help:List]]
| [[WP:List dos and don'ts]]
| [[WP:Manual of Style/Embedded lists]]
| {{section link|WP:Manual of Style/Accessibility#Lists}}
| [[WP:WikiProject Lists]]
}}
}}
{|style="width:100%"
| style="vertical-align:top; width:32%" |
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|hlist |item1 |item2 }}
|-
|
{{hlist |item1 |item2}}
|}
| rowspan=4 style="width:2%"|
| style="vertical-align:top; width:32%"|
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|flatlist|<br />* item1<br />* item2}}
|-
|
{{flatlist|
* item1
* item2
}}
|}
| rowspan=4 style="width:2%" |
| style="vertical-align:top; width:32%"|
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|cslist |item1 |item2 }}
|-
|
{{cslist |item1 |item2 }}
|}
|-
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Bulleted list
|-
| {{tlx|bulleted list |item1 |item2 }}
|-
|
{{bulleted list |item1 |item2 }}
|}
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Numeric ordered list
|-
| {{tlx|Ordered list |first |second }}
|-
|
{{Ordered list |first |second }}
|}
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Alphabetic ordered list
|-
| {{tlx|Ordered list |list_style_type{{=}}lower-alpha |first |second }}
|-
|
{{Ordered list |list_style_type=lower-alpha |first |second }}
|}
|-
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Unbulleted list
|-
| {{tlx|unbulleted list |item1 |item2 }}
|-
|
{{unbulleted list|item1 |item2 }}
|}
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Unbulleted list
|-
| {{tlx|plainlist|<br />* item1<br />* item2}}
|-
|
{{plainlist|
* item1
* item2
}}
|}
| style="vertical-align:top" rowspan=2|
{| class="wikitable" style="width:100%"
|-
! [[Wikipedia:Manual of Style/Glossaries|Glossary]] or definition list
|-
| {{tlx|glossary}}<br />
{{tlx|term|first term}}{{tlx|defn|first description}}<br />
{{tnull|term|second term}}{{tnull|defn|second description}}<br />
{{tlx|glossary end}}
|-
|
{{glossary}}
{{term|first term}}{{defn|first description}}
{{term|second term}}{{defn|second description}}
{{glossary end}}
|}
|-
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Bulleted list to flow around an image
|-
| <code><nowiki>[[File:Bad Title Example.png|left|thumb|100px]]</nowiki></code><br />
{{tlx|flowlist|<br />*item1<br />*item2}}
|-
|
[[File:Bad Title Example.png|left|thumb|100px]]
{{flowlist|
*item1
*item2
}}
|}
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Ordered list in columns
|-
| {{tlx|columns-list|colwidth{{=}}5em|<br /># first<br /># second}}
|-
|
{{columns-list|colwidth=5em|
# first
# second
}}
|}
| style="vertical-align:top"|
|}
{{navbox bottom
|below = {{cl|List formatting and function templates}}
}}<noinclude>
{{documentation}}
<!-- Please add categories to the /doc subpage; interwikis go to Wikidata -->
</noinclude>
mrnhqir11nmaag7k40s1y5193bkht5b
9507
9506
2026-08-23T10:37:59Z
RAPTOR7762
18
1 revision imported from [[:en:Template:HTML_lists]]
9506
wikitext
text/x-wiki
{{navbox top
|name= HTML lists
|title=HTML lists
|state=<includeonly>collapsed</includeonly>
|above = More information — {{hlist|class=inline
| [[Help:List]]
| [[WP:List dos and don'ts]]
| [[WP:Manual of Style/Embedded lists]]
| {{section link|WP:Manual of Style/Accessibility#Lists}}
| [[WP:WikiProject Lists]]
}}
}}
{|style="width:100%"
| style="vertical-align:top; width:32%" |
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|hlist |item1 |item2 }}
|-
|
{{hlist |item1 |item2}}
|}
| rowspan=4 style="width:2%"|
| style="vertical-align:top; width:32%"|
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|flatlist|<br />* item1<br />* item2}}
|-
|
{{flatlist|
* item1
* item2
}}
|}
| rowspan=4 style="width:2%" |
| style="vertical-align:top; width:32%"|
{| class="wikitable" style="width:100%"
|-
! Horizontal list
|-
| {{tlx|cslist |item1 |item2 }}
|-
|
{{cslist |item1 |item2 }}
|}
|-
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Bulleted list
|-
| {{tlx|bulleted list |item1 |item2 }}
|-
|
{{bulleted list |item1 |item2 }}
|}
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Numeric ordered list
|-
| {{tlx|Ordered list |first |second }}
|-
|
{{Ordered list |first |second }}
|}
| style="vertical-align:top;"|
{| class="wikitable" style="width:100%"
|-
! Alphabetic ordered list
|-
| {{tlx|Ordered list |list_style_type{{=}}lower-alpha |first |second }}
|-
|
{{Ordered list |list_style_type=lower-alpha |first |second }}
|}
|-
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Unbulleted list
|-
| {{tlx|unbulleted list |item1 |item2 }}
|-
|
{{unbulleted list|item1 |item2 }}
|}
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Unbulleted list
|-
| {{tlx|plainlist|<br />* item1<br />* item2}}
|-
|
{{plainlist|
* item1
* item2
}}
|}
| style="vertical-align:top" rowspan=2|
{| class="wikitable" style="width:100%"
|-
! [[Wikipedia:Manual of Style/Glossaries|Glossary]] or definition list
|-
| {{tlx|glossary}}<br />
{{tlx|term|first term}}{{tlx|defn|first description}}<br />
{{tnull|term|second term}}{{tnull|defn|second description}}<br />
{{tlx|glossary end}}
|-
|
{{glossary}}
{{term|first term}}{{defn|first description}}
{{term|second term}}{{defn|second description}}
{{glossary end}}
|}
|-
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Bulleted list to flow around an image
|-
| <code><nowiki>[[File:Bad Title Example.png|left|thumb|100px]]</nowiki></code><br />
{{tlx|flowlist|<br />*item1<br />*item2}}
|-
|
[[File:Bad Title Example.png|left|thumb|100px]]
{{flowlist|
*item1
*item2
}}
|}
| style="vertical-align:top"|
{| class="wikitable" style="width:100%"
|-
! Ordered list in columns
|-
| {{tlx|columns-list|colwidth{{=}}5em|<br /># first<br /># second}}
|-
|
{{columns-list|colwidth=5em|
# first
# second
}}
|}
| style="vertical-align:top"|
|}
{{navbox bottom
|below = {{cl|List formatting and function templates}}
}}<noinclude>
{{documentation}}
<!-- Please add categories to the /doc subpage; interwikis go to Wikidata -->
</noinclude>
mrnhqir11nmaag7k40s1y5193bkht5b
Tempilet:Navbox lists
10
1237
9508
2018-05-30T19:49:39Z
en>Ahecht
0
Ahecht moved page [[Template:Navbox lists]] to [[Template:HTML lists]]: title is "HTML lists"
9508
wikitext
text/x-wiki
#REDIRECT [[Template:HTML lists]]
{{R from move}}
g95cnhimutsd14rvq5fqfs6l9bicefi
9509
9508
2026-08-23T10:37:59Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Navbox_lists]]
9508
wikitext
text/x-wiki
#REDIRECT [[Template:HTML lists]]
{{R from move}}
g95cnhimutsd14rvq5fqfs6l9bicefi
Tempilet:Hlist/doc
10
1238
9510
2026-08-03T08:38:22Z
en>FaviFake
0
/* */ Fix order of templates at the top
9510
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Categories go at the bottom of this page and interwikis go in Wikidata. -->
{{tlr|clear=right|Horizontal list|dotlist}}
{{used in system|in [[MediaWiki:Citethispage-content]]}}
{{Uses TemplateStyles}}
{{Lua|Module:List}}
{{cascade-protected template}}
This template creates [[WP:HLIST|horizontal lists]]. Each item in the list may be individually styled with [[CSS]].
Lists output by {{tl|Flatlist}} and {{tl|Hlist}} are semantically and visually identical, and differ only in the wiki-markup used to create the lists.
__TOC__
{{-}}
== Usage ==
'''Basic usage'''
{{pre|<nowiki>{{</nowiki>hlist<nowiki>|</nowiki>''first item''<nowiki>|</nowiki>''second item''<nowiki>|</nowiki>''third item''<nowiki>|</nowiki>...<nowiki>}}</nowiki>}}
'''All parameters'''
{{pre|
<nowiki>{{</nowiki>hlist
<nowiki>|</nowiki>''first item''<nowiki>|</nowiki>''second item''<nowiki>|</nowiki>''third item''<nowiki>|</nowiki>...
<nowiki>|class = </nowiki>''class for div tag''
<nowiki>|style = </nowiki>''style for div tag''
<nowiki>|list_style = </nowiki>''style for ul tag''
<nowiki>|item_style = </nowiki>''style for all li tags''
<nowiki>|item1_style = </nowiki>''style for first li tag''
<nowiki>|item2_style = </nowiki>''style for second li tag''
<nowiki>|</nowiki>...
<nowiki>|indent = </nowiki>''the number of tabs to indent''
<nowiki>}}</nowiki>
}}
'''Example'''
{{tnull|hlist|Jazz|rock|pop|rap}}
produces:
{{hlist|Jazz|rock|pop|rap}}
== Parameters ==
* Positional parameters (<code>1</code>, <code>2</code>, <code>3</code>...): these are the list items. If no list items are present, the module will output nothing.
* <code>class</code>: a custom class for the {{tag|div}} tags surrounding the list. Set to <code>inline</code> when using {{tlf|hlist}} inside text.
* <code>style</code>: a custom CSS style for the {{tag|div}} tags surrounding the list, e.g. <code>font-size: 90%;</code>.
* <code>list_style</code>: a custom CSS style for the {{tag|ul}} tags around the list. The format is the same as for the {{para|style}} parameter.
* <code>item_style</code>: a custom CSS style for all of the list items (the {{Tag|li}} tags). The format is the same as for the {{para|style}} parameter.
*: Avoid using the style <code>white-space:nowrap</code> in the <code>item_style</code> parameter, because it will have the unintended effect of avoiding line breaks anywhere in the list, instead of just inside the list item; the workaround is to move this style in the <code>list_style</code> parameter, and then insert {{Tl|Wbr}} at the ''beginning'' of each item value, to insert an invisible word-break opportunity (and not at ''end'' of the item value, as the word-break would occur just before the trailing spaced-bullet separator).
* <code>item1_style</code>, <code>item2_style</code>, <code>item3_style</code>...: custom CSS styles for each of the list items. The format is the same as for the {{para|style}} parameter.
* <code>indent</code>: the number of tabs to indent the list. Default value is 0.
== Examples ==
{{Markup
| <nowiki>{{hlist|entry1|entry2|entry3|entry4|entry5|entry6|entry7|entry8|entry9}}</nowiki>
| {{hlist|entry1|entry2|entry3|entry4|entry5|entry6|entry7|entry8|entry9}}
| <nowiki>✘ Giant planets ({{hlist|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}).</nowiki>
| ✘ Giant planets ({{hlist|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}). ''(incorrect markup)''
| <nowiki>✔ Giant planets ({{hlist|class=inline|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}).</nowiki>
| ✔ Giant planets ({{hlist|class=inline|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}). ''(correct markup)''
| <nowiki>{{hlist|Winner|Runner-up|Third place|indent=2}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|indent=2}}
| <nowiki>{{hlist|Winner|Runner-up|Third place|item_style=color:blue;}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|item_style=color:blue;}}
| <nowiki>{{hlist|Winner|Runner-up|Third place|item1_style=background-color:yellow;color:black;|item2_style=background-color:silver;color:black;}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|item1_style=background-color:yellow;color:black;|item2_style=background-color:silver;color:black;}}
}}
== Avoiding Linter errors ==
{{tlf|hlist}} will produce [[Wikipedia:Linter|Linter]] [[Special:LintErrors/misc-tidy-replacement-issues|errors]] if placed inside a template that uses {{tag|span}} tags, such as {{tl|small}}, {{tl|larger}}, etc. To avoid this, use the substitutions from the table below:
{| class="wikitable"
! {{no|}} {{cross}} Incorrect markup !! {{yes|}} {{tick}} Correct markup
|-
| <code><nowiki>{{small|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:85%}}</nowiki></code>
|-
| <code><nowiki>{{resize|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:90%}}</nowiki></code>
|-
| <code><nowiki>{{midsize|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:92%}}</nowiki></code>
|-
| <code><nowiki>{{larger|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{big|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{large|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{huge|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:180%}}</nowiki></code>
|-
| <code><nowiki>{{resize|x%|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:x%}}</nowiki></code>
|-
| <code><nowiki>{{font|size=x%|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:x%}}</nowiki></code>
|-
| <code><nowiki>{{nowrap|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=white-space: nowrap}}</nowiki></code>
|}
{{navbox lists}}
<includeonly>{{Sandbox other||
<!-- Categories go here, and interwikis go in Wikidata -->
[[Category:Inline list formatting templates]]
[[Category:Variadic templates]]
}}</includeonly>
86fp5ecvthhid98b1nf6o3uiq73kqlr
9511
9510
2026-08-23T10:37:59Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Hlist/doc]]
9510
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Categories go at the bottom of this page and interwikis go in Wikidata. -->
{{tlr|clear=right|Horizontal list|dotlist}}
{{used in system|in [[MediaWiki:Citethispage-content]]}}
{{Uses TemplateStyles}}
{{Lua|Module:List}}
{{cascade-protected template}}
This template creates [[WP:HLIST|horizontal lists]]. Each item in the list may be individually styled with [[CSS]].
Lists output by {{tl|Flatlist}} and {{tl|Hlist}} are semantically and visually identical, and differ only in the wiki-markup used to create the lists.
__TOC__
{{-}}
== Usage ==
'''Basic usage'''
{{pre|<nowiki>{{</nowiki>hlist<nowiki>|</nowiki>''first item''<nowiki>|</nowiki>''second item''<nowiki>|</nowiki>''third item''<nowiki>|</nowiki>...<nowiki>}}</nowiki>}}
'''All parameters'''
{{pre|
<nowiki>{{</nowiki>hlist
<nowiki>|</nowiki>''first item''<nowiki>|</nowiki>''second item''<nowiki>|</nowiki>''third item''<nowiki>|</nowiki>...
<nowiki>|class = </nowiki>''class for div tag''
<nowiki>|style = </nowiki>''style for div tag''
<nowiki>|list_style = </nowiki>''style for ul tag''
<nowiki>|item_style = </nowiki>''style for all li tags''
<nowiki>|item1_style = </nowiki>''style for first li tag''
<nowiki>|item2_style = </nowiki>''style for second li tag''
<nowiki>|</nowiki>...
<nowiki>|indent = </nowiki>''the number of tabs to indent''
<nowiki>}}</nowiki>
}}
'''Example'''
{{tnull|hlist|Jazz|rock|pop|rap}}
produces:
{{hlist|Jazz|rock|pop|rap}}
== Parameters ==
* Positional parameters (<code>1</code>, <code>2</code>, <code>3</code>...): these are the list items. If no list items are present, the module will output nothing.
* <code>class</code>: a custom class for the {{tag|div}} tags surrounding the list. Set to <code>inline</code> when using {{tlf|hlist}} inside text.
* <code>style</code>: a custom CSS style for the {{tag|div}} tags surrounding the list, e.g. <code>font-size: 90%;</code>.
* <code>list_style</code>: a custom CSS style for the {{tag|ul}} tags around the list. The format is the same as for the {{para|style}} parameter.
* <code>item_style</code>: a custom CSS style for all of the list items (the {{Tag|li}} tags). The format is the same as for the {{para|style}} parameter.
*: Avoid using the style <code>white-space:nowrap</code> in the <code>item_style</code> parameter, because it will have the unintended effect of avoiding line breaks anywhere in the list, instead of just inside the list item; the workaround is to move this style in the <code>list_style</code> parameter, and then insert {{Tl|Wbr}} at the ''beginning'' of each item value, to insert an invisible word-break opportunity (and not at ''end'' of the item value, as the word-break would occur just before the trailing spaced-bullet separator).
* <code>item1_style</code>, <code>item2_style</code>, <code>item3_style</code>...: custom CSS styles for each of the list items. The format is the same as for the {{para|style}} parameter.
* <code>indent</code>: the number of tabs to indent the list. Default value is 0.
== Examples ==
{{Markup
| <nowiki>{{hlist|entry1|entry2|entry3|entry4|entry5|entry6|entry7|entry8|entry9}}</nowiki>
| {{hlist|entry1|entry2|entry3|entry4|entry5|entry6|entry7|entry8|entry9}}
| <nowiki>✘ Giant planets ({{hlist|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}).</nowiki>
| ✘ Giant planets ({{hlist|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}). ''(incorrect markup)''
| <nowiki>✔ Giant planets ({{hlist|class=inline|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}).</nowiki>
| ✔ Giant planets ({{hlist|class=inline|[[Jupiter|J]]|[[Saturn|S]]|[[Uranus|U]]|[[Neptune|N]]}}). ''(correct markup)''
| <nowiki>{{hlist|Winner|Runner-up|Third place|indent=2}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|indent=2}}
| <nowiki>{{hlist|Winner|Runner-up|Third place|item_style=color:blue;}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|item_style=color:blue;}}
| <nowiki>{{hlist|Winner|Runner-up|Third place|item1_style=background-color:yellow;color:black;|item2_style=background-color:silver;color:black;}}</nowiki>
| {{hlist|Winner|Runner-up|Third place|item1_style=background-color:yellow;color:black;|item2_style=background-color:silver;color:black;}}
}}
== Avoiding Linter errors ==
{{tlf|hlist}} will produce [[Wikipedia:Linter|Linter]] [[Special:LintErrors/misc-tidy-replacement-issues|errors]] if placed inside a template that uses {{tag|span}} tags, such as {{tl|small}}, {{tl|larger}}, etc. To avoid this, use the substitutions from the table below:
{| class="wikitable"
! {{no|}} {{cross}} Incorrect markup !! {{yes|}} {{tick}} Correct markup
|-
| <code><nowiki>{{small|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:85%}}</nowiki></code>
|-
| <code><nowiki>{{resize|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:90%}}</nowiki></code>
|-
| <code><nowiki>{{midsize|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:92%}}</nowiki></code>
|-
| <code><nowiki>{{larger|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{big|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{large|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:120%}}</nowiki></code>
|-
| <code><nowiki>{{huge|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:180%}}</nowiki></code>
|-
| <code><nowiki>{{resize|x%|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:x%}}</nowiki></code>
|-
| <code><nowiki>{{font|size=x%|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=font-size:x%}}</nowiki></code>
|-
| <code><nowiki>{{nowrap|{{hlist|...}}}}</nowiki></code> || <code><nowiki>{{hlist|...|style=white-space: nowrap}}</nowiki></code>
|}
{{navbox lists}}
<includeonly>{{Sandbox other||
<!-- Categories go here, and interwikis go in Wikidata -->
[[Category:Inline list formatting templates]]
[[Category:Variadic templates]]
}}</includeonly>
86fp5ecvthhid98b1nf6o3uiq73kqlr
Tempilet:Glossary/styles.css
10
1239
9512
2024-06-13T03:21:51Z
en>Pppery
0
Protected "[[Template:Glossary/styles.css]]": [[WP:High-risk templates|High-risk template or module]] ([Edit=Require autoconfirmed or confirmed access] (indefinite) [Move=Require autoconfirmed or confirmed access] (indefinite))
9512
sanitized-css
text/css
/* {{pp-template}} */
.glossary dt {
margin-top: 0.4em;
}
.glossary dt + dt {
margin-top: -0.2em;
}
/* the inline styles that were defined in {gbq}/{gquote};
simply use {quote} within {defn}, will work like {gbq} */
.glossary .templatequote {
margin-top: 0;
margin-bottom: -0.5em;
}
4hh821x02ojnxsxxaojq51gaveybu7m
9513
9512
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Glossary/styles.css]]
9512
sanitized-css
text/css
/* {{pp-template}} */
.glossary dt {
margin-top: 0.4em;
}
.glossary dt + dt {
margin-top: -0.2em;
}
/* the inline styles that were defined in {gbq}/{gquote};
simply use {quote} within {defn}, will work like {gbq} */
.glossary .templatequote {
margin-top: 0;
margin-bottom: -0.5em;
}
4hh821x02ojnxsxxaojq51gaveybu7m
Tempilet:Category link/core
10
1240
9514
2024-07-22T17:59:58Z
en>MusikBot II
0
Changed protection settings for "[[Template:Category link/core]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 322812 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite))
9514
wikitext
text/x-wiki
[[:Category:{{{1}}}|{{{2}}}]]{{#if:{{Yesno|1={{{count|no}}}}}| <small style="{{#ifexpr:{{{page_count}}}>={{{backlog}}}|font-weight: bold; color: #DD0000;}}">( {{formatnum:{{{page_count}}}}} )</small>}}<noinclude>
{{Documentation|Template:Category link/doc}}
</noinclude>
77gpt1bl3z1t1b6sim8w905lwpmzfkw
9515
9514
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Category_link/core]]
9514
wikitext
text/x-wiki
[[:Category:{{{1}}}|{{{2}}}]]{{#if:{{Yesno|1={{{count|no}}}}}| <small style="{{#ifexpr:{{{page_count}}}>={{{backlog}}}|font-weight: bold; color: #DD0000;}}">( {{formatnum:{{{page_count}}}}} )</small>}}<noinclude>
{{Documentation|Template:Category link/doc}}
</noinclude>
77gpt1bl3z1t1b6sim8w905lwpmzfkw
Tempilet:Markup/styles.css
10
1241
9516
2026-07-06T18:16:25Z
en>ABreault (WMF)
0
For [[phab:T398967|T398967]], see the talk page
9516
sanitized-css
text/css
/* {{pp-template|small=yes}} */
.markup {
margin: 0;
margin-bottom: 0.5em;
border-width: medium;
padding: 0;
}
.markup > caption {
font-weight: bold;
}
.markup > tbody > tr > th[scope=col] {
width: 50%;
}
.markup > tbody > tr > td {
background: var(--background-color-interactive-subtle, #f8f9fa);
color:inherit;
border: 1px solid #eaecf0;
padding: 5px;
vertical-align: top;
}
.markup-wrapper > :first-child {
margin-top: 0;
}
.markup-wrapper > :last-child {
margin-bottom: 0;
}
.markup-markup {
margin: 0;
border: none;
overflow-wrap: break-word;
white-space: pre-wrap;
}
code.markup-markup {
padding: 0;
}
pre.markup-markup {
padding: 2px 0 0;
}
/* These are for the anti-pattern of using <syntaxhighlight/> inside {{Markup}},
use |tag=syntaxhighlight instead */
.markup-markup .mw-highlight {
margin: 0;
}
.markup-markup .mw-highlight pre {
border: none;
}
/* These are for |tag=syntaxhighlight */
div.markup-markup.mw-highlight > pre {
padding: 0;
border: 0;
}
6vxis1e6usecpamywbv21jwq8pnzc24
9517
9516
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Markup/styles.css]]
9516
sanitized-css
text/css
/* {{pp-template|small=yes}} */
.markup {
margin: 0;
margin-bottom: 0.5em;
border-width: medium;
padding: 0;
}
.markup > caption {
font-weight: bold;
}
.markup > tbody > tr > th[scope=col] {
width: 50%;
}
.markup > tbody > tr > td {
background: var(--background-color-interactive-subtle, #f8f9fa);
color:inherit;
border: 1px solid #eaecf0;
padding: 5px;
vertical-align: top;
}
.markup-wrapper > :first-child {
margin-top: 0;
}
.markup-wrapper > :last-child {
margin-bottom: 0;
}
.markup-markup {
margin: 0;
border: none;
overflow-wrap: break-word;
white-space: pre-wrap;
}
code.markup-markup {
padding: 0;
}
pre.markup-markup {
padding: 2px 0 0;
}
/* These are for the anti-pattern of using <syntaxhighlight/> inside {{Markup}},
use |tag=syntaxhighlight instead */
.markup-markup .mw-highlight {
margin: 0;
}
.markup-markup .mw-highlight pre {
border: none;
}
/* These are for |tag=syntaxhighlight */
div.markup-markup.mw-highlight > pre {
padding: 0;
border: 0;
}
6vxis1e6usecpamywbv21jwq8pnzc24
Tempilet:Flowing list
10
1242
9518
2026-08-07T18:00:06Z
en>MusikBot II
0
Protected "[[Template:Flowing list]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 250 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9518
wikitext
text/x-wiki
<templatestyles src="Flowing list/styles.css" /><div class="flowlist {{{class|}}}" {{#if: {{{style|}}}|style="{{{style}}}"}}>{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
kfkv7ge8h32s6cllecpo85qqygcrm2r
9519
9518
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Flowing_list]]
9518
wikitext
text/x-wiki
<templatestyles src="Flowing list/styles.css" /><div class="flowlist {{{class|}}}" {{#if: {{{style|}}}|style="{{{style}}}"}}>{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
kfkv7ge8h32s6cllecpo85qqygcrm2r
Tempilet:Flowing list/styles.css
10
1243
9520
2026-08-09T18:00:00Z
en>MusikBot II
0
Protected "[[Template:Flowing list/styles.css]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 250 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite))
9520
sanitized-css
text/css
.flowlist ul {
overflow-x: hidden;
margin-left: 0;
padding-left: 1.6em;
}
.flowlist ol {
overflow-x: hidden;
margin-left: 0;
padding-left: 3.2em;
}
.flowlist dl {
overflow-x: hidden;
}
igrr8xl5xvxo8f8317d995u5rnberye
9521
9520
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Flowing_list/styles.css]]
9520
sanitized-css
text/css
.flowlist ul {
overflow-x: hidden;
margin-left: 0;
padding-left: 1.6em;
}
.flowlist ol {
overflow-x: hidden;
margin-left: 0;
padding-left: 3.2em;
}
.flowlist dl {
overflow-x: hidden;
}
igrr8xl5xvxo8f8317d995u5rnberye
Tempilet:Comma-separated list
10
1244
9522
2026-08-03T09:14:26Z
en>FaviFake
0
postmove cu
9522
wikitext
text/x-wiki
<templatestyles src="Comma-separated list/styles.css" />{{#invoke:Cslist |makelist}}<noinclude>
{{documentation}}<!-- Please place categories and language links on the /doc page, not here! -->
</noinclude>
f5e6nxkqj3wn9eesvktm7s58dl10gse
9523
9522
2026-08-23T10:38:00Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Comma-separated_list]]
9522
wikitext
text/x-wiki
<templatestyles src="Comma-separated list/styles.css" />{{#invoke:Cslist |makelist}}<noinclude>
{{documentation}}<!-- Please place categories and language links on the /doc page, not here! -->
</noinclude>
f5e6nxkqj3wn9eesvktm7s58dl10gse
Tempilet:Comma-separated list/styles.css
10
1245
9524
2026-08-03T09:13:56Z
en>FaviFake
0
FaviFake moved page [[Template:Cslist/styles.css]] to [[Template:Comma-separated list/styles.css]] without leaving a redirect: Moving for the reason explained at [[Template talk:Hlist#c-FaviFake-20260803091300-Requested_move_3_August_2026]]
9524
sanitized-css
text/css
/* {{pp-template}} */
/* make an inline list with either comma or semicolon separators */
ul.cslist, ul.sslist, ul.andlist, ul.andlistoxford {
margin: 0;
padding: 0;
display: inline-block;
list-style: none;
}
ul.cslist-embedded {
display: inline;
}
.cslist li, .sslist li, .andlist li, .andlistoxford li {
margin: 0;
padding: 0 0.25em 0 0;
display: inline-block;
}
.cslist li:after, .andlistoxford li:after {
content: ", ";
}
.sslist li:after {
content: "; ";
}
.cslist li:last-child:after,
.sslist li:last-child:after,
.andlist li:last-child:after, .andlistoxford li:last-child:after {
content: none;
}
.andlist li:nth-last-child(2):after {
content: " and ";
}
.andlistoxford li:nth-last-child(2):after {
content: ", and ";
}
sjeps3to13rvtslga1mu0t849vt5a6d
9525
9524
2026-08-23T10:38:01Z
RAPTOR7762
18
1 revision imported from [[:en:Template:Comma-separated_list/styles.css]]
9524
sanitized-css
text/css
/* {{pp-template}} */
/* make an inline list with either comma or semicolon separators */
ul.cslist, ul.sslist, ul.andlist, ul.andlistoxford {
margin: 0;
padding: 0;
display: inline-block;
list-style: none;
}
ul.cslist-embedded {
display: inline;
}
.cslist li, .sslist li, .andlist li, .andlistoxford li {
margin: 0;
padding: 0 0.25em 0 0;
display: inline-block;
}
.cslist li:after, .andlistoxford li:after {
content: ", ";
}
.sslist li:after {
content: "; ";
}
.cslist li:last-child:after,
.sslist li:last-child:after,
.andlist li:last-child:after, .andlistoxford li:last-child:after {
content: none;
}
.andlist li:nth-last-child(2):after {
content: " and ";
}
.andlistoxford li:nth-last-child(2):after {
content: ", and ";
}
sjeps3to13rvtslga1mu0t849vt5a6d
Module:Comma-separated list
828
1246
9526
2026-08-03T09:25:53Z
en>FaviFake
0
FaviFake moved page [[Module:Cslist]] to [[Module:Comma-separated list]]: Moving for the reasons explained at [[Template talk:Hlist#c-FaviFake-20260803091300-Requested_move_3_August_2026|this comment]]
9526
Scribunto
text/plain
p = {}
p.makelist = function(frame)
local args = frame.args
if not args[1] then
args = frame:getParent().args
if not args[1] then return end
end
local semi = args.semi
if semi then semi = semi:lower() end
local oxford = args.oxford
if oxford then oxford = oxford:lower() end
local embedded = args.embedded
if embedded then embedded = embedded:lower() end
local out = ""
for k, v in ipairs(args) do
v = mw.text.trim(v)
if v ~= "" then
out = out .. "<li>" .. v .. "</li>"
end
end
local listclass = ""
if semi then
listclass = listclass .. "sslist"
else
if oxford then
if args[3] then
listclass = listclass .. "andlistoxford"
else
listclass = listclass .. "andlist"
end
else
listclass = listclass .. "cslist"
end
end
if embedded then
listclass = listclass .. " cslist-embedded"
end
if out ~= "" then
return '<ul class="'.. listclass ..'">' .. out .. '</ul>'
end
end
return p
3fj8k957dg266yw39h8kuabkuaqeqqq
9527
9526
2026-08-23T10:38:01Z
RAPTOR7762
18
1 revision imported from [[:en:Module:Comma-separated_list]]
9526
Scribunto
text/plain
p = {}
p.makelist = function(frame)
local args = frame.args
if not args[1] then
args = frame:getParent().args
if not args[1] then return end
end
local semi = args.semi
if semi then semi = semi:lower() end
local oxford = args.oxford
if oxford then oxford = oxford:lower() end
local embedded = args.embedded
if embedded then embedded = embedded:lower() end
local out = ""
for k, v in ipairs(args) do
v = mw.text.trim(v)
if v ~= "" then
out = out .. "<li>" .. v .. "</li>"
end
end
local listclass = ""
if semi then
listclass = listclass .. "sslist"
else
if oxford then
if args[3] then
listclass = listclass .. "andlistoxford"
else
listclass = listclass .. "andlist"
end
else
listclass = listclass .. "cslist"
end
end
if embedded then
listclass = listclass .. " cslist-embedded"
end
if out ~= "" then
return '<ul class="'.. listclass ..'">' .. out .. '</ul>'
end
end
return p
3fj8k957dg266yw39h8kuabkuaqeqqq