Wikipedia
gvwiki
https://gv.wikipedia.org/wiki/Ard-ghuillag
MediaWiki 1.47.0-wmf.17
first-letter
Meanyn
Er lheh
Resooney
Ymmydeyr
Resooney ymmydeyr
Wikipedia
Resooney Wikipedia
Coadan
Resooney coadan
MediaWiki
Resooney MediaWiki
Clowan
Resooney clowan
Cooney
Resooney cooney
Ronney
Resooney ronney
TimedText
TimedText talk
Module
Module talk
Event
Event talk
Resooney ymmydeyr:MacTire02
3
2773
392670
383348
2026-09-01T20:26:24Z
WikiBayer
13794
/* Infobox styles */ new section
392670
wikitext
text/x-wiki
{{Tashtlannyn}}
{{Tashtlann resoonaght MacTire}}
== Translation request ==
Hello, MacTire02.
Can you translate and upload the articles [[:en:Mount Bazardüzü]] as [[Slieau Bazardüzü]] and [[:en:Phlegraean Fields]] as [[Campi Flegrei]] in Manx Wikipedia?
Yours sincerely, [[Ymmydeyr:Kurcke|Kurcke]] ([[Resooney ymmydeyr:Kurcke|resoonaght]]) 20:44, 25 Toshiaght Arree 2026 (UTC)
: Ta'n chied art jeant nish. Lhisin ny ronnaghyn y chroo nish as, lurg shen, neem y nah art. Bee yn nah art soit ec [[ny Magheryn Phlegraeagh]].
: I have finished the first article. I just need to create the categories and then I will do the second article. The second article will be located at [[ny Magheryn Phlegraeagh]].
: [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 04:07, 26 Toshiaght Arree 2026 (UTC)
::Thank you very much for the new articles. [[Ymmydeyr:Kurcke|Kurcke]] ([[Resooney ymmydeyr:Kurcke|resoonaght]]) 07:42, 27 Toshiaght Arree 2026 (UTC)
== You may be an eligible candidate for the U4C election ==
<div lang="en" dir="ltr" class="mw-content-ltr">
Greetings,
The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee (U4C)]] seeks candidates for the 2026 election. The U4C is the global committee responsible for overseeing enforcement of the [[foundation:Special:MyLanguage/Policy:Universal Code of Conduct|Universal Code of Conduct]]. Elections are held annually, if elected a committee member serves for two years.
This year the U4C requires candidates to hold administrator rights on at least one wiki, which is why you are being contacted as you appear to hold this right. There are other requirements, such as candidates must be at least 18 years old and may not be employed by the Wikimedia Foundation or other related chapters and affiliates. You can find more information in the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026#Call_for_Candidates|call for candidates on Meta-wiki]]. Additionally, the committee's working language is English; some ability to communicate in English is required.
The election opens on 18 May, if you are eligible and interested you have until 10 May to submit your candidacy. There will week between for candidates to answer questions from the community. Voting takes place privately in [[m:Special:MyLanguage/SecurePoll|SecurePoll]], successful candidates must receive at least 60% support. More information is available on [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|the 2026 Elections page]], including timelines and other candidacy information. If you read over the material and consider yourself qualified, please consider submitting your name to run for the committee. If you think someone else in your community might be interested and qualified, please encourage them to run.
In partnership with the U4C -- [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User_talk:Keegan (WMF)|talk]]) 18:33, 28 Averil 2026 (UTC) </div>
<!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Keegan_(WMF)/test&oldid=30471754 -->
== Manx ==
Hello. I'm looking for translation of descriptions "studio album by Basshunter", "song by Käärijä and Basshunter" and "single by Käärijä and Basshunter" in Manx for Wikidata items. Would you help? [[Ymmydeyr:Eurohunter|Eurohunter]] ([[Resooney ymmydeyr:Eurohunter|resoonaght]]) 19:56, 30 Averil 2026 (UTC)
:These would be, respectively, "albym seyrlann lesh Basshunter", "arrane lesh Käärijä as Basshunter", and "singyl lesh Käärijä as Basshunter". Best, [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 19:58, 30 Averil 2026 (UTC)
:: Thank you. Could we also have "compilation album by Basshunter", "promotional single by Basshunter", "music video by Basshunter" and "lyric video by Basshunter"? It would be complete then. [[Ymmydeyr:Eurohunter|Eurohunter]] ([[Resooney ymmydeyr:Eurohunter|resoonaght]]) 19:50, 7 Boaldyn 2026 (UTC)
== Possible unblock ==
Hi [[Ymmydeyr:MacTire02|MacTire02]], I would like to check if it is possible, to unblock [[User:TDKR Chicago 101]]? They're active simplewiki-sysop and I think things changed from 2013. It would be great if you could consider that. Thank you very much! [[Ymmydeyr:NDG|NDG]] ([[Resooney ymmydeyr:NDG|resoonaght]]) 22:10, 17 Mean Souree 2026 (UTC)
:@[[Ymmydeyr:NDG|NDG]] I have removed the block. I did note on the block removal that any repeat of past behaviours will result in the block being reinstated permanently. There will be no warnings the next time. Failure to engage in commentary when an admin contacts this user over an issue will result in a block. Disrupting the project in any way will result in a block. Please communicate that to the user. [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 01:11, 18 Mean Souree 2026 (UTC)
::Thanks a lot for giving it a try! [[Ymmydeyr:NDG|NDG]] ([[Resooney ymmydeyr:NDG|resoonaght]]) 05:08, 18 Mean Souree 2026 (UTC)
== KPop Demon Hunters ==
Could you please add more content to the page [[KPop Demon Hunters]]? Thank you. [[Er lheh:Contributions/~2026-35926-97|~2026-35926-97]] ([[Resooney ymmydeyr:~2026-35926-97|talk]]) 19:37, 20 Mean Souree 2026 (UTC)
== Infobox styles ==
you can now edit the Style. I have migrate the code to Templatestyles [[Clowan:Kishtey fys/styles.css]] [[Ymmydeyr:WikiBayer|WikiBayer]] ([[Resooney ymmydeyr:WikiBayer|resoonaght]]) 20:26, 1 Mean Fouyir 2026 (UTC)
7iqtawhrjho1tciqlgxj74ualirhedf
392672
392670
2026-09-01T20:28:25Z
MacTire02
219
/* Infobox styles */ Freggyrt
392672
wikitext
text/x-wiki
{{Tashtlannyn}}
{{Tashtlann resoonaght MacTire}}
== Translation request ==
Hello, MacTire02.
Can you translate and upload the articles [[:en:Mount Bazardüzü]] as [[Slieau Bazardüzü]] and [[:en:Phlegraean Fields]] as [[Campi Flegrei]] in Manx Wikipedia?
Yours sincerely, [[Ymmydeyr:Kurcke|Kurcke]] ([[Resooney ymmydeyr:Kurcke|resoonaght]]) 20:44, 25 Toshiaght Arree 2026 (UTC)
: Ta'n chied art jeant nish. Lhisin ny ronnaghyn y chroo nish as, lurg shen, neem y nah art. Bee yn nah art soit ec [[ny Magheryn Phlegraeagh]].
: I have finished the first article. I just need to create the categories and then I will do the second article. The second article will be located at [[ny Magheryn Phlegraeagh]].
: [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 04:07, 26 Toshiaght Arree 2026 (UTC)
::Thank you very much for the new articles. [[Ymmydeyr:Kurcke|Kurcke]] ([[Resooney ymmydeyr:Kurcke|resoonaght]]) 07:42, 27 Toshiaght Arree 2026 (UTC)
== You may be an eligible candidate for the U4C election ==
<div lang="en" dir="ltr" class="mw-content-ltr">
Greetings,
The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee (U4C)]] seeks candidates for the 2026 election. The U4C is the global committee responsible for overseeing enforcement of the [[foundation:Special:MyLanguage/Policy:Universal Code of Conduct|Universal Code of Conduct]]. Elections are held annually, if elected a committee member serves for two years.
This year the U4C requires candidates to hold administrator rights on at least one wiki, which is why you are being contacted as you appear to hold this right. There are other requirements, such as candidates must be at least 18 years old and may not be employed by the Wikimedia Foundation or other related chapters and affiliates. You can find more information in the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026#Call_for_Candidates|call for candidates on Meta-wiki]]. Additionally, the committee's working language is English; some ability to communicate in English is required.
The election opens on 18 May, if you are eligible and interested you have until 10 May to submit your candidacy. There will week between for candidates to answer questions from the community. Voting takes place privately in [[m:Special:MyLanguage/SecurePoll|SecurePoll]], successful candidates must receive at least 60% support. More information is available on [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|the 2026 Elections page]], including timelines and other candidacy information. If you read over the material and consider yourself qualified, please consider submitting your name to run for the committee. If you think someone else in your community might be interested and qualified, please encourage them to run.
In partnership with the U4C -- [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User_talk:Keegan (WMF)|talk]]) 18:33, 28 Averil 2026 (UTC) </div>
<!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Keegan_(WMF)/test&oldid=30471754 -->
== Manx ==
Hello. I'm looking for translation of descriptions "studio album by Basshunter", "song by Käärijä and Basshunter" and "single by Käärijä and Basshunter" in Manx for Wikidata items. Would you help? [[Ymmydeyr:Eurohunter|Eurohunter]] ([[Resooney ymmydeyr:Eurohunter|resoonaght]]) 19:56, 30 Averil 2026 (UTC)
:These would be, respectively, "albym seyrlann lesh Basshunter", "arrane lesh Käärijä as Basshunter", and "singyl lesh Käärijä as Basshunter". Best, [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 19:58, 30 Averil 2026 (UTC)
:: Thank you. Could we also have "compilation album by Basshunter", "promotional single by Basshunter", "music video by Basshunter" and "lyric video by Basshunter"? It would be complete then. [[Ymmydeyr:Eurohunter|Eurohunter]] ([[Resooney ymmydeyr:Eurohunter|resoonaght]]) 19:50, 7 Boaldyn 2026 (UTC)
== Possible unblock ==
Hi [[Ymmydeyr:MacTire02|MacTire02]], I would like to check if it is possible, to unblock [[User:TDKR Chicago 101]]? They're active simplewiki-sysop and I think things changed from 2013. It would be great if you could consider that. Thank you very much! [[Ymmydeyr:NDG|NDG]] ([[Resooney ymmydeyr:NDG|resoonaght]]) 22:10, 17 Mean Souree 2026 (UTC)
:@[[Ymmydeyr:NDG|NDG]] I have removed the block. I did note on the block removal that any repeat of past behaviours will result in the block being reinstated permanently. There will be no warnings the next time. Failure to engage in commentary when an admin contacts this user over an issue will result in a block. Disrupting the project in any way will result in a block. Please communicate that to the user. [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 01:11, 18 Mean Souree 2026 (UTC)
::Thanks a lot for giving it a try! [[Ymmydeyr:NDG|NDG]] ([[Resooney ymmydeyr:NDG|resoonaght]]) 05:08, 18 Mean Souree 2026 (UTC)
== KPop Demon Hunters ==
Could you please add more content to the page [[KPop Demon Hunters]]? Thank you. [[Er lheh:Contributions/~2026-35926-97|~2026-35926-97]] ([[Resooney ymmydeyr:~2026-35926-97|talk]]) 19:37, 20 Mean Souree 2026 (UTC)
== Infobox styles ==
you can now edit the Style. I have migrate the code to Templatestyles [[Clowan:Kishtey fys/styles.css]] [[Ymmydeyr:WikiBayer|WikiBayer]] ([[Resooney ymmydeyr:WikiBayer|resoonaght]]) 20:26, 1 Mean Fouyir 2026 (UTC)
:Thank you so much! [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 20:28, 1 Mean Fouyir 2026 (UTC)
fnkxlccbdfre3o48j1py7flxsfngkg7
MediaWiki:Common.css
8
5180
392665
370306
2026-09-01T20:22:44Z
WikiBayer
13794
Move to Template Style
392665
css
text/css
/*
'''Common CSS for all skins'''
{{interwiki-all}}
<pre><nowiki>*/
/* Main page fixes */
#interwiki-completelist {
font-weight: bold;
}
/* Don't display some stuff on the main page */
body.page-Ard-ghuillag #deleteconfirm,
body.page-Ard-ghuillag #t-cite,
body.page-Ard-ghuillag #footer-info-lastmod,
body.page-Ard-ghuillag #siteSub,
body.page-Ard-ghuillag #contentSub,
body.page-Ard-ghuillag #ca-delete {
display: none;
}
body.page-Ard-ghuillag h1.firstHeading {
display: none !important;
}
body.page-Ard-ghuillag #Ard-ghuillag {
margin-top: 0;
}
body.page-Main_Page #mp-topbanner {
clear: both;
}
/* make the list of references look smaller */
ol.references,
div.reflist,
div.refbegin {
font-size: 90%; /* Default font-size */
margin-bottom: 0.5em;
}
div.reflist ol.references {
font-size: 100%; /* Reset font-size when nested in div.reflist */
list-style-type: inherit; /* Enable custom list style types */
}
/* Highlight clicked reference in blue to help navigation */
ol.references li:target,
sup.reference:target,
span.citation:target {
background-color: #DEF;
}
/* Ensure refs in table headers and the like aren't bold or italic */
sup.reference {
font-weight: normal;
font-style: normal;
}
/* Allow hidden ref errors to be shown by user CSS */
span.brokenref {
display: none;
}
/* Styling for Citations */
cite {
font-style: normal;
word-wrap: break-word;
}
/* If there is an inline link to a full citation, the full citation will turn blue when the inline link is clicked */
cite:target {
background-color: #DEF;
}
/* Do not expand URLs within citations for printing. The urls should be included explicitly, to avoid confusion */
@media print {
#content cite a.external.text:after {
display: none;
}
}
/* For linked citation numbers and document IDs, where the number need not be shown on a screen or a handheld, but should be included in the printed version */
@media screen, handheld, projection {
cite *.printonly {
display: none;
}
}
/* default skin for navigation boxes */
table.navbox {
background-color: #f9f9f9;
border: 1px solid #aaa;
clear: both;
font-size: 90%;
margin: 1em 0em 0em;
padding: 2px;
text-align: center;
width: 100%;
}
table.navbox th {
background-color: #ccf;
padding-left: 1em;
padding-right: 1em;
}
table.navbox tr:not(:first-child) th {
background-color: #ddf;
}
@media print {
.navbox {
display: none;
}
}
/* Standard talk template style */
.Talk-Notice {
border: 1px solid #C0C090;
background-color: #F8EABA;
margin-bottom: 3px;
width: 85%;
border-spacing: 3px;
margin-left: auto;
margin-right: auto;
}
.Talk-Notice:after {
content: "The CSS for this template should be changed. See [[Wikipedia:Template Standardisation]].";
}
/* Make template background appear correctly on all browsers */
.Talk-Notice td {
background: inherit;
}
/* Persondata */
table.persondata {
border: 1px solid #aaa;
display: none;
speak: none;
}
.persondata-label {
color: #aaa;
}
/* Makes redirects appear in italics in categories and on [[Special:Allpages]] */
.redirect-in-category, .allpagesredirect {
font-style: italic;
}
/* Class for links with loudspeaker icon next to them */
/* (Used in [[Template:Audio]] and the like to make the speaker clickable) */
.audiolink a {
background: url("//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Loudspeaker.svg/11px-Loudspeaker.svg.png") center left no-repeat !important;
padding-left: 20px !important;
padding-right: 0 !important;
}
/* Icons for medialist templates [[Template:Listen]], [[Template:Multi-listen_start]], [[Template:Video]], [[Template:Multi-video_start]] */
div.listenlist {
background: url("//upload.wikimedia.org/wikipedia/commons/thumb/a/a6/Gnome-speakernotes.png/30px-Gnome-speakernotes.png");
padding-left: 40px;
}
div.videolist, div.multivideolist {
background: url("//upload.wikimedia.org/wikipedia/en/thumb/2/20/Tango-video-x-generic.png/40px-Tango-video-x-generic.png");
padding-left: 50px;
}
/* Style rules for media list templates */
div.medialist {
min-height: 50px;
margin: 1em;
background-position: top left;
background-repeat: no-repeat;
}
div.medialist ul {
list-style-type: none;
list-style-image: none;
margin: 0;
}
div.medialist ul li {
padding-bottom: 0.5em;
}
div.medialist ul li li {
font-size: 91%;
padding-bottom: 0;
}
/* Change the external link icon to an Adobe icon for all PDF files */
/* (in browsers that support these CSS selectors, like Mozilla and Opera) */
#bodyContent a[href$=".pdf"].external,
#bodyContent a[href*=".pdf?"].external,
#bodyContent a[href*=".pdf#"].external,
#bodyContent a[href$=".PDF"].external,
#bodyContent a[href*=".PDF?"].external,
#bodyContent a[href*=".PDF#"].external {
background: url(//upload.wikimedia.org/wikipedia/commons/thumb/2/23/Icons-mini-file_acrobat.gif/15px-Icons-mini-file_acrobat.gif) center right no-repeat;
padding-right: 16px;
}
/* Change the external link icon to an Adobe icon anywhere the PDFlink class */
/* is used (notably Template:PDFlink). This works in IE, unlike the above. */
span.PDFlink a {
background: url(//upload.wikimedia.org/wikipedia/commons/thumb/2/23/Icons-mini-file_acrobat.gif/15px-Icons-mini-file_acrobat.gif) center right no-repeat !important;
padding-right: 17px !important;
}
span.geolink a {
background: url(//upload.wikimedia.org/wikipedia/en/a/a7/Monobook-globe.png) center right no-repeat !important;
padding-right: 11px !important;
}
/* Content in columns with CSS instead of tables [[Template:Columns]] */
div.columns-2 div.column {
float: left;
width: 50%;
min-width: 300px;
}
div.columns-3 div.column {
float: left;
width: 33.3%;
min-width: 200px;
}
div.columns-4 div.column {
float: left;
width: 25%;
min-width: 150px;
}
div.columns-5 div.column {
float: left;
width: 20%;
min-width: 120px;
}
/*Add formatting to make sure that "external references" from [[Template:Ref]] do
not get URL expansion, not even when printed. The mechanism up to MediaWiki 1.4 was
that the HTML code contained a SPAN following the anchor A; this SPAN had the class
"urlexpansion", which was not displayed on screen, but was shown when the medium was
"print". The rules below ensure (a) that there is no extra padding to the right of
the anchor (displayed as "[<number>]"), (b) that there is no "external link arrow" for
the link, and (c) that this SPAN of class "urlexpansion" is never shown.
[[Ymmydeyr:Krinkle|Krinkle]] ([[Resooney ymmydeyr:Krinkle|talk]]) 05:18, 18 Mee Houney 2016 (UTC)
*/
.plainlinksneverexpand {
background: none ! important;
padding: 0 ! important;
}
.plainlinksneverexpand .urlexpansion {
display: none ! important;
}
/* Make sure that ext links displayed within "plainlinksneverexpand" don't get
the arrow...
*/
.plainlinksneverexpand a {
background: none !important;
padding: 0 !important;
}
/* With MediaWiki 1.5, the mechanism has changed: instead of a SPAN of class "urlexpansion"
following the anchor A, the anchor itself now has class "external autonumber" and the
expansion is inserted when printing (see the common printing style sheet at
//en.wikipedia.org/w/skins/common/commonPrint.css) using the ":after" pseudo-
element of CSS. We have to switch this off for links due to Template:Ref!
[[Ymmydeyr:Krinkle|Krinkle]] ([[Resooney ymmydeyr:Krinkle|talk]]) 05:18, 18 Mee Houney 2016 (UTC)
*/
.plainlinksneverexpand a.external.text:after {
display: none !important;
}
.plainlinksneverexpand a.external.autonumber:after {
display: none !important;
}
/* Messagebox templates */
.messagebox {
border: 1px solid #aaa;
background-color: #f9f9f9;
width: 80%;
margin: 0 auto 1em auto;
padding: .2em;
}
.messagebox.merge {
border: 1px solid #c0b8cc;
background-color: #f0e5ff;
text-align: center;
}
.messagebox.cleanup {
border: 1px solid #9f9fff;
background-color: #efefff;
text-align: center;
}
.messagebox.standard-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
}
.messagebox.nested-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
width: 100%;
margin: 2px 4px 2px 4px;
}
.messagebox.small {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
}
.messagebox.small-talk {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
background: #F8EABA;
}
/* Stylesheet for navigations bars, cf. [[de:w:Wikipedia:Navigationsleisten]] */
div.BoxenVerschmelzen,
div.NavFrame {
margin: 0px;
padding: 2px;
border: 1px solid #aaaaaa;
text-align: center;
border-collapse: collapse;
font-size: 95%;
clear:both;
}
div.BoxenVerschmelzen div.NavFrame {
border-style: none;
border-style: hidden;
}
div.NavFrame + div.NavFrame {
border-top-style: none;
border-top-style: hidden;
}
div.NavPic {
background-color: #ffffff;
margin: 0px;
padding: 2px;
float: left;
}
div.NavFrame div.NavHead {
font-weight: bold;
font-size: 100%;
background-color: #efefef;
}
div.NavFrame p {
font-size: 100%;
}
div.NavFrame div.NavContent {
font-size: 100%;
}
div.NavFrame div.NavContent p {
font-size: 100%;
}
div.NavEnd {
margin: 0px;
padding: 0px;
line-height: 1px;
clear: both;
}
/* Stylesheet for 'toggle'-Button of navigation bars, implemented in [[MediaWiki:Common.js]] */
.NavToggle {
font-size: x-small;
float:right;
}
/* Workaround für Internet Explorer 6 */
div.NavFrame, div.NavPic, .NavToggle {
position:relative;
}
/* margin above navigation bars */
div.BoxenVerschmelzen,
div.NavFrame {
margin-top: 1.5em;
}
div.BoxenVerschmelzen div.NavFrame {
margin-top: 0;
}
div.NavFrame + div.NavFrame {
margin-top: 0;
}
/* Article message box template styles */
table.ambox {
width: 80%;
margin: 0 auto;
border-collapse: collapse;
background: #f8fcff;
border: 1px solid #aaa;
border-left: 10px solid #1e90ff; /* Default "notice" blue */
}
table.ambox th, table.ambox td { /* The message body cell(s) */
padding: 0.25em 0.5em; /* 0.5em left/right */
}
table.ambox td.ambox-image { /* The left image cell */
width: 52px;
padding: 2px 0px 2px 0.5em; /* 0.5em left, 0px right */
text-align: center;
}
table.ambox td.ambox-imageright { /* The right image cell */
width: 52px;
padding: 2px 4px 2px 0px; /* 0px left, 4px right */
text-align: center;
}
table.ambox-notice {
border-left: 10px solid #1e90ff; /* DodgerBlue */
/* border-right: 10px solid #1e90ff; */ /* If you want two blue bars */
}
table.ambox-serious {
border-left: 10px solid #b22222; /* FireBrick */
}
table.ambox-content {
border-left: 10px solid #f28500; /* Tangerine */
}
table.ambox-style {
border-left: 10px solid #f4c430; /* Saffron */
}
table.ambox-merge {
border-left: 10px solid #9932cc; /* DarkOrchid */
}
table.ambox-growth {
border-left: 10px solid #228b22; /* Forest green */
}
table.ambox.ambox-mini { /* small floating box variant */
float: right;
clear: right;
margin: 0 0 0 1em;
width: 25%;
}
/* Put a checker background at the image description page only visible if the image has transparent background */
#file img {background: url("//upload.wikimedia.org/wikipedia/commons/5/5d/Checker-16x16.png") repeat;}
/* Support for Template:IPA, Template:Unicode and Template:Polytonic. The inherit declaration resets the font for all browsers except MSIE6. The empty comment must remain. Please copy any changes to [[Template:IPA fonts]] and [[Template:Unicode fonts]]. */
.IPA {
font-family: "Chrysanthi Unicode", "Doulos SIL", Gentium, GentiumAlt, Code2000, "TITUS Cyberbit Basic", "DejaVu Sans", "Bitstream Cyberbit", "Arial Unicode MS", "Lucida Sans Unicode", "Hiragino Kaku Gothic Pro", "Matrix Unicode";
font-family /**/:inherit;
}
.Unicode {
font-family: Code2000, Code2001, "Free Serif", "TITUS Cyberbit Basic", "Doulos SIL", "Chrysanthi Unicode", "Bitstream Cyberbit", "Bitstream CyberBase", Thryomanes, Gentium, GentiumAlt, "Lucida Grande", "Free Sans", "Arial Unicode MS", "Microsoft Sans Serif", "Lucida Sans Unicode";
font-family /**/:inherit;
}
.latinx {
font-family: Code2000, Code2001, "TITUS Cyberbit Basic", "Microsoft Sans Serif";
font-family /**/:inherit;
}
.polytonic {
font-family: Athena, Gentium, "Palatino Linotype", "Arial Unicode MS", "Lucida Sans Unicode", "Lucida Grande", Code2000;
font-family /**/:inherit;
}
.mufi {
font-family: Alphabetum, Cardo, LeedsUni, Junicode, "TITUS Cyberbit Basic", ALPHA-Demo;
}
/* pseudo-classes in support of [[Template:lang]]. */
:lang(he) {
font-family: "SBL Hebrew", "Ezra SIL SR", "Ezra SIL", Cardo, "Chrysanthi Unicode", "TITUS Cyberbit Basic", "Arial Unicode MS", Narkisim, "Times New Roman";
font-family /**/:inherit;
}
:lang(fa) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(ps) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(ur) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(sux-Xsux) {
font-family: Akkadian;
font-family /**/:inherit;
}
:lang(ja) {
font-family: Code2000, "Arial Unicode MS", "Bitstream Cyberbit", "Bitstream CyberCJK", IPAGothic, IPAPGothic, IPAUIGothic, "Kochi Gothic", IPAMincho, IPAPMincho;
font-family /**/:inherit;
}
:lang(ko) {
font-family: "Adobe Myungjo Std M", AppleMyungjo, "Baekmuk Batang", "Baekmuk Gulim", Batang, Dotum, DotumChe, Gulim, GulimChe, HYGothic-Extra, HYMyeongJo-Extra, "New Gulim", UnBatang, UnDotum, UnYetgul, UWKMJF;
font-family /**/:inherit;
}
:lang(zh-Hans) {
font-family: "Adobe Song Std L", "AR PL ShanHeiSun Uni", "AR PL ShanHeiSun Uni MBE", "MS Hei", "MS Song", SimHei;
font-family /**/:inherit;
}
:lang(zh-Hant) {
font-family: "Adobe Ming Std L", "AR PL New Sung", "AR PL ZenKai Uni", "AR PL ZenKai Uni MBE", MingLiU, PMingLiU;
font-family /**/:inherit;
}
:lang(grc) {
font-family: Athena, Gentium, "Palatino Linotype", "Arial Unicode MS", "Lucida Sans Unicode", "Lucida Grande", Code2000;
font-family /**/:inherit;
}
#wpSave {
font-weight: bold;
}
/* class hiddenStructure is defunct. See [[Wikipedia:hiddenStructure]] */
.hiddenStructure {
display: inline ! important;
color: #f00;
background-color: #0f0;
}
/* Removes underlines from links */
.nounderlines a {
text-decoration: none;
}
/* Remove underline from IPA links */
.IPA a:link, .IPA a:visited {
text-decoration: none;
}
/* Removes useless links from printout */
@media print {
#privacy, #about, #disclaimer {display:none;}
}
#EnWpMpBook { background-image: url(//upload.wikimedia.org/wikipedia/en/7/7e/MP-open-book.png); }
#EnWpMpSearch { background: url(//upload.wikimedia.org/wikipedia/en/a/ae/MP-magnifying-glass.png) no-repeat top right; }
#EnWpMpSearchInner { float: right; width: 20em; text-align: center; }
#EnWpMpBook2 { background-image: url(//upload.wikimedia.org/wikipedia/commons/8/8e/MP-open-book2.png); }
/* Standard Navigationsleisten, aka box hiding thingy from .de. Documentation at [[Wikipedia:NavFrame]]. */
div.Boxmerge,
div.NavFrame {
margin: 0px;
padding: 4px;
border: 1px solid #aaa;
text-align: center;
border-collapse: collapse;
font-size: 95%;
}
div.Boxmerge div.NavFrame {
border-style: none;
border-style: hidden;
}
div.NavFrame + div.NavFrame {
border-top-style: none;
border-top-style: hidden;
}
div.NavPic {
background-color: #fff;
margin: 0px;
padding: 2px;
float: left;
}
div.NavFrame div.NavHead {
height: 1.6em;
font-weight: bold;
background-color: #ccf;
position:relative;
}
div.NavFrame p {
font-size: 100%;
}
div.NavFrame div.NavContent {
font-size: 100%;
}
div.NavFrame div.NavContent p {
font-size: 100%;
}
div.NavEnd {
margin: 0px;
padding: 0px;
line-height: 1px;
clear: both;
}
a.NavToggle {
position: absolute;
top: 0px;
right: 3px;
font-weight: normal;
font-size: smaller;
}
/* Coloured watchlist numbers */
.mw-plusminus-pos {
color: #006400; /* darkgreen */
}
/* .mw-plusminus-null currently at developer default */
.mw-plusminus-neg {
color: #8B0000; /* darkred */
}
.dablink {
font-style: italic;
padding-left: 2em;
}
.dablink i {
font-style: normal;
}
/* Style for horizontal UL lists */
.horizontal ul {
padding: 0;
margin: 0;
}
.horizontal li {
padding: 0 0.6em 0 0.4em;
display: inline;
border-right: 1px solid;
}
.horizontal li:last-child {
border-right: none;
padding-right: 0;
}
/* Geographical coordinates
To display coordinates using the notation in the source code, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: none }
.geo-dec { display: inline } .geo-dms { display: inline }
To display coordinates using decimal notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: inline } .geo-dms { display: none }
To display coordinates using DMS notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: none } .geo-dms { display: inline }
To display coordinates in both decimal and DMS notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: inline } .geo-dms { display: inline }
.geo-multi-punct { display: inline }
See [[Template:Coor link]] for how these are used.
Note that the classes "geo", "longitude", and "latitude" are not just styles but also used by the [[Geo microformat]], so the names should not be changed.
*/
.geo-default { display: inline; }
.geo-nondefault { display: none; }
.geo-dms { display: inline; }
.geo-dec { display: inline; }
.geo-multi-punct { display: none; }
.longitude .latitude {
white-space: nowrap;
}
/* This is used for the Geo microformat, but no style is needed for now other than .geo-dec. */
.geo { }
/***** end Geo-related */
/* When <div class="nonumtoc"> is used on the table of contents, the ToC will display without numbers */
.nonumtoc .tocnumber { display:none; }
.nonumtoc #toc ul,
.nonumtoc .toc ul {
line-height: 1.5em;
list-style: none;
margin: .3em 0 0;
padding: 0;
}
.nonumtoc #toc ul ul,
.nonumtoc .toc ul ul {
margin: 0 0 0 2em;
}
/* Allow limiting of which header levels are shown in a TOC; <div class="toclimit-3">, for
instance, will limit to showing ==headings== and ===headings=== but no further (as long as
there are no =headings= on the page, which there shouldn't be according to the MoS). */
.toclimit-2 .toclevel-2 {display:none;}
.toclimit-3 .toclevel-3 {display:none;}
.toclimit-4 .toclevel-4 {display:none;}
.toclimit-5 .toclevel-5 {display:none;}
.toclimit-6 .toclevel-6 {display:none;}
.toclimit-7 .toclevel-7 {display:none;}
/* Allow transcluded pages to display in lists rather than a table. Compatible in Firefox; incompatible in IE6. */
.listify td {display:list-item}
.listify tr {display:block}
.listify table {display:block}
/* Styling for Template:Quote */
blockquote.templatequote { margin-top: 0; }
blockquote.templatequote div.templatequotecite {
line-height: 1em;
text-align: left;
padding-left: 2em;
margin-top: 0;
}
blockquote.templatequote div.templatequotecite cite {
font-size: smaller;
}
div.user-block {
padding: 5px;
border: 1px solid #A9A9A9;
background-color: #FFEFD5;
}
/* Prevents line breaks in links; see docs at Template:Nowraplinks */
.nowraplinks a {
white-space: nowrap;
}
/* Enables borders on PNG images in IE 5.5 and 6 */
.thumbborder {
border:1px solid #DDDDDD;
}
/* Support for script templates. The inherit declaration resets the font for all browsers except MSIE6. The empty comment must remain. */
.IPA {
font-family: DejaVu Sans, Segoe UI, Lucida Grande, Lucida Sans Unicode, Charis SIL, Doulos SIL, Code2000, Gentium, Gentium Alternative, TITUS Cyberbit Basic, Arial Unicode MS;
font-family /**/:inherit;
}
.Unicode {
font-family: TITUS Cyberbit Basic, Code2000, Doulos SIL, Chrysanthi Unicode, Bitstream Cyberbit, Bitstream CyberBase, Bitstream Vera, Thryomanes, Gentium, GentiumAlt, Visual Geez Unicode, Lucida Grande, Tahoma, Arial Unicode MS, Microsoft Sans Serif, Lucida Sans Unicode;
font-family /**/:inherit;
}
/* Arabic */
.AR {
font-family: Tahoma, Arial Unicode MS, Code2000, Traditional Arabic;
font-family /**/:inherit;
font-size: 125%;
}
/* Bengali */
.BN {
font-family: UniBangla, Arial Unicode MS, Code2000, Likhan, UT Bengali Dhaka, Vrinda;
font-family /**/:inherit;
font-size: 130%;
}
/* Persian */
.FA {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Kashmiri */
.KS {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Kurdish */
.KU {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Latin Extended-B */
.latinx {
font-family: TITUS Cyberbit Basic, Code2000, Microsoft Sans Serif;
font-family /**/:inherit;
}
/* Polytonic Greek */
.polytonic {
font-family: Athena, Gentium, Palatino Linotype, Arial Unicode MS, Lucida Sans Unicode, Lucida Grande, Code2000;
font-family /**/:inherit;
}
/* Russian and other Cyrillic */
.RU {
font-family: Arial Unicode MS, Gentium, Code2000, Lucida Sans Unicode;
font-family /**/:inherit;
}
/* Sindhi */
.SD {
font-family: MB Sindhi, MBSarang Sattar, MB Bhitai Sattar, MB Lateefi, Ayaz Gul, Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Thai */
.TH {
font-family: Arial Unicode MS, Code2000;
font-family /**/:inherit;
font-size: 125%;
}
/* Urdu */
.UR {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Han characters - added 30/5/2008 Moilleadóir */
.Han {
font-size: 125%;
}
/* Colours for language groups in (long) translation lists - Moilleadóir 2/6/2008 */
.Ceilteach { background-color: #e0ffe0 }
.Iodálach { background-color: #e0f9ea }
.Gearmánach { background-color: #e0f4f4 }
.BaltachSlavach { background-color: #e0efff }
.Gréagach { background-color: #e0f7ef }
.Iaráineach { background-color: #e0ffe0 }
.Indiach { background-color: #efffe0 }
.Eile { background-color: #ffffe0 }
.Seanfhocail { background-color: #e0ffe0 }
/* defaults from en.wikt to support template en-noun - really need to check if we need more of this stuff
Moilleadóir 3/6/2008 */
/* default setting for [[:en:Category:Inflection templates]] */
.infl-inline { display: inline }
.infl-table { display: none }
/* defaults for template {{tlx|comhthéacs}} Moilleadóir 7/6/2008 */
.qualifier-brac { display:none }
.qualifier-content { font-variant: small-caps; font-style:normal }
/* styles for Edittools (see [[MediaWiki:Edittools.js]]) Moilleadóir 3/7/2008 */
#editpage-newstyle {
margin-top: 10px;
border: 1px solid #aaa;
padding: 2px;
text-align: center;
font-size: 120%;
}
#editpage-newstyle a {
border: 1px outset #f0f0f0;
padding: 0 0.1em 0.1em;
background-color: #eaedf6;
/* background-image: url('//upload.wikimedia.org/wiktionary/ga/a/a9/Button_gradient.png'); */
color: black !important;
font-weight: bold;
font-size: 0.9em;
text-decoration: none !important;
}
#editpage-newstyle a:hover {
border: 1px inset #f0f0f0;
background-color: #d5d9e5;
/* background-image: url('//upload.wikimedia.org/wiktionary/ga/a/a9/Button_reverse_gradient.png'); */
}
/* more Edittools (moved from [[Mediawiki:Edittools]] Moilleadóir 4/7/2008 */
#editpage-specialchars {
margin-top: 15px;
border: 1px solid #aaa;
padding: 2px;
}
kd5gaxhx04bs9o95r5nm3vu936iv5di
392667
392665
2026-09-01T20:23:26Z
WikiBayer
13794
[[Mediawiki:Common.css]] import
392667
css
text/css
/* Infobox template style */
.infobox {
border: 1px solid #aaa;
background-color: #f9f9f9;
color: black;
margin: 0.5em 0 0.5em 1em;
padding: 0.2em;
float: right;
clear: right;
}
.infobox td,
.infobox th {
vertical-align: top;
}
.infobox caption {
font-size: larger;
margin-left: inherit;
}
.infobox.bordered {
border-collapse: collapse;
}
.infobox.bordered td,
.infobox.bordered th {
border: 1px solid #aaa;
}
.infobox.bordered .borderless td,
.infobox.bordered .borderless th {
border: 0;
}
.infobox.sisterproject {
width: 20em;
font-size: 90%;
}
@media print {
.infobox.sisterproject {
display: none;
}
}
.infobox.standard-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
}
.infobox.standard-talk.bordered td,
.infobox.standard-talk.bordered th {
border: 1px solid #c0c090;
}
/* styles for bordered infobox with merged rows */
.infobox.bordered .mergedtoprow td,
.infobox.bordered .mergedtoprow th {
border: 0;
border-top: 1px solid #aaa;
border-right: 1px solid #aaa;
}
.infobox.bordered .mergedrow td,
.infobox.bordered .mergedrow th {
border: 0;
border-right: 1px solid #aaa;
}
/* Styles for geography infoboxes, e.g. countries, country subdivisions, cities, etc. */
.infobox.geography {
text-align: left;
border-collapse: collapse;
line-height: 1.2em;
font-size: 90%;
}
.infobox.geography td,
.infobox.geography th {
border-top: solid 1px #aaa;
padding: 0.4em 0.6em 0.4em 0.6em;
}
.infobox.geography .mergedtoprow td,
.infobox.geography .mergedtoprow th {
border-top: solid 1px #aaa;
padding: 0.4em 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedrow td,
.infobox.geography .mergedrow th {
border: 0;
padding: 0 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedbottomrow td,
.infobox.geography .mergedbottomrow th {
border-top: 0;
border-bottom: solid 1px #aaa;
padding: 0 0.6em 0.4em 0.6em;
}
.infobox.geography .maptable td,
.infobox.geography .maptable th {
border: 0;
padding: 0;
}
/* Style for "notices" */
.notice {
margin: 1em;
padding: 0.2em;
}
#disambig {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.spoiler {
border-top: 2px solid #ddd;
border-bottom: 2px solid #ddd;
}
hlucl9wixif1se2h30exyprd12fugg9
392668
392667
2026-09-01T20:24:03Z
WikiBayer
13794
wrong page
392668
css
text/css
/*
'''Common CSS for all skins'''
{{interwiki-all}}
<pre><nowiki>*/
/* Main page fixes */
#interwiki-completelist {
font-weight: bold;
}
/* Don't display some stuff on the main page */
body.page-Ard-ghuillag #deleteconfirm,
body.page-Ard-ghuillag #t-cite,
body.page-Ard-ghuillag #footer-info-lastmod,
body.page-Ard-ghuillag #siteSub,
body.page-Ard-ghuillag #contentSub,
body.page-Ard-ghuillag #ca-delete {
display: none;
}
body.page-Ard-ghuillag h1.firstHeading {
display: none !important;
}
body.page-Ard-ghuillag #Ard-ghuillag {
margin-top: 0;
}
body.page-Main_Page #mp-topbanner {
clear: both;
}
/* make the list of references look smaller */
ol.references,
div.reflist,
div.refbegin {
font-size: 90%; /* Default font-size */
margin-bottom: 0.5em;
}
div.reflist ol.references {
font-size: 100%; /* Reset font-size when nested in div.reflist */
list-style-type: inherit; /* Enable custom list style types */
}
/* Highlight clicked reference in blue to help navigation */
ol.references li:target,
sup.reference:target,
span.citation:target {
background-color: #DEF;
}
/* Ensure refs in table headers and the like aren't bold or italic */
sup.reference {
font-weight: normal;
font-style: normal;
}
/* Allow hidden ref errors to be shown by user CSS */
span.brokenref {
display: none;
}
/* Styling for Citations */
cite {
font-style: normal;
word-wrap: break-word;
}
/* If there is an inline link to a full citation, the full citation will turn blue when the inline link is clicked */
cite:target {
background-color: #DEF;
}
/* Do not expand URLs within citations for printing. The urls should be included explicitly, to avoid confusion */
@media print {
#content cite a.external.text:after {
display: none;
}
}
/* For linked citation numbers and document IDs, where the number need not be shown on a screen or a handheld, but should be included in the printed version */
@media screen, handheld, projection {
cite *.printonly {
display: none;
}
}
/* default skin for navigation boxes */
table.navbox {
background-color: #f9f9f9;
border: 1px solid #aaa;
clear: both;
font-size: 90%;
margin: 1em 0em 0em;
padding: 2px;
text-align: center;
width: 100%;
}
table.navbox th {
background-color: #ccf;
padding-left: 1em;
padding-right: 1em;
}
table.navbox tr:not(:first-child) th {
background-color: #ddf;
}
@media print {
.navbox {
display: none;
}
}
/* Standard talk template style */
.Talk-Notice {
border: 1px solid #C0C090;
background-color: #F8EABA;
margin-bottom: 3px;
width: 85%;
border-spacing: 3px;
margin-left: auto;
margin-right: auto;
}
.Talk-Notice:after {
content: "The CSS for this template should be changed. See [[Wikipedia:Template Standardisation]].";
}
/* Make template background appear correctly on all browsers */
.Talk-Notice td {
background: inherit;
}
/* Persondata */
table.persondata {
border: 1px solid #aaa;
display: none;
speak: none;
}
.persondata-label {
color: #aaa;
}
/* Makes redirects appear in italics in categories and on [[Special:Allpages]] */
.redirect-in-category, .allpagesredirect {
font-style: italic;
}
/* Class for links with loudspeaker icon next to them */
/* (Used in [[Template:Audio]] and the like to make the speaker clickable) */
.audiolink a {
background: url("//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Loudspeaker.svg/11px-Loudspeaker.svg.png") center left no-repeat !important;
padding-left: 20px !important;
padding-right: 0 !important;
}
/* Icons for medialist templates [[Template:Listen]], [[Template:Multi-listen_start]], [[Template:Video]], [[Template:Multi-video_start]] */
div.listenlist {
background: url("//upload.wikimedia.org/wikipedia/commons/thumb/a/a6/Gnome-speakernotes.png/30px-Gnome-speakernotes.png");
padding-left: 40px;
}
div.videolist, div.multivideolist {
background: url("//upload.wikimedia.org/wikipedia/en/thumb/2/20/Tango-video-x-generic.png/40px-Tango-video-x-generic.png");
padding-left: 50px;
}
/* Style rules for media list templates */
div.medialist {
min-height: 50px;
margin: 1em;
background-position: top left;
background-repeat: no-repeat;
}
div.medialist ul {
list-style-type: none;
list-style-image: none;
margin: 0;
}
div.medialist ul li {
padding-bottom: 0.5em;
}
div.medialist ul li li {
font-size: 91%;
padding-bottom: 0;
}
/* Change the external link icon to an Adobe icon for all PDF files */
/* (in browsers that support these CSS selectors, like Mozilla and Opera) */
#bodyContent a[href$=".pdf"].external,
#bodyContent a[href*=".pdf?"].external,
#bodyContent a[href*=".pdf#"].external,
#bodyContent a[href$=".PDF"].external,
#bodyContent a[href*=".PDF?"].external,
#bodyContent a[href*=".PDF#"].external {
background: url(//upload.wikimedia.org/wikipedia/commons/thumb/2/23/Icons-mini-file_acrobat.gif/15px-Icons-mini-file_acrobat.gif) center right no-repeat;
padding-right: 16px;
}
/* Change the external link icon to an Adobe icon anywhere the PDFlink class */
/* is used (notably Template:PDFlink). This works in IE, unlike the above. */
span.PDFlink a {
background: url(//upload.wikimedia.org/wikipedia/commons/thumb/2/23/Icons-mini-file_acrobat.gif/15px-Icons-mini-file_acrobat.gif) center right no-repeat !important;
padding-right: 17px !important;
}
span.geolink a {
background: url(//upload.wikimedia.org/wikipedia/en/a/a7/Monobook-globe.png) center right no-repeat !important;
padding-right: 11px !important;
}
/* Content in columns with CSS instead of tables [[Template:Columns]] */
div.columns-2 div.column {
float: left;
width: 50%;
min-width: 300px;
}
div.columns-3 div.column {
float: left;
width: 33.3%;
min-width: 200px;
}
div.columns-4 div.column {
float: left;
width: 25%;
min-width: 150px;
}
div.columns-5 div.column {
float: left;
width: 20%;
min-width: 120px;
}
/*Add formatting to make sure that "external references" from [[Template:Ref]] do
not get URL expansion, not even when printed. The mechanism up to MediaWiki 1.4 was
that the HTML code contained a SPAN following the anchor A; this SPAN had the class
"urlexpansion", which was not displayed on screen, but was shown when the medium was
"print". The rules below ensure (a) that there is no extra padding to the right of
the anchor (displayed as "[<number>]"), (b) that there is no "external link arrow" for
the link, and (c) that this SPAN of class "urlexpansion" is never shown.
[[Ymmydeyr:Krinkle|Krinkle]] ([[Resooney ymmydeyr:Krinkle|talk]]) 05:18, 18 Mee Houney 2016 (UTC)
*/
.plainlinksneverexpand {
background: none ! important;
padding: 0 ! important;
}
.plainlinksneverexpand .urlexpansion {
display: none ! important;
}
/* Make sure that ext links displayed within "plainlinksneverexpand" don't get
the arrow...
*/
.plainlinksneverexpand a {
background: none !important;
padding: 0 !important;
}
/* With MediaWiki 1.5, the mechanism has changed: instead of a SPAN of class "urlexpansion"
following the anchor A, the anchor itself now has class "external autonumber" and the
expansion is inserted when printing (see the common printing style sheet at
//en.wikipedia.org/w/skins/common/commonPrint.css) using the ":after" pseudo-
element of CSS. We have to switch this off for links due to Template:Ref!
[[Ymmydeyr:Krinkle|Krinkle]] ([[Resooney ymmydeyr:Krinkle|talk]]) 05:18, 18 Mee Houney 2016 (UTC)
*/
.plainlinksneverexpand a.external.text:after {
display: none !important;
}
.plainlinksneverexpand a.external.autonumber:after {
display: none !important;
}
/* Messagebox templates */
.messagebox {
border: 1px solid #aaa;
background-color: #f9f9f9;
width: 80%;
margin: 0 auto 1em auto;
padding: .2em;
}
.messagebox.merge {
border: 1px solid #c0b8cc;
background-color: #f0e5ff;
text-align: center;
}
.messagebox.cleanup {
border: 1px solid #9f9fff;
background-color: #efefff;
text-align: center;
}
.messagebox.standard-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
}
.messagebox.nested-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
width: 100%;
margin: 2px 4px 2px 4px;
}
.messagebox.small {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
}
.messagebox.small-talk {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
background: #F8EABA;
}
/* Stylesheet for navigations bars, cf. [[de:w:Wikipedia:Navigationsleisten]] */
div.BoxenVerschmelzen,
div.NavFrame {
margin: 0px;
padding: 2px;
border: 1px solid #aaaaaa;
text-align: center;
border-collapse: collapse;
font-size: 95%;
clear:both;
}
div.BoxenVerschmelzen div.NavFrame {
border-style: none;
border-style: hidden;
}
div.NavFrame + div.NavFrame {
border-top-style: none;
border-top-style: hidden;
}
div.NavPic {
background-color: #ffffff;
margin: 0px;
padding: 2px;
float: left;
}
div.NavFrame div.NavHead {
font-weight: bold;
font-size: 100%;
background-color: #efefef;
}
div.NavFrame p {
font-size: 100%;
}
div.NavFrame div.NavContent {
font-size: 100%;
}
div.NavFrame div.NavContent p {
font-size: 100%;
}
div.NavEnd {
margin: 0px;
padding: 0px;
line-height: 1px;
clear: both;
}
/* Stylesheet for 'toggle'-Button of navigation bars, implemented in [[MediaWiki:Common.js]] */
.NavToggle {
font-size: x-small;
float:right;
}
/* Workaround für Internet Explorer 6 */
div.NavFrame, div.NavPic, .NavToggle {
position:relative;
}
/* margin above navigation bars */
div.BoxenVerschmelzen,
div.NavFrame {
margin-top: 1.5em;
}
div.BoxenVerschmelzen div.NavFrame {
margin-top: 0;
}
div.NavFrame + div.NavFrame {
margin-top: 0;
}
/* Article message box template styles */
table.ambox {
width: 80%;
margin: 0 auto;
border-collapse: collapse;
background: #f8fcff;
border: 1px solid #aaa;
border-left: 10px solid #1e90ff; /* Default "notice" blue */
}
table.ambox th, table.ambox td { /* The message body cell(s) */
padding: 0.25em 0.5em; /* 0.5em left/right */
}
table.ambox td.ambox-image { /* The left image cell */
width: 52px;
padding: 2px 0px 2px 0.5em; /* 0.5em left, 0px right */
text-align: center;
}
table.ambox td.ambox-imageright { /* The right image cell */
width: 52px;
padding: 2px 4px 2px 0px; /* 0px left, 4px right */
text-align: center;
}
table.ambox-notice {
border-left: 10px solid #1e90ff; /* DodgerBlue */
/* border-right: 10px solid #1e90ff; */ /* If you want two blue bars */
}
table.ambox-serious {
border-left: 10px solid #b22222; /* FireBrick */
}
table.ambox-content {
border-left: 10px solid #f28500; /* Tangerine */
}
table.ambox-style {
border-left: 10px solid #f4c430; /* Saffron */
}
table.ambox-merge {
border-left: 10px solid #9932cc; /* DarkOrchid */
}
table.ambox-growth {
border-left: 10px solid #228b22; /* Forest green */
}
table.ambox.ambox-mini { /* small floating box variant */
float: right;
clear: right;
margin: 0 0 0 1em;
width: 25%;
}
/* Put a checker background at the image description page only visible if the image has transparent background */
#file img {background: url("//upload.wikimedia.org/wikipedia/commons/5/5d/Checker-16x16.png") repeat;}
/* Support for Template:IPA, Template:Unicode and Template:Polytonic. The inherit declaration resets the font for all browsers except MSIE6. The empty comment must remain. Please copy any changes to [[Template:IPA fonts]] and [[Template:Unicode fonts]]. */
.IPA {
font-family: "Chrysanthi Unicode", "Doulos SIL", Gentium, GentiumAlt, Code2000, "TITUS Cyberbit Basic", "DejaVu Sans", "Bitstream Cyberbit", "Arial Unicode MS", "Lucida Sans Unicode", "Hiragino Kaku Gothic Pro", "Matrix Unicode";
font-family /**/:inherit;
}
.Unicode {
font-family: Code2000, Code2001, "Free Serif", "TITUS Cyberbit Basic", "Doulos SIL", "Chrysanthi Unicode", "Bitstream Cyberbit", "Bitstream CyberBase", Thryomanes, Gentium, GentiumAlt, "Lucida Grande", "Free Sans", "Arial Unicode MS", "Microsoft Sans Serif", "Lucida Sans Unicode";
font-family /**/:inherit;
}
.latinx {
font-family: Code2000, Code2001, "TITUS Cyberbit Basic", "Microsoft Sans Serif";
font-family /**/:inherit;
}
.polytonic {
font-family: Athena, Gentium, "Palatino Linotype", "Arial Unicode MS", "Lucida Sans Unicode", "Lucida Grande", Code2000;
font-family /**/:inherit;
}
.mufi {
font-family: Alphabetum, Cardo, LeedsUni, Junicode, "TITUS Cyberbit Basic", ALPHA-Demo;
}
/* pseudo-classes in support of [[Template:lang]]. */
:lang(he) {
font-family: "SBL Hebrew", "Ezra SIL SR", "Ezra SIL", Cardo, "Chrysanthi Unicode", "TITUS Cyberbit Basic", "Arial Unicode MS", Narkisim, "Times New Roman";
font-family /**/:inherit;
}
:lang(fa) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(ps) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(ur) {
font-family: "Nafees Nastaleeq", "Pak Nastaleeq", PDMS_Jauhar;
font-family /**/:inherit;
}
:lang(sux-Xsux) {
font-family: Akkadian;
font-family /**/:inherit;
}
:lang(ja) {
font-family: Code2000, "Arial Unicode MS", "Bitstream Cyberbit", "Bitstream CyberCJK", IPAGothic, IPAPGothic, IPAUIGothic, "Kochi Gothic", IPAMincho, IPAPMincho;
font-family /**/:inherit;
}
:lang(ko) {
font-family: "Adobe Myungjo Std M", AppleMyungjo, "Baekmuk Batang", "Baekmuk Gulim", Batang, Dotum, DotumChe, Gulim, GulimChe, HYGothic-Extra, HYMyeongJo-Extra, "New Gulim", UnBatang, UnDotum, UnYetgul, UWKMJF;
font-family /**/:inherit;
}
:lang(zh-Hans) {
font-family: "Adobe Song Std L", "AR PL ShanHeiSun Uni", "AR PL ShanHeiSun Uni MBE", "MS Hei", "MS Song", SimHei;
font-family /**/:inherit;
}
:lang(zh-Hant) {
font-family: "Adobe Ming Std L", "AR PL New Sung", "AR PL ZenKai Uni", "AR PL ZenKai Uni MBE", MingLiU, PMingLiU;
font-family /**/:inherit;
}
:lang(grc) {
font-family: Athena, Gentium, "Palatino Linotype", "Arial Unicode MS", "Lucida Sans Unicode", "Lucida Grande", Code2000;
font-family /**/:inherit;
}
#wpSave {
font-weight: bold;
}
/* class hiddenStructure is defunct. See [[Wikipedia:hiddenStructure]] */
.hiddenStructure {
display: inline ! important;
color: #f00;
background-color: #0f0;
}
/* Removes underlines from links */
.nounderlines a {
text-decoration: none;
}
/* Remove underline from IPA links */
.IPA a:link, .IPA a:visited {
text-decoration: none;
}
/* Removes useless links from printout */
@media print {
#privacy, #about, #disclaimer {display:none;}
}
#EnWpMpBook { background-image: url(//upload.wikimedia.org/wikipedia/en/7/7e/MP-open-book.png); }
#EnWpMpSearch { background: url(//upload.wikimedia.org/wikipedia/en/a/ae/MP-magnifying-glass.png) no-repeat top right; }
#EnWpMpSearchInner { float: right; width: 20em; text-align: center; }
#EnWpMpBook2 { background-image: url(//upload.wikimedia.org/wikipedia/commons/8/8e/MP-open-book2.png); }
/* Standard Navigationsleisten, aka box hiding thingy from .de. Documentation at [[Wikipedia:NavFrame]]. */
div.Boxmerge,
div.NavFrame {
margin: 0px;
padding: 4px;
border: 1px solid #aaa;
text-align: center;
border-collapse: collapse;
font-size: 95%;
}
div.Boxmerge div.NavFrame {
border-style: none;
border-style: hidden;
}
div.NavFrame + div.NavFrame {
border-top-style: none;
border-top-style: hidden;
}
div.NavPic {
background-color: #fff;
margin: 0px;
padding: 2px;
float: left;
}
div.NavFrame div.NavHead {
height: 1.6em;
font-weight: bold;
background-color: #ccf;
position:relative;
}
div.NavFrame p {
font-size: 100%;
}
div.NavFrame div.NavContent {
font-size: 100%;
}
div.NavFrame div.NavContent p {
font-size: 100%;
}
div.NavEnd {
margin: 0px;
padding: 0px;
line-height: 1px;
clear: both;
}
a.NavToggle {
position: absolute;
top: 0px;
right: 3px;
font-weight: normal;
font-size: smaller;
}
/* Coloured watchlist numbers */
.mw-plusminus-pos {
color: #006400; /* darkgreen */
}
/* .mw-plusminus-null currently at developer default */
.mw-plusminus-neg {
color: #8B0000; /* darkred */
}
.dablink {
font-style: italic;
padding-left: 2em;
}
.dablink i {
font-style: normal;
}
/* Style for horizontal UL lists */
.horizontal ul {
padding: 0;
margin: 0;
}
.horizontal li {
padding: 0 0.6em 0 0.4em;
display: inline;
border-right: 1px solid;
}
.horizontal li:last-child {
border-right: none;
padding-right: 0;
}
/* Geographical coordinates
To display coordinates using the notation in the source code, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: none }
.geo-dec { display: inline } .geo-dms { display: inline }
To display coordinates using decimal notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: inline } .geo-dms { display: none }
To display coordinates using DMS notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: none } .geo-dms { display: inline }
To display coordinates in both decimal and DMS notation, write this in your User:Username/monobook.css:
.geo-default { display: inline } .geo-nondefault { display: inline }
.geo-dec { display: inline } .geo-dms { display: inline }
.geo-multi-punct { display: inline }
See [[Template:Coor link]] for how these are used.
Note that the classes "geo", "longitude", and "latitude" are not just styles but also used by the [[Geo microformat]], so the names should not be changed.
*/
.geo-default { display: inline; }
.geo-nondefault { display: none; }
.geo-dms { display: inline; }
.geo-dec { display: inline; }
.geo-multi-punct { display: none; }
.longitude .latitude {
white-space: nowrap;
}
/* This is used for the Geo microformat, but no style is needed for now other than .geo-dec. */
.geo { }
/***** end Geo-related */
/* When <div class="nonumtoc"> is used on the table of contents, the ToC will display without numbers */
.nonumtoc .tocnumber { display:none; }
.nonumtoc #toc ul,
.nonumtoc .toc ul {
line-height: 1.5em;
list-style: none;
margin: .3em 0 0;
padding: 0;
}
.nonumtoc #toc ul ul,
.nonumtoc .toc ul ul {
margin: 0 0 0 2em;
}
/* Allow limiting of which header levels are shown in a TOC; <div class="toclimit-3">, for
instance, will limit to showing ==headings== and ===headings=== but no further (as long as
there are no =headings= on the page, which there shouldn't be according to the MoS). */
.toclimit-2 .toclevel-2 {display:none;}
.toclimit-3 .toclevel-3 {display:none;}
.toclimit-4 .toclevel-4 {display:none;}
.toclimit-5 .toclevel-5 {display:none;}
.toclimit-6 .toclevel-6 {display:none;}
.toclimit-7 .toclevel-7 {display:none;}
/* Allow transcluded pages to display in lists rather than a table. Compatible in Firefox; incompatible in IE6. */
.listify td {display:list-item}
.listify tr {display:block}
.listify table {display:block}
/* Styling for Template:Quote */
blockquote.templatequote { margin-top: 0; }
blockquote.templatequote div.templatequotecite {
line-height: 1em;
text-align: left;
padding-left: 2em;
margin-top: 0;
}
blockquote.templatequote div.templatequotecite cite {
font-size: smaller;
}
div.user-block {
padding: 5px;
border: 1px solid #A9A9A9;
background-color: #FFEFD5;
}
/* Prevents line breaks in links; see docs at Template:Nowraplinks */
.nowraplinks a {
white-space: nowrap;
}
/* Enables borders on PNG images in IE 5.5 and 6 */
.thumbborder {
border:1px solid #DDDDDD;
}
/* Support for script templates. The inherit declaration resets the font for all browsers except MSIE6. The empty comment must remain. */
.IPA {
font-family: DejaVu Sans, Segoe UI, Lucida Grande, Lucida Sans Unicode, Charis SIL, Doulos SIL, Code2000, Gentium, Gentium Alternative, TITUS Cyberbit Basic, Arial Unicode MS;
font-family /**/:inherit;
}
.Unicode {
font-family: TITUS Cyberbit Basic, Code2000, Doulos SIL, Chrysanthi Unicode, Bitstream Cyberbit, Bitstream CyberBase, Bitstream Vera, Thryomanes, Gentium, GentiumAlt, Visual Geez Unicode, Lucida Grande, Tahoma, Arial Unicode MS, Microsoft Sans Serif, Lucida Sans Unicode;
font-family /**/:inherit;
}
/* Arabic */
.AR {
font-family: Tahoma, Arial Unicode MS, Code2000, Traditional Arabic;
font-family /**/:inherit;
font-size: 125%;
}
/* Bengali */
.BN {
font-family: UniBangla, Arial Unicode MS, Code2000, Likhan, UT Bengali Dhaka, Vrinda;
font-family /**/:inherit;
font-size: 130%;
}
/* Persian */
.FA {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Kashmiri */
.KS {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Kurdish */
.KU {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Latin Extended-B */
.latinx {
font-family: TITUS Cyberbit Basic, Code2000, Microsoft Sans Serif;
font-family /**/:inherit;
}
/* Polytonic Greek */
.polytonic {
font-family: Athena, Gentium, Palatino Linotype, Arial Unicode MS, Lucida Sans Unicode, Lucida Grande, Code2000;
font-family /**/:inherit;
}
/* Russian and other Cyrillic */
.RU {
font-family: Arial Unicode MS, Gentium, Code2000, Lucida Sans Unicode;
font-family /**/:inherit;
}
/* Sindhi */
.SD {
font-family: MB Sindhi, MBSarang Sattar, MB Bhitai Sattar, MB Lateefi, Ayaz Gul, Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Thai */
.TH {
font-family: Arial Unicode MS, Code2000;
font-family /**/:inherit;
font-size: 125%;
}
/* Urdu */
.UR {
font-family: Tahoma;
font-family /**/:inherit;
font-size: 125%;
}
/* Han characters - added 30/5/2008 Moilleadóir */
.Han {
font-size: 125%;
}
/* Colours for language groups in (long) translation lists - Moilleadóir 2/6/2008 */
.Ceilteach { background-color: #e0ffe0 }
.Iodálach { background-color: #e0f9ea }
.Gearmánach { background-color: #e0f4f4 }
.BaltachSlavach { background-color: #e0efff }
.Gréagach { background-color: #e0f7ef }
.Iaráineach { background-color: #e0ffe0 }
.Indiach { background-color: #efffe0 }
.Eile { background-color: #ffffe0 }
.Seanfhocail { background-color: #e0ffe0 }
/* defaults from en.wikt to support template en-noun - really need to check if we need more of this stuff
Moilleadóir 3/6/2008 */
/* default setting for [[:en:Category:Inflection templates]] */
.infl-inline { display: inline }
.infl-table { display: none }
/* defaults for template {{tlx|comhthéacs}} Moilleadóir 7/6/2008 */
.qualifier-brac { display:none }
.qualifier-content { font-variant: small-caps; font-style:normal }
/* styles for Edittools (see [[MediaWiki:Edittools.js]]) Moilleadóir 3/7/2008 */
#editpage-newstyle {
margin-top: 10px;
border: 1px solid #aaa;
padding: 2px;
text-align: center;
font-size: 120%;
}
#editpage-newstyle a {
border: 1px outset #f0f0f0;
padding: 0 0.1em 0.1em;
background-color: #eaedf6;
/* background-image: url('//upload.wikimedia.org/wiktionary/ga/a/a9/Button_gradient.png'); */
color: black !important;
font-weight: bold;
font-size: 0.9em;
text-decoration: none !important;
}
#editpage-newstyle a:hover {
border: 1px inset #f0f0f0;
background-color: #d5d9e5;
/* background-image: url('//upload.wikimedia.org/wiktionary/ga/a/a9/Button_reverse_gradient.png'); */
}
/* more Edittools (moved from [[Mediawiki:Edittools]] Moilleadóir 4/7/2008 */
#editpage-specialchars {
margin-top: 15px;
border: 1px solid #aaa;
padding: 2px;
}
kd5gaxhx04bs9o95r5nm3vu936iv5di
Clowan:Kishtey fys
10
5838
392662
373989
2026-09-01T20:17:05Z
WikiBayer
13794
392662
wikitext
text/x-wiki
<templatestyles src="Kishtey fys/styles.css" />
{{#invoke:Infobox|infobox}}<includeonly>{{template other|{{#ifeq:{{PAGENAME}}|Infobox||{{#ifeq:{{str left|{{SUBPAGENAME}}|7}}|Infobox|[[Ronney:Clowanyn kishtey fys|{{remove first word|{{SUBPAGENAME}}}}]]}}}}|}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go in the /doc subpage, and interwikis go in Wikidata. -->
</noinclude>
87odynwonb8zskf9eu53gvwnw828eo0
Logh Titicaca
0
5934
392675
337946
2026-09-01T20:33:43Z
MacTire02
219
++
392675
wikitext
text/x-wiki
{{Kishtey fys ushtaghyn
| ennym = Logh Titicaca
| jalloo = Lake Titicaca on the Andes from Bolivia.jpg
| fo-heidyl = Reayrt er y logh veih [[Isla del Sol]]
| jalloo_bathymeadraght = Lake Titicaca map.png
| fo-heidyl_bathymeadraght = Kaart Logh Titicaca
| coordyn = {{Coord|15|49|30|S|69|19|30|W|type:waterbody_scale:2000000|display=inline,title}}
| sorçh = [[Shenn logh]], [[logh]] [[slieau]]
| yn-stroo = 27 awinyn
| ass-stroo = [[Awin Desaguadero (y Volivia)|Awin Desaguadero]]<br />[[Gaalaghey]]
| awintragh = {{cvt|58000|km2|sqmi|-2}}<ref name="ilec" />
| çheeraghyn_awintragh = [[Yn Volivia|Y Volivia]] as y [[Yn Pheroo|Pheroo]]
| lhiurid = {{cvt|190|km|mi|0}}
| lheead = {{cvt|80|km|mi|0}}
| eaghtyr = {{cvt|8372|km2|sqmi|0}}<ref name="ilec" />
| diunid = {{cvt|107|m|ft|0}}<ref name="ilec" />
| boayl_sdiuney = {{cvt|281|m|ft|0}}<ref name="ilec" />
| thummid = {{cvt|896|km3|cumi|0}}<ref name="ilec" />
| traa_freaylley = 1,343 bleeantyn<ref name="ilec" />
| coose = {{cvt|1125|km|mi|0}}<ref name="ilec" />
| yrjid = {{cvt|3812|m|ft|0}}<ref name="ilec" />
| riojit = riojit erbee<ref name="ilec" />
| ellanyn = 42+ (jeeagh er yn ''[[#Ellanyn|art]]'')
| ard-valjyn = [[Copacabana, y Volivia]]<br />[[Puno, y Pheroo]]
| imraa = <ref name="ilec" />
| meeryn = [[Wiñaymarka]]
| pushpin_label =
| pushpin_map_caption =
| pushpin_map = Bolivia#Peru#South America
| pushpin_relief = y
| pushpin_label_position= bottom
| embedded = {{Infobox mapframe |wikidata=yes |zoom=7 |coord={{WikidataCoord|display=i}}}} {{Designation list
| embed = yes
| designation1 = Ramsar
| designation1_offname = Lago Titicaca
| designation1_date = 20 Jerrey Geuree 1997
| designation1_number = 881<ref>{{Cite web |title=Lago Titicaca |website=[[Coardailys Ramsar|Ramsar]] Sites Information Service |url=https://rsis.ramsar.org/ris/881 |access-date=25 Averil 2018 |archive-date=13 Mee Houney 2020 |archive-url=https://web.archive.org/web/20201113165151/https://rsis.ramsar.org/ris/881 |url-status=live }}</ref>
| designation2 = Ramsar
| designation2_offname = Lago Titicaca
| designation2_date = 11 Mean Fouyir 1998
| designation2_number = 959<ref>{{Cite web |title=Lago Titicaca |website=[[Coardailys Ramsar|Ramsar]] Sites Information Service |url=https://rsis.ramsar.org/ris/959 |access-date=25 Averil 2018 |archive-date=13 Mee Houney 2020 |archive-url=https://web.archive.org/web/20201113165127/https://rsis.ramsar.org/ris/959 |url-status=live }}</ref>}}
}}
Ta '''Logh Titicaca''' ([[Spaainish]]: ''El lago Titicaca'', [[Quechua]]: ''Titiqaqa qucha'') ny logh ta soit er y joarey eddyr [[Yn Pheroo|y Pheroo]] as [[Yn Volivia|y Volivia]] 'syn [[Yn Americkey Yiass|Americkey Yiass]]. T'eh ny logh smoo er y vooar-rheynn rere thummid. Ta'n logh {{cvt|107|m|ft|0}} er mean-diunid.<ref name="ilec">{{cite web |url=http://www.ilec.or.jp/database/sam/dsam04.html |title=Data Summary: Lago Titicaca (Lake Titicaca) |publisher=International Lake Environment Committee Foundation – ILEC |access-date=2009-01-03 |url-status=dead |archive-url=https://web.archive.org/web/20110723165816/http://www.ilec.or.jp/database/sam/dsam04.html |archive-date=2011-07-23}}</ref>
==Imraaghyn==
{{reflist}}
==Kianglaghyn magh==
{{Commons category|Lake Titicaca|Logh Titicaca}}
* [http://www.laketiticaca.com laketiticaca.com]
* [http://www.discover-peru.org/lake-titicaca/ Sheshaght Chultooragh y Pheroo – Shennaghys Logh Titicaca]
{{Gurneil eaghtyrys}}
{{DEFAULTSORT:Titicaca}}
[[Ronney:Logh Titicaca| ]]
[[Ronney:Shenn loghyn]]
[[Ronney:Loghyn slieau]]
[[Ronney:Laaraghyn Ramsar 'sy Volivia]]
[[Ronney:Laaraghyn Ramsar 'sy Pheroo]]
[[Ronney:Loghyn 'sy Pheroo]]
[[Ronney:Loghyn 'sy Volivia]]
[[Ronney:Yn joarey eddyr y Pheroo as y Volivia]]
[[Ronney:Loghyn eddyrashoonagh ayns America Yiass]]
[[Ronney:Loghyn ayns Ard Puno]]
[[Ronney:Loghyn ayns Rheynn La Paz (y Volivia)]]
[[Ronney:Altiplano]]
5jlaafy25bgc9cjopgw8zsadabww58k
Clowan:Kishtey fys awin
10
8407
392686
375839
2026-09-01T22:17:32Z
MacTire02
219
++; ny smoo ry-yannoo
392686
wikitext
text/x-wiki
<includeonly>{{main other|{{#if:{{Has short description}} |<!--Do nothing--> |{{#invoke:Type in location|main|River|{{comma separated entries
|1= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn2|}}}|</li>|, </li>}}}}}}
|2= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn1|}}}|</li>|, </li>}}}}}}
}}}}}}}}{{Infobox
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{image|}}}}}|size={{{image_size|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{sorçh_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{sorçh_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{sorçh_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{sorçh_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{sorçh_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_coordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_coordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_coordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_coordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_coordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{depth_min|}}}{{{depth_avg|}}}{{{depth_max|}}}| }}
| label37 = <span style="font-weight:normal"> • minimum</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{depth_min|}}}
| label38 = <span style="font-weight:normal"> • average</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{depth_avg|}}}
| label39 = <span style="font-weight:normal"> • maximum</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{depth_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{discharge1_location|}}}
|min={{Infobox river/calcunit|free={{{discharge1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{discharge1_avg|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{discharge1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{discharge2_location|}}}|min={{{discharge2_min|}}}|avg={{{discharge2_avg|}}}|max={{{discharge2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{discharge3_location|}}}|min={{{discharge3_min|}}}|avg={{{discharge3_avg|}}}|max={{{discharge3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{discharge4_location|}}}|min={{{discharge4_min|}}}|avg={{{discharge4_avg|}}}|max={{{discharge4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{discharge5_location|}}}|min={{{discharge5_min|}}}|avg={{{discharge5_avg|}}}|max={{{discharge5_max|}}}}}
| header55 = Basin features
| label56 = Progression
| data56 = {{{progression|}}}
| label57 = {{nowrap|[[Drainage basin|River system]]}}
| data57 = {{{river_system|}}}
| label58 = Landmarks
| data58 = {{{basin_landmarks|}}}
| label59 = Cities
| data59 = {{{cities|}}}
| label60 = Population
| data60 = {{{basin_population|}}}
| label61 = Tributaries
| data61 = {{#if:{{{tributaries_left|}}}{{{tributaries_right|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • left</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{tributaries_left|}}}
| label63 = <span style="font-weight:normal"> • right</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{tributaries_right|}}}
| label64 = Waterbodies
| data64 = {{{waterbodies|}}}
| label65 = Waterfalls
| data65 = {{{waterfalls|}}}
| label66 = Bridges
| data66 = {{{bridges|}}}
| label67 = [[Inland port]]s
| data67 = {{{ports|}}}
| label68 = {{longitem|{{{custom_label|}}}}}
| data68 = {{{custom_data|}}}
| below = {{{extra|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using infobox river with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Infobox river]] with unknown parameter "_VALUE_" | ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Category:Pages using infobox river with mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
5mx6xqpbl3cbnlqc71tin8ucq35vony
392691
392686
2026-09-01T23:38:04Z
MacTire02
219
++
392691
wikitext
text/x-wiki
<includeonly>{{main other|{{#if:{{Has short description}} |<!--Do nothing--> |{{#invoke:Type in location|main|River|{{comma separated entries
|1= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn2|}}}|</li>|, </li>}}}}}}
|2= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn1|}}}|</li>|, </li>}}}}}}
}}}}}}}}{{Infobox
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{image|}}}}}|size={{{image_size|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{sorçh_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{sorçh_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{sorçh_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{sorçh_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{sorçh_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
sxfpzy9arzji7hri9mwg3znpx7372dy
392694
392691
2026-09-01T23:46:59Z
MacTire02
219
prowal
392694
wikitext
text/x-wiki
<includeonly>{{main other|{{#if:{{Has short description}} |<!--Do nothing--> |{{#invoke:Type in location|main|River|{{comma separated entries
|1= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn2|}}}|</li>|, </li>}}}}}}
|2= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn1|}}}|</li>|, </li>}}}}}}
}}}}}}}}{{Infobox
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{jalloo|}}}}}|size={{{mooadys_jalloo|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{sorçh_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{sorçh_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{sorçh_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{sorçh_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{sorçh_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
6ly3tcog7rcwxeuvqaq2wwr4ercxbbx
392695
392694
2026-09-01T23:52:08Z
MacTire02
219
++
392695
wikitext
text/x-wiki
<includeonly>{{main other|{{#if:{{Has short description}} |<!--Do nothing--> |{{#invoke:Type in location|main|River|{{comma separated entries
|1= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn2|}}}|</li>|, </li>}}}}}}
|2= {{Plain text|{{strip tags|{{replace|{{{sorçh_aarheynn1|}}}|</li>|, </li>}}}}}}
}}}}}}}}{{Infobox
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{jalloo|}}}}}|size={{{mooadys_jalloo|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{ennym_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{ennym_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{ennym_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{ennym_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{ennym_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
ee85d9esnhumvz3q0ctzv8r2x9t27cw
392706
392695
2026-09-02T01:04:23Z
MacTire02
219
prowal
392706
wikitext
text/x-wiki
<includeonly>{{Infobox
| bodyclass = vcard
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| aboveclass = fn org
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{jalloo|}}}}}|size={{{mooadys_jalloo|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{ennym_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{ennym_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{ennym_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{ennym_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{ennym_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
i3olssicigyhiaq9xbftj5h3vynoaq5
392707
392706
2026-09-02T01:20:28Z
MacTire02
219
prowal mooadys ny screeuyn
392707
wikitext
text/x-wiki
<includeonly>{{Infobox
| bodyclass = vcard
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| aboveclass = fn org
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122; font-size:95%;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{jalloo|}}}}}|size={{{mooadys_jalloo|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = {{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = {{{fo-heidyl_caslys-çheerey|}}}
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{ennym_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{ennym_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{ennym_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{ennym_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{ennym_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
1z3qya8tf9nz658whqra6rhimpvi236
392716
392707
2026-09-02T01:30:34Z
MacTire02
219
++
392716
wikitext
text/x-wiki
<includeonly>{{Infobox
| bodyclass = vcard
| child = {{{embed|}}}
| abovestyle = background-color: #CEDEFF;color: #202122;
| aboveclass = fn org
| above = {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}{{#if:{{{ennym_elley|}}}|<br /><div class="nickname" style="display:inline;font-size:78%">{{{ennym_elley|}}}</div>}}
| autoheaders= y
| headerstyle= background-color: #CEDEFF;color: #202122; font-size:95%;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{#invoke:WikidataIB |getValue|rank=best|P18 |name=image |qid={{{qid|}}} |suppressfields={{{suppressfields|}}} |fetchwikidata={{if empty|{{{fetchwikidata|}}}|ALL}} |onlysourced=no |noicon=yes |maxvals=1 |{{{jalloo|}}}}}|size={{{mooadys_jalloo|}}}|sizedefault=250px|upright={{if empty|{{{image_upright|}}}|1}}|suppressplaceholder=yes}}
| caption = <div style="padding-top:2pt; font-size:85%;">{{#if:{{{jalloo|}}}|{{{fo-heidyl_jalloo|}}}|{{if empty|{{{fo-heidyl_jalloo|}}}|{{#invoke:WikidataIB|getValue|P18|qual=P2096|qualsonly=y|fwd=ALL}}}}}}</div>
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=250px}}
| caption2 = <div style="padding-top:2pt; font-size:85%;">{{{fo-heidyl_caslys-çheerey|}}}</div>
| image3 = {{#if:{{both|{{{caslys-çheerey_freeney|}}}|{{{co-ordnaidyn_inver|}}}{{#property:P625}}}}|{{#invoke:Location map|infobox_pushpin_map
| default_width = 250
| coordinates = {{{co-ordnaidyn_inver|}}}
| pushpin_relief = 1
}}}}
| image4 = {{#invoke:Infobox mapframe
|autoWithCaption
|onByDefault={{#if:{{{caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
|mapframe-frame-width=250
|mapframe-stroke-color=#0000ff
|mapframe-marker=water
|mapframe-type=river
|mapframe-length_km={{{lhiurid_km|}}}|mapframe-length_mi={{{lhiurid_mi|}}}
|mapframe-area_km2={{{mooadys_awintragh_km2|}}}|mapframe-area_mi2={{{mooadys_awintragh_mi2|}}}
}}
| label1 = Bun-ocklaght
| data1 = {{{bun-ocklaght|}}}
| class2 = nickname
| label2 = Far-ennym
| data2 = {{{far-ennym|}}}
| class3 = nickname
| label3 = Ennym dooghyssagh
| data3 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| header5 = Soiaghey
| label6 = {{if empty|{{{sorçh_aarheynn1|}}}|Çheer}}
| rowstyle6 = {{Infobox river/row-style}}
| data6 = {{{ennym_aarheynn1|}}}
| label7 = {{if empty|{{{sorçh_aarheynn2|}}}|Steat}}
| rowstyle7 = {{Infobox river/row-style}}
| data7 = {{{ennym_aarheynn2|}}}
| label8 = {{if empty|{{{sorçh_aarheynn3|}}}|Ard}}
| rowstyle8 = {{Infobox river/row-style}}
| data8 = {{{ennym_aarheynn3|}}}
| label9 = {{if empty|{{{sorçh_aarheynn4|}}}|Slyst}}
| rowstyle9 = {{Infobox river/row-style}}
| data9 = {{{ennym_aarheynn4|}}}
| label10 = {{if empty|{{{sorçh_aarheynn5|}}}|Baljaght}}
| rowstyle10 = {{Infobox river/row-style}}
| data10 = {{{ennym_aarheynn5|}}}
| header15 = Troghyn fishigagh
| rowstyle16 = display:none;
| data16 = {{Infobox river/source|source={{{moir1|}}}|loc={{{soiaghey_moir1|}}}|elev={{{yrjid_moir1|}}}|coord={{{co-ordnaidyn_moir1|}}}|len={{{lhiurid_moir1|}}}|coord_ref={{{imraa_co-ordnaidyn_moir1|}}}}}
| rowstyle17 = display:none;
| data17 = {{Infobox river/source|2h voir|source={{{moir2|}}}|loc={{{soiaghey_moir2|}}}|elev={{{yrjid_moir2|}}}|coord={{{co-ordnaidyn_moir2|}}}|len={{{lhiurid_moir2|}}}|coord_ref={{{imraa_co-ordnaidyn_moir2|}}}}}
| rowstyle18 = display:none;
| data18 = {{Infobox river/source|3oo moir|source={{{moir3|}}}|loc={{{soiaghey_moir3|}}}|elev={{{yrjid_moir3|}}}|coord={{{co-ordnaidyn_moir3|}}}|len={{{lhiurid_moir3|}}}|coord_ref={{{imraa_co-ordnaidyn_moir3|}}}}}
| rowstyle19 = display:none;
| data19 = {{Infobox river/source|4oo moir|source={{{moir4|}}}|loc={{{soiaghey_moir4|}}}|elev={{{yrjid_moir4|}}}|coord={{{co-ordnaidyn_moir4|}}}|len={{{lhiurid_moir4|}}}|coord_ref={{{imraa_co-ordnaidyn_moir4|}}}}}
| rowstyle20 = display:none;
| data20 = {{Infobox river/source|5oo moir|source={{{source5|}}}|loc={{{soiaghey_moir5|}}}|elev={{{yrjid_moir5|}}}|coord={{{co-ordnaidyn_moir5|}}}|len={{{lhiurid_moir5|}}}|coord_ref={{{imraa_co-ordnaidyn_moir5|}}}}}
| rowstyle21 = display:none;
| data21 = {{Infobox river/source|Co-strooan mayrey|source={{{co-strooan_maayrey|}}}|loc={{{soiaghey_co-strooan_mayrey|}}}|elev={{{yrjid_co-strooan_mayrey|}}}|coord={{{co-ordnaidyn_co-strooan_mayrey|}}}|coord_ref={{{imraa_co-strooan_mayrey|}}}}}
| label22 = [[Inver]]
| data22 = {{#if:{{{inver|}}}|{{{inver}}}|{{#if:{{{soiaghey_inver|}}}{{{co-ordnaidyn_inver|}}}{{{yrjid_inver|}}}| }}}}
| label23 = <div style="display:inline;font-weight:normal"> • soiaghey</div>
| rowstyle23 = {{Infobox river/row-style}}
| data23 = {{{soiaghey_inver|}}}
| label24 = <div style="display:inline;font-weight:normal"> • co-ordnaidyn</div>
| rowstyle24 = {{Infobox river/row-style}}
| data24 = {{#if:{{{co-ordnaidyn_inver|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn_inver}}}|type:river}}{{{imraa_co-ordnaidyn_inver|}}}}}
| label25 = <div style="display:inline;font-weight:normal"> • yrjid</div>
| rowstyle25 = {{Infobox river/row-style}}
| data25 = {{Infobox river/calcunit|free={{{yrjid_inver|}}}|met_unit=m|imp_unit=ft}}
| label30 = Lhiurid
| rowstyle30 = {{Infobox river/row-style}}
| data30 = {{Infobox river/calcunit|free={{{lhiurid|}}}|met={{{lhiurid_km|}}}|met_unit=km|imp={{{lhiurid_mi|}}}|imp_unit=mi}}<!--
-->{{#if:{{{lhiurid_km|}}}{{{lhiurid_mi|}}}|{{{imraa_lhiurid|}}}}}
| label31 = {{longitem|Mooadys yn awintragh}}
| data31 = {{Infobox river/calcunit|free={{{mooadys_awintragh|}}}|met={{{mooadys_awintragh_km2|}}}|met_unit=km2|imp={{{mooadys_awintragh_mi2|}}}|imp_unit=mi2}}<!--
-->{{#if:{{{mooadys_awintragh_km2|}}}{{{mooadys_awintragh_mi2|}}}|{{{imraa_mooadys_awintragh|}}}}}
| label32 = Lheead
| rowstyle32 = {{Infobox river/row-style}}
| data32 = {{#if:{{{lheead_min|}}}{{{lheead_mean|}}}{{{lheead_max|}}}| }}
| label33 = <span style="font-weight:normal"> • s'keyley</span>
| rowstyle33 = {{Infobox river/row-style}}
| data33 = {{Infobox river/calcunit|free={{{lheead_min|}}}|met_unit=m|imp_unit=yd}}
| label34 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle34 = {{Infobox river/row-style}}
| data34 = {{Infobox river/calcunit|free={{{lheead_mean|}}}|met_unit=m|imp_unit=yd}}
| label35 = <span style="font-weight:normal"> • s'lhea</span>
| rowstyle35 = {{Infobox river/row-style}}
| data35 = {{Infobox river/calcunit|free={{{lheead_max|}}}|met_unit=m|imp_unit=yd}}
| label36 = Diunid
| data36 = {{#if:{{{diunid_min|}}}{{{diunid_mean|}}}{{{diunid_max|}}}| }}
| label37 = <span style="font-weight:normal"> • s'thanney</span>
| rowstyle37 = {{Infobox river/row-style}}
| data37 = {{{diunid_min|}}}
| label38 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle38 = {{Infobox river/row-style}}
| data38 = {{{diunid_avg|}}}
| label39 = <span style="font-weight:normal"> • s'diuney</span>
| rowstyle39 = {{Infobox river/row-style}}
| data39 = {{{diunid_max|}}}
| rowstyle50 = display:none;
| data50 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh1|}}}
|min={{Infobox river/calcunit|free={{{stroo-magh1_min|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|avg={{Infobox river/calcunit|free={{{stroo-magh1_mean|}}}|met_unit=m3/s|imp_unit=cuft/s}}
|max={{Infobox river/calcunit|free={{{stroo-magh1_max|}}}|met_unit=m3/s|imp_unit=cuft/s}}
}}
| rowstyle51 = display:none;
| data51 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh2|}}}|min={{{stroo-magh2_min|}}}|avg={{{stroo-magh2_mean|}}}|max={{{stroo-magh2_max|}}}}}
| rowstyle52 = display:none;
| data52 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh3|}}}|min={{{stroo-magh3_min|}}}|avg={{{stroo-magh3_mean|}}}|max={{{stroo-magh3_max|}}}}}
| rowstyle53 = display:none;
| data53 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh4|}}}|min={{{stroo-magh4_min|}}}|avg={{{stroo-magh4_mean|}}}|max={{{stroo-magh4_max|}}}}}
| rowstyle54 = display:none;
| data54 = {{Infobox river/discharge|loc={{{soiaghey_stroo-magh5|}}}|min={{{stroo-magh5_min|}}}|avg={{{stroo-magh5_avg|}}}|max={{{stroo-magh5_max|}}}}}
| header55 = Troghyn yn awintragh
| label56 = Immeeaght
| data56 = {{{immeeaght|}}}
| label57 = {{nowrap|[[Awintragh teaymee|Corys awiney]]}}
| data57 = {{{corys_awiney|}}}
| label58 = Cowraghyn thallooin
| data58 = {{{cowraghyn_thallooin|}}}
| label59 = Ard-valjyn
| data59 = {{{ard-valjyn|}}}
| label60 = Earroo yn phobble
| data60 = {{{earroo_yn_phobble|}}}
| label61 = Crouw-awinyn
| data61 = {{#if:{{{crouw-awinyn_toshtal|}}}{{{crouw-awinyn_jesh|}}}| }}
| rowstyle61 = {{Infobox river/row-style}}
| label62 = <span style="font-weight:normal"> • toshtal</span>
| rowstyle62 = {{Infobox river/row-style}}
| data62 = {{{crouw-awinyn_toshtal|}}}
| label63 = <span style="font-weight:normal"> • jesh</span>
| rowstyle63 = {{Infobox river/row-style}}
| data63 = {{{crouw-awinyn_jesh|}}}
| label64 = Ushtaghyn
| data64 = {{{ushtaghyn|}}}
| label65 = Easyn
| data65 = {{{easyn|}}}
| label66 = Droghadyn
| data66 = {{{droghadyn|}}}
| label67 = [[Purt antraieagh|Puirt antraieagh]]
| data67 = {{{puirt|}}}
| label68 = {{longitem|{{{lipaid_brash|}}}}}
| data68 = {{{fysseree_vrash|}}}
| below = {{{brash|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys awin lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys awin]] lesh y pharameadar "_VALUE_" gyn enney| ignoreblank = y | mapframe_args = y | pushpin_map_args = y | basin_landmarks | basin_population | basin_size | basin_size_km2 | basin_size_mi2 | basin_size_ref | bridges | cities | custom_data | custom_label | depth_avg | depth_max | depth_min | discharge1_avg | discharge1_location | discharge1_max | discharge1_min | discharge2_avg | discharge2_location | discharge2_max | discharge2_min | discharge3_avg | discharge3_location | discharge3_max | discharge3_min | discharge4_avg | discharge4_location | discharge4_max | discharge4_min | discharge5_avg | discharge5_location | discharge5_max | discharge5_min | embed | etymology | extra | fetchwikidata | image | image_alt | image_caption | image_size | image_upright | length | length_km | length_mi | length_ref | map | map_alt | map_caption | map_size | mouth | mouth_coord_ref | mouth_coordinates | mouth_elevation | mouth_location | name | native_name | nickname | other_name | ports | progression | qid | river_system | source_confluence | source_confluence_coord_ref | source_confluence_coordinates | source_confluence_elevation | source_confluence_location | source1 | source1_coord_ref | source1_coordinates | source1_elevation | source1_length | source1_location | source2 | source2_coord_ref | source2_coordinates | source2_elevation | source2_length | source2_location | source3 | source3_coord_ref | source3_coordinates | source3_elevation | source3_length | source3_location | source4 | source4_coord_ref | source4_coordinates | source4_elevation | source4_length | source4_location | source5 | source5_coord_ref | source5_coordinates | source5_elevation | source5_length | source5_location | subdivision_name1 | subdivision_name2 | subdivision_name3 | subdivision_name4 | subdivision_name5 | subdivision_type1 | subdivision_type2 | subdivision_type3 | subdivision_type4 | subdivision_type5 | suppressfields | tributaries_left | tributaries_right | waterbodies | waterfalls | width_avg | width_max | width_min }}{{main other|{{#if:{{{map|}}}{{{pushpin_map|}}}||[[Ronney:Duillagyn gymmydey kishtey fys awin lesh mapframe]]}}}}<noinclude>
{{Documentation}}
</noinclude>
rcp51dd7kmsx5foplc1x8owuxjdnigi
Clowan:Kishtey fys boayl Nerin
10
13802
392671
150808
2026-09-01T20:28:12Z
WikiBayer
13794
392671
wikitext
text/x-wiki
<templatestyles src="Kishtey fys/styles.css" />
{| class="infobox geography vcard" style="width:22em; text-align:left; font-size: 88%; line-height: 1.5em"
|colspan=2 class= style="text-align: center; background:#E0E0E0; " |<big class="fn org">'''{{{ennym}}}'''</big>{{#if: {{{baarle| }}}| <br>''{{lang|en|{{{baarle}}} }}'' }}{{#if: {{{gaeilge| }}}| <br>''{{lang|ga|{{{gaeilge}}} }}'' }}{{#if: {{{yernish| }}}| <br>''{{lang|ga|{{{yernish}}} }}'' }}{{#if: {{{baarle albinagh| }}}| <br>''{{lang|sco|{{{baarle albinagh}}} }}'' }}
|-
{{#if: {{{jalloo armys<includeonly>|</includeonly>}}} |
! colspan=2 style="background: white; text-align: center; font-size: 85%;" {{!}} [[Coadan:{{{jalloo armys}}}|100px|Armys {{{ennym gienneydagh<includeonly>|</includeonly>}}}]] }}
|-
{{#if: {{{jalloo brattagh<includeonly>|</includeonly>}}} |
! colspan=2 style="background: white; text-align: center; font-size: 85%;" {{!}} [[Coadan:{{{jalloo brattagh}}}|175px|border|Brattagh {{{ennym gienneydagh<includeonly>|</includeonly>}}}]] }}
|- class="note"
{{#if: {{{jarroo-raa<includeonly>|</includeonly>}}} |
! colspan="2" style="text-align: center; font-size: 85%;" {{!}} [[Jarroo-raa]]: {{{jarroo-raa}}} }}
|- class="note"
{{#if: {{{jalloo_neughleashagh<includeonly>|</includeonly>}}} |
! colspan=2 style="background: white; text-align: center; font-size: 85%;" {{!}} [[Coadan:{{{jalloo_neughleashagh}}}|240px]]{{#if: {{{fo-heidyl_jalloo_neughleashagh<includeonly>|</includeonly>}}}|<br />{{{fo-heidyl_jalloo_neughleashagh<includeonly>|</includeonly>}}}}}}}
|-
{{#if: {{{coordyn pin|}}} {{{jalloo caslys<includeonly>|</includeonly>}}} | {{!}}colspan="2" style="background: #E0E0E0; text-align: center;"{{!}} '''Soiaghey'''|}}
|-
|colspan=2 style="background: white;" align="center" |
{| style="text-align: center; margin: 0 auto; background: none;"
|-
| style="border: 0; vertical-align: middle;" | {{#if: {{{coordyn pin|}}}|<div style="position: relative;"><div style="position:absolute;top:5;left:5;"><div style="position: absolute; display: block; {{{coordyn pin}}}; width:8px; height:8px; padding:0">[[Coadan:Locationinireland.gif|Soiaghey {{{ennym gienneydagh}}}]]</div></div>}}{{#if: {{{jalloo caslys<includeonly>|</includeonly>}}}|[[Coadan:{{{jalloo caslys}}}|center|{{#if: {{{mooadyscaslys<includeonly>|</includeonly>}}}|{{{mooadyscaslys}}}}}|{{{ennym}}} er caslys-çheerey]]|}}
|}
|-style="background: white; text-align: center; font-size: 85%;"
{{#if: {{{coord<includeonly>|</includeonly>}}} |
{{!}} style="text-align: center;" colspan=2 {{!}}
<div align="center">[[Corys co-ordnaidyn çheer-oaylleeagh|Co-ordnaidyn]]:<br><includeonly>{{{coord}}}</includeonly>}}
|-style="background: white; text-align: center; font-size: 85%;"
{{#if: {{{ingagh yernagh<includeonly>|</includeonly>}}} |
! style="text-align: center; border-top: solid 1px #ccd2d9;" colspan=2 {{!}} [[Corys ingagh ogheragh Nerin|Ingagh ogheragh Nerin]]<br><includeonly>{{iem4ibx|</includeonly>{{{ingagh yernagh}}}<includeonly>}}</includeonly>}}
|-
| colspan="2" style="background: #E0E0E0; text-align: center;"|'''Staydraa'''
|-
{{#if: {{{queiggey<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Queiggaghyn Nerin|Queiggey]]:
{{!}} {{{queiggey}}} }}
|- class="adr"
{{#if: {{{coontae<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Coondaeghyn Nerin|Coontae]]:
{{!}} <span class="region">{{{coontae}}}</span> }}
|-
{{#if: {{{slyst NH<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Gurneilys ynnydagh ayns Nerin Hwoaie|Slyst]]:
{{!}} {{{slyst NH}}} }}
|- class="note"
{{#if: {{{co-heiyderysdail<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Co-heiyderyssyn parlamaidagh ayns Pobblagh Nerin|Dáil Éireann]]:
{{!}} {{{co-heiyderysdail}}} }}
|- class="note"
{{#if: {{{co-heiyderys RU<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Rolley co-heiyderyssyn parlamaidagh 'sy Reeriaght Unnaneysit|Parlamaid yn RU]]:
{{!}} {{{co-heiyderys RU}}} }}
|-
{{#if: {{{co-heiyderys UO<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Parlamaid ny h-Oarpey]]:
{{!}} {{{co-heiyderys UO}}} }}
|-
{{#if: {{{balley coontae<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Balley coontae]]:
{{!}} {{{balley coontae}}} }}
|-
{{#if: {{{coad<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Earroo-chlaareyn carbyd Nerin|Coad]]:
{{!}} {{{coad}}} }}
|-
{{#if: {{{coadçhellvane<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Coad çhellvane|Coad jeeley]]:
{{!}} {{{coadçhellvane}}} }}
|-
{{#if: {{{balleypostagh<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Balley postagh]]:
{{!}} {{{balleypostagh}}} }}
|-
{{#if: {{{coadpostagh<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Coadyn postagh 'sy Reeriaght Unnaneysit|Coad(yn) postagh]]:
{{!}} {{{coadpostagh}}} }}
|-
{{#if: {{{coadpostaghIE<includeonly>|</includeonly>}}} |
! style="background: #EDEDED;" {{!}} [[Coadyn postagh ayns Pobblaght Nerin|Slyst(yn) postagh]]:
{{!}} {{{coadpostaghIE}}} }}
|-
{{#if: {{{eaghtyr km2|{{{eaghtyr<includeonly>|</includeonly>}}}}}}|
! style="background: #EDEDED;" {{!}} [[Eaghtyr]]:
{{!}} {{#if:{{{eaghtyr km2|}}}|{{convert|{{{eaghtyr km2}}}|km2|miker|abbr=on}}|{{{eaghtyr}}}}} {{{notey eaghtyr|}}} }}
|-
{{#if: {{{yrjid m|{{{yrjid<includeonly>|</includeonly>}}}}}}{{{yrjid min m|}}}{{{yrjid max m|}}} |
! style="background: #EDEDED;" {{!}} [[Yrjid]]:
{{!}} {{#if:{{{yrjid m|}}}|{{convert|{{{yrjid m}}}|m|tr|abbr=on}}|{{{yrjid<includeonly>|</includeonly>}}}}}{{{notey yrjid|}}}
{{!}}-
{{#if: {{{yrjid min m|}}} |
! style="background: #EDEDED; border-top: 0px; line-height: 1.0em" {{!}} - S'inshley:
{{!}} style="border-top: 0px; line-height: 1.0em" {{!}} {{yrjid|{{{yrjid min m}}}|m|tr|abbr=on}}
{{!}}-
}}
{{#if: {{{yrjid max m|}}} |
! style="background: #EDEDED; border-top: 0px; line-height: 1.0em" {{!}} - S'yrjey:
{{!}} style="border-top: 0px; line-height: 1.0em" {{!}} {{convert|{{{yrjid max m}}}|m|tr|abbr=on}}
{{!}}-
}} }}
{{#if: {{{pobbyl<includeonly>|</includeonly>}}}{{{binn|}}}{{{pob baljagh|}}}{{{pob çheerey|}}}|
! style="background: #EDEDED;" {{!}} {{nowrap|[[Earroo yn phobble]]}}{{#if:{{{bl coontey-pobble|}}}| ({{{bl coontey-pobble}}})}}{{
<!--If pop. & environs defined, show Proper heading-->
#if: {{{pobbyl<includeonly>|</includeonly>}}}
| {{
#if: {{{binn<includeonly>|</includeonly>}}}
| <br/> - [[Jeoraghtyn caayragh|Cair]]:
}}
}}{{
<!--If environs defined, show Environs heading-->
#if: {{{binn<includeonly>|</includeonly>}}}
| <br/> - Binn:
}}{{
<!--If town pop & rural pop defined, show Town heading-->
#if: {{{pob baljagh<includeonly>|</includeonly>}}}
| {{
#if: {{{pob çheerey<includeonly>|</includeonly>}}}
| <br/> - Balley:
}}
}}{{
<!--If rural pop defined, show Environs heading (was Rural)-->
#if: {{{pob çheerey<includeonly>|</includeonly>}}}
| <br/> - Binn:
}}
{{!}} {{
<!--If pop. defined, show it-->
#if: {{{pobbyl<includeonly>|</includeonly>}}}
| {{
<!--if pop. & environs defined, placed <br/> to show pop. next to Proper heading-->
#if: {{{binn<includeonly>|</includeonly>}}}
| <br/>
}} {{formatnum:{{{pobbyl}}}}} {{{notey pobbyl|}}}
}}{{
<!--If environs defined, show it next-->
#if: {{{binn<includeonly>|</includeonly>}}}
| <br/> {{formatnum:{{{binn}}}}}{{{notey binn|}}}
}}{{
<!--If town pop & rural pop defined, show town pop next to Town heading-->
#if: {{{pob baljagh<includeonly>|</includeonly>}}}
| {{
#if: {{{pob çheerey<includeonly>|</includeonly>}}}
| <br/>
}} {{formatnum:{{{pob baljagh}}}}}{{#if:{{{pobbyl|}}}||{{{notey pobbyl|}}} }}{{{notey balley|}}}
}}{{
<!--If "rural pop" defined, show it next to Environs heading (was Rural)-->
#if: {{{pob çheerey<includeonly>|</includeonly>}}}
| <br/> {{formatnum:{{{pob çheerey}}}}}{{{notey çheerey|}}}
}}
}}
|-
{{#if: {{{ynnyd-eggey<includeonly>|</includeonly>}}} |
{{!}} colspan="2" style="text-align: center; border-top: solid 1px #ccd2d9;" {{!}} '''Ynnyd-eggey:''' [http://{{{ynnyd-eggey}}} {{{ynnyd-eggey}}}] }}
|-
{{#if: {{{noteyn<includeonly>|</includeonly>}}} |
{{!}} colspan="2" style="text-align: center; border-top: solid 1px #ccd2d9; font-size:90%;" {{!}} {{{noteyn}}} }}
|}{{ns0|{{#if:{{{eaghtyr|}}}{{{yrjid|}}}{{#ifeq:{{{1|CHECK}}}|CHECK||CHECK}}{{#ifexist:media:{{{jalloo armys}}}||{{{jalloo armys|}}}}}{{#ifexist:media:{{{jalloo brattagh}}}||{{{jalloo brattagh|}}}}}{{#ifexist:media:{{{jalloo caslys}}}||{{{jalloo caslys|}}}}}{{#ifexist:media:{{{jalloo neughleashagh}}}||{{{jalloo neughleashagh|}}}}}{{#ifexist:media:{{{jalloo_neughleashagh}}}||{{{jalloo_neughleashagh|}}}}}{{#iferror:{{#expr: {{#if:{{{coord hwoaie|}}}|{{{coord hwoaie}}}|0}}+{{#if:{{{coord heear|}}}|{{{coord heear}}}|0}}+{{#if:{{{pobbyl|}}}|{{{pobbyl}}}|0}}+{{#if:{{{pob baljagh|}}}|{{{pob baljagh}}}|0}}+{{#if:{{{pob çheerey|}}}|{{{pob çheerey}}}|0}}+{{#if:{{{binn|}}}|{{{binn}}}|0}}+{{#if:{{{yrjid min m|}}}|{{{yrjid min m}}}|0}}+{{#if:{{{yrjid max m|}}}|{{{yrjid max m}}}|0}}+{{#if:{{{yrjid m|}}}|{{{yrjid m}}}|0}}+{{#if:{{{eaghtyr km2|}}}|{{{eaghtyr km2}}}|0}} }}|true|}}|<!--[[Category:Infobox Place Ireland using deprecated parameters]]-->}}}}<noinclude>
<!-- Categories and interlanguage links go on /doc page, not here -->
{{docamadys}}
</noinclude>
g31va57zryu8ea2mnosdsgdgabfpnq8
Shooylaghan Loch
0
15478
392661
286550
2026-09-01T17:01:29Z
MacTire02
219
clowan noa
392661
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Shooylaghan Logh
|ennym_elley = {{lang|en|''Loch Promenade''}} {{small|([[Baarle]])}}
|jalloo = Loch Promenade - geograph.org.uk - 1237690.jpg
|fo-heidyl = Jeeaghyn da'n twoaie er Shooylaghan Loch
|soiaghey = [[Doolish]], Mannin
|lhiurid_mi = 0.56
|imraa_lhiurid=
|kione_a = [[Kerrin Oonlee]]
|troa_a = hwoaie
|kione_b = [[Shooylaghan Harris]]
|troa_b = yiass
|date_jerrey_yn_troggal = 1878
|co-ordnaidyn ={{Coord|54.15224|N|04.47819|W|display=title,inline}}
}}
She fer jeh ny straidyn mooarey as y shooylaghan smoo scanshoil ayns [[Doolish]], [[Mannin]], eh '''Shooylaghan Loch''' ({{lang-en|Loch Promenade}}). Ta ennym y Chiannoort [[H. B. Loch|Loch]] currit er y çhooylaghan. Va'n shooylaghan as y traid troggit as foshlit 'sy vlein 1878 er thalloo lhiassit veih'n vooir. T'eh roie veih jerrey [[Kerrin Oonlee|Cherrin Oonlee]] rish y vaie feie 2,500 slatyn, as t'eh creaghney er y ghoal lesh [[Raad ny Killey, Doolish|Raad ny Killey]] as y [[Shooylaghan Harris]]. Ta ny h-ard-straidyn [[Straid Duke, Doolish|Straid Duke]] as [[Straid Broogh y Traie]] kianglt rish. Va leagh y raad cosnit ec ny troggeyderyn lesh cur er creck ny thallooyn çheu-chooyl jeh'n voalley marrey. Hie straneyn dy hieyn Victorianagh er nyn droggal rish y raad, as nish t'ad coontit myr nane jeh ard-chowraghyn Ghoolish.
[[Ronney:Straidyn ayns Doolish]]
jep9qq34n19i47iaxwpqxhuevrxvkav
392666
392661
2026-09-01T20:22:47Z
MacTire02
219
+GE, +kishtey fys noa
392666
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Shooylaghan Logh
|ennym_elley = {{lang|en|''Loch Promenade''}} {{small|([[Baarle]])}}
|jalloo = Loch Promenade - geograph.org.uk - 1237690.jpg
|fo-heidyl = Jeeaghyn da'n twoaie er Shooylaghan Loch
|soiaghey = [[Doolish]], Mannin
|lhiurid_mi = 0.56
|imraa_lhiurid=
|kione_a = [[Shooylaghan Harris]]
|troa_a = hwoaie
|kione_b = [[Kerrin Peveril]]
|troa_b = yiass
|date_jerrey_yn_troggal = 1878
|co-ordnaidyn ={{Coord|54.15224|N|04.47819|W|display=title,inline}}
}}
She fer jeh ny straidyn mooarey as y shooylaghan smoo scanshoil ayns [[Doolish]], [[Mannin]], eh '''Shooylaghan Loch''' ({{lang-en|Loch Promenade}}). Ta ennym y Chiannoort [[H. B. Loch|Loch]] currit er y çhooylaghan. Va'n shooylaghan as y traid troggit as foshlit 'sy vlein 1878 er thalloo lhiassit veih'n vooir. T'eh roie veih jerrey [[Kerrin Oonlee|Cherrin Oonlee]] rish y vaie feie 2,500 slatyn, as t'eh creaghney er y ghoal lesh [[Raad ny Killey, Doolish|Raad ny Killey]] as y [[Shooylaghan Harris]]. Ta ny h-ard-straidyn [[Straid Duke, Doolish|Straid Duke]] as [[Straid Broogh y Traie]] kianglt rish. Va leagh y raad cosnit ec ny troggeyderyn lesh cur er creck ny thallooyn çheu-chooyl jeh'n voalley marrey. Hie straneyn dy hieyn Victorianagh er nyn droggal rish y raad, as nish t'ad coontit myr nane jeh ard-chowraghyn Ghoolish.
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Doolish]]
jkxzodm9kinqdde1w1pflxsu3y17otg
392684
392666
2026-09-01T21:38:24Z
MacTire02
219
++
392684
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Shooylaghan Logh
|ennym_elley = {{lang|en|''Loch Promenade''}} {{small|([[Baarle]])}}
|jalloo = Loch Promenade - geograph.org.uk - 1237690.jpg
|fo-heidyl = Jeeaghyn da'n twoaie er Shooylaghan Loch
|soiaghey = [[Doolish]], Mannin
|lhiurid_mi = 0.56
|imraa_lhiurid=
|ayrn_jeh = {{ERAA|A11|GBM|art=y}}
|kione_a = [[Shooylaghan Harris]]
|troa_a = hwoaie
|kione_b = [[Kerrin Peveril]]
|troa_b = yiass
|date_jerrey_yn_troggal = 1878
|co-ordnaidyn ={{Coord|54.15224|N|04.47819|W|display=title,inline}}
}}
She fer jeh ny straidyn mooarey as y shooylaghan smoo scanshoil ayns [[Doolish]], [[Mannin]], eh '''Shooylaghan Loch''' ({{lang-en|Loch Promenade}}). Ta ennym y Chiannoort [[H. B. Loch|Loch]] currit er y çhooylaghan. Va'n shooylaghan as y traid troggit as foshlit 'sy vlein 1878 er thalloo lhiassit veih'n vooir. T'eh roie veih jerrey [[Kerrin Oonlee|Cherrin Oonlee]] rish y vaie feie 2,500 slatyn, as t'eh creaghney er y ghoal lesh [[Raad ny Killey, Doolish|Raad ny Killey]] as y [[Shooylaghan Harris]]. Ta ny h-ard-straidyn [[Straid Duke, Doolish|Straid Duke]] as [[Straid Broogh y Traie]] kianglt rish. Va leagh y raad cosnit ec ny troggeyderyn lesh cur er creck ny thallooyn çheu-chooyl jeh'n voalley marrey. Hie straneyn dy hieyn Victorianagh er nyn droggal rish y raad, as nish t'ad coontit myr nane jeh ard-chowraghyn Ghoolish.
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Doolish]]
37txrq30u6wvgrsv3hx2j4wije8q17w
Straid Korablestroiteley
0
15727
392679
292588
2026-09-01T21:11:29Z
MacTire02
219
++
392679
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Straid Korablestroiteley
|ennym_elley = {{lang|ru|Улица Кораблестроителей}} {{small|([[Rooshish]])}}
|jalloo = Ulica Korablestroiteley.JPG
|fo-heidyl =
|soiaghey = [[Caayr Pheddyr]], y Roosh
|lhiurid_km = 2.8
|imraa_lhiurid=
|kione_a = [[Straid Nalichnaya, Caayr Pheddyr|Straid Nalichnaya]]
|kione_b = [[Kerrin Pribaltiyskaya, Caayr Pheddyr|Kerrin Pribaltiyskaya]] {{small|([[Bollagh Shkiperskiy]])}}
|date_jerrey_yn_troggal =
|co-ordnaidyn = {{Coord|59.94917|N|30.21639|E|display=title,inline}}
|fo-halloo = [[Coadan:Spb_metro_line3.svg|30px]] [[Primorskaya (stashoon fo-halloo)|Primorskaya]]
}}
She straid ayns [[Caayr Pheddyr]] heear, [[Yn Roosh|y Roosh]], ee '''Straid Korablestroiteley''' ({{lang-ru|У́лица Кораблестрои́телей}}, ''Ulitsa Korablestroiteley''; Rooshish son "Straid ny Troggeyderyn Lhongey"). Ta'n straid ny soie er [[Ellan Vasilyevsky]] heear as t'eh er credjal dy vel ee ny straid s'lhea 'sy chaayr. Hooar y straid yn ennym eck 'sy vlein 1972. T'ee roie tessen yn awin [[Smolenka (awin)|Smolenka]] liorish [[Droghad Korablestroiteley]]. Ta'n chooid smoo jeh ny thieyn er y traid nyn dhieyn cummaltagh preevaadjagh, agh ta thie lhiabbagh jeh [[Ollooscoil Steat Chaayr Pheddyr]] as yn thie oast "[[Pribaltiyskaya (thie oast)|Pribaltiyskaya]]" nyn soie er y traid.
{{gurneil eaghtyrys}}
{{DEFAULTSORT:Korablestroiteley, Straid}}
{{bun}}
[[Ronney:Straidyn ayns Caayr Pheddyr]]
{{coord|59|56|57|N|30|12|59|E|type:landmark|display=title}}
j676cjfnlqk2b9nnjoqeuren9l8snhe
Raad Lhean
0
18823
392677
341215
2026-09-01T20:50:45Z
MacTire02
219
++
392677
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Raad Lhean
|ennym_elley = {{lang|en|''Broadway''}} {{small|([[Baarle]])}}
|jalloo = Broadway, Douglas, Isle of Man - geograph.org.uk - 227545.jpg
|fo-heidyl = Jeeaghyn sheese y Raad Lhean dys y vooir
|soiaghey = [[Doolish]], Mannin
|lhiurid_mi = 0.6
|ayrn_jeh = [[Coadan:UK road A22.svg|40px]] [[A22 (Mannin)|A22]]
|imraa_lhiurid=
|kione_a = [[Bayr Glion Shirragh]], [[Ardane Stanlagh]], [[Raad Varriaght]]
|kione_b = [[Shooylaghan Harris]], [[Shooylaghan Meanagh]]
|date_jerrey_yn_troggal =
|co-ordnaidyn ={{Coord|54.15765|N|04.47812|W|display=title,inline}}
}}
She straid ghiare ayns çheshvean [[Doolish|Ghoolish]], [[Mannin]], eh '''Raad Lhean''' ({{lang-en|Broadway}}). T'eh goaill toshiaghey er y ghoal rish [[Bayr Glion Shirragh]], [[Raad Victoria]] as [[Ardane Stanlagh]] as t'eh roie shiar yiass gys y choose raad t'eh kiangley er goal rish [[Shooylaghan Harris]] as y [[Shooylaghan Meanagh|Çhooylaghan Meanagh]]. Ta [[Plaase ny Marrey]] ny hoie ec jerrey yn raad as ta [[Garaghyn Cooinaghtyn T. E. Brown]] soit ec y toshiaght.
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Doolish]]
penpfw92tq6iut8tqnsll9fdyn8skkk
392685
392677
2026-09-01T21:39:03Z
MacTire02
219
+clowan
392685
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Raad Lhean
|ennym_elley = {{lang|en|''Broadway''}} {{small|([[Baarle]])}}
|jalloo = Broadway, Douglas, Isle of Man - geograph.org.uk - 227545.jpg
|fo-heidyl = Jeeaghyn sheese y Raad Lhean dys y vooir
|soiaghey = [[Doolish]], Mannin
|lhiurid_mi = 0.6
|ayrn_jeh = {{ERAA|A22|GBM|art=y}}
|imraa_lhiurid=
|kione_a = [[Bayr Glion Shirragh]], [[Ardane Stanlagh]], [[Raad Varriaght]]
|kione_b = [[Shooylaghan Harris]], [[Shooylaghan Meanagh]]
|date_jerrey_yn_troggal =
|co-ordnaidyn ={{Coord|54.15765|N|04.47812|W|display=title,inline}}
}}
She straid ghiare ayns çheshvean [[Doolish|Ghoolish]], [[Mannin]], eh '''Raad Lhean''' ({{lang-en|Broadway}}). T'eh goaill toshiaghey er y ghoal rish [[Bayr Glion Shirragh]], [[Raad Victoria]] as [[Ardane Stanlagh]] as t'eh roie shiar yiass gys y choose raad t'eh kiangley er goal rish [[Shooylaghan Harris]] as y [[Shooylaghan Meanagh|Çhooylaghan Meanagh]]. Ta [[Plaase ny Marrey]] ny hoie ec jerrey yn raad as ta [[Garaghyn Cooinaghtyn T. E. Brown]] soit ec y toshiaght.
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Doolish]]
gw5z0qag2d05r7xlashadb96t78shk3
Bayr ny h-Albey, Purt ny h-Inshey
0
21094
392651
392609
2026-09-01T14:16:56Z
MacTire02
219
++
392651
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Bayr ny h-Albey
|soiaghey = [[Purt ny h-Inshey]]
|lhiurid_ft = 770
|kione_a = [[Raad Derby, Purt ny-Inshey|Raad Derby]]
|troa_a = hwoaie
|kione_b = [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] / [[A1 (raad ayns Mannin)|A1]]
|troa_b = yiass
|co-ordnaidyn={{coord|54.2211|N|4.6900|W|display=title,inline}}
}}
She bayr ayns [[Purt ny h-Inshey]], [[Mannin]], eh '''Bayr ny h-Albey''' ny '''Bayr ny Halbey''' ({{lang-en|Albany Road}}). T'eh kianglaghey ny raaidyn [[A1 (Mannin)|A1]] as [[A20 (Mannin)|A20]] rish y cheilley as t'eh croo ayrn jeh'n voggyl raaidey 'sy lieh hiar jeh'n valley.<ref name=NLS>{{cite web |url=https://maps.nls.uk/geo/find/marker/#zoom=17&lat=54.2215&lon=-4.6890&f=1&z=1&marker=54.2203,-4.6910&from=1450&to=2000 |title=Map Finder |website=Lioarlann Ashoonagh ny h-Albey |access-date=30 Luanistyn 2026}}</ref>
== Soiaghey ==
Ta Bayr ny h-Albey roie dy faggyssagh veih'n jiass dys y twoaie eddyr [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] (yn A1) as [[Bayr Derby, Purt ny h-Inshey|Bayr Derby]] (yn A20).<ref name=NLS/> Ta'n raad roie trooid ard cummaltagh er y chooid smoo. She raad giare t'eh nagh vel agh {{cvt|770|ft|m}} er lhiurid.<ref>{{cite web |url=https://www.openstreetmap.org/way/25987495 |title=Way: Albany Road (25987495) |website=OpenStreetMap |publisher=OpenStreetMap Foundation |access-date=30 Luanistyn 2026 }}</ref> Ta [[Ynnyd Lheihys Phurt ny h-Inshey]] soit er Close ny h-Albey, beggan mooie veih Bayr ny h-Albey.<ref>{{cite web |url=https://www.gov.im/categories/health-and-wellbeing/doctors/peel-medical-centre/ |title=Ynnyd Lheihys Phurt ny h-Inshey (Peel Medical Centre) |lang=en |publisher=Reiltys Vannin |access-date=29 Luanistyn 2026}}</ref>
== Shennaghys ==
Va Bayr ny h-Albey er ny hroggal eddyr 1890 as 1894 car mooadaghey Phurt ny h-Inshey 'sy 19oo eash yeianagh. Cha nel y raad ry-akin er y chaslys-çheerey 25 oarleeyn lesh yn ''Ordnance Survey'' lurg y towshan-çheerey v'er ny yannoo eddyr 1868 as 1869, agh va'n ennym Baarlagh {{lang|en|''Albany-road''}} ymmydit 'sy vlein 1894 ayns ''Brown's Directory'' tra ren eh listal Edward Anderson, seyr as troggeyder, as eh cummal er y raad.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peelc.htm |title=Peel |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026|lang=en}}</ref>
Car y feedoo eash va lhiasaghey undinyssagh as thieys coadit currit rish cowrey cummaltagh y raad. Va Thie Cooinaghtyn Corrin foshlit er Bayr ny h-Albey 'sy vlein 1956 as v'eh obbrit myr thie kiarail cummaltagh da sleih aasit derrey v'eh er ny ghooney ayns Jerrey Souree 2021.<ref>{{cite news |title=Old people's home to shut |work=Isle of Man Today |date=23 Averil 2021 |url=https://www.iomtoday.co.im/news/old-peoples-home-to-shut-240648 |access-date=30 Luanistyn 2026}}</ref> 'Sy vlein 1969 va Bing Thieys Phurt ny h-Inshey as Slyst Heear bunnit dy lhiasaghey thieys coadit ec Westlands, beggan mooie veih Bayr ny h-Albey; haink jerrey rish troggal y chied cheim as ny chied vungalowyn 'sy vlein 1970, as va keimyn s'odjey jeant ayns 1974 as 1981.<ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026 |lang=en}}</ref>
Va'n raad er ny aahroggal 'sy 20oo eash yeianagh. Ta Tashtlann Ashoonagh Vannin recortyssey planyn aahroggal 'sy vlein 1987, treealtyssyn son towshan-çheerey aa-yannoo rea ec goal Vayr ny h-Albey, Imman y Venrein, as Raad Ghoolish 'sy vlein 1991, as cassan-breck treealit 'sy vlein 1997.<ref>{{cite web |title=Plan: Albany Road Reconstruction Cross Sections Plan in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Boaldyn 1987 |url=https://archives.gov.im/Record.aspx?AddBasket=S5%2FA41%2F1485&id=S5%2FA41%2F1485&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Douglas Road, Queens Drive, Albany Road, Peel. Survey plan |publisher=Manx National Archives |date=Mayrnt 1991 |url=https://archives.gov.im/Record.aspx?id=S5%2FA41%2F1727&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Proposed Zebra Crossing at Albany Road in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Luanistyn 1997 |url=https://archives.gov.im/record/catalog/S5/A41/4262 |access-date=30 Luanistyn 2026}}</ref>
'Sy chied eash as feed, haghyr lhiasaghey mooie veih Bayr ny h-Albey, goaill stiagh mooadaghey Ynnyd Lheihys Phurt ny h-Inshey as aalhiasaghey co-hroggalys thieys coadit Westlands, Cooyrt Vac Guilley Chreest as Cooyrt Valkyrs.<ref>{{cite web |title=Alterations, erection of extension to Medical Centre, and demolition of Nos. 1–4 Westlands in order to provide additional parking provision |publisher=Isle of Man Planning Portal |date=22 Jerrey Souree 2019 |url=https://planningportal.im/a/29750-german-peel-gp-surgery-demolition-extension |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Public Session |publisher=Barrantee Skeerey Marooney |date=19 Toshiaght Arree 2025 |url=https://marown.im/filemanager/250219a%20minutes.pdf |access-date=30 Luanistyn 2026}}</ref>
== Sleih kianglt rish y raad ==
* [[Edmund Goodwin|Edmund Evans Greaves Goodwin]] – scoillar as çhyndaader ny Gaelgey as ughtar y lioar ''[[First Lessons in Manx]]''<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/gazateer/gyards/mlang.htm |title=Manx Language Epitaphs |website=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* [[George Goodwin]] – screeudeyr shennaghys as peinteyr thie, ren cummal er Bayr ny h-Albey as va listit ayns ''Brown's Directory'' 'sy vlein 1894.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peel.htm |title=Peel Alphabetical List |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* Annie Cowley as Jennie Cowley – olteynyn y [[Yn Çheshaght Ghailckagh|Çheshaght Ghailckagh]], ren cummal er Bayr ny h-Albey as va listit ayn 'sy vlein 1922.<ref>{{cite web |url=https://isle-of-man.com/manxnotebook/mquart/mq28039.htm |title=List of Members Yn Cheshaght Ghailckagh, 1922 |work=Manx Quarterly |issue=28 |date=1922 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
==Imraaghyn==
{{reflist}}
{{Straidyn ayns Purt ny h-Inshey}}
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Purt ny h-Inshey]]
5khv51mbfqmyf6qr1hutu4tcnim4nvn
392655
392651
2026-09-01T14:32:35Z
MacTire02
219
++
392655
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Bayr ny h-Albey<br/>{{nobold|{{lang|en|''Albany Road''}} {{small|([[Baarle]])}}}}
|soiaghey = [[Purt ny h-Inshey]], Mannin
|lhiurid_ft = 770
|imraa_lhiurid= <ref name=OSM/>
|kione_a = [[Raad Derby, Purt ny-Inshey|Raad Derby]]
|troa_a = hwoaie
|kione_b = [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] / [[A1 (raad ayns Mannin)|A1]]
|troa_b = yiass
|co-ordnaidyn ={{coord|54.2211|N|4.6900|W|display=title,inline}}
}}
She bayr ayns [[Purt ny h-Inshey]], [[Mannin]], eh '''Bayr ny h-Albey''' ny '''Bayr ny Halbey''' ({{lang-en|Albany Road}}). T'eh kianglaghey ny raaidyn [[A1 (Mannin)|A1]] as [[A20 (Mannin)|A20]] rish y cheilley as t'eh croo ayrn jeh'n voggyl raaidey 'sy lieh hiar jeh'n valley.<ref name=NLS>{{cite web |url=https://maps.nls.uk/geo/find/marker/#zoom=17&lat=54.2215&lon=-4.6890&f=1&z=1&marker=54.2203,-4.6910&from=1450&to=2000 |title=Map Finder |website=Lioarlann Ashoonagh ny h-Albey |access-date=30 Luanistyn 2026}}</ref>
== Soiaghey ==
Ta Bayr ny h-Albey roie dy faggyssagh veih'n jiass dys y twoaie eddyr [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] (yn A1) as [[Bayr Derby, Purt ny h-Inshey|Bayr Derby]] (yn A20).<ref name=NLS/> Ta'n raad roie trooid ard cummaltagh er y chooid smoo. She raad giare t'eh nagh vel agh {{cvt|770|ft|m}} er lhiurid.<ref name=OSM>{{cite web |url=https://www.openstreetmap.org/way/25987495 |title=Way: Albany Road (25987495) |website=OpenStreetMap |publisher=OpenStreetMap Foundation |access-date=30 Luanistyn 2026 }}</ref> Ta [[Ynnyd Lheihys Phurt ny h-Inshey]] soit er Close ny h-Albey, beggan mooie veih Bayr ny h-Albey.<ref>{{cite web |url=https://www.gov.im/categories/health-and-wellbeing/doctors/peel-medical-centre/ |title=Ynnyd Lheihys Phurt ny h-Inshey (Peel Medical Centre) |lang=en |publisher=Reiltys Vannin |access-date=29 Luanistyn 2026}}</ref>
== Shennaghys ==
Va Bayr ny h-Albey er ny hroggal eddyr 1890 as 1894 car mooadaghey Phurt ny h-Inshey 'sy 19oo eash yeianagh. Cha nel y raad ry-akin er y chaslys-çheerey 25 oarleeyn lesh yn ''Ordnance Survey'' lurg y towshan-çheerey v'er ny yannoo eddyr 1868 as 1869, agh va'n ennym Baarlagh {{lang|en|''Albany-road''}} ymmydit 'sy vlein 1894 ayns ''Brown's Directory'' tra ren eh listal Edward Anderson, seyr as troggeyder, as eh cummal er y raad.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peelc.htm |title=Peel |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026|lang=en}}</ref>
Car y feedoo eash va lhiasaghey undinyssagh as thieys coadit currit rish cowrey cummaltagh y raad. Va Thie Cooinaghtyn Corrin foshlit er Bayr ny h-Albey 'sy vlein 1956 as v'eh obbrit myr thie kiarail cummaltagh da sleih aasit derrey v'eh er ny ghooney ayns Jerrey Souree 2021.<ref>{{cite news |title=Old people's home to shut |work=Isle of Man Today |date=23 Averil 2021 |url=https://www.iomtoday.co.im/news/old-peoples-home-to-shut-240648 |access-date=30 Luanistyn 2026}}</ref> 'Sy vlein 1969 va Bing Thieys Phurt ny h-Inshey as Slyst Heear bunnit dy lhiasaghey thieys coadit ec Westlands, beggan mooie veih Bayr ny h-Albey; haink jerrey rish troggal y chied cheim as ny chied vungalowyn 'sy vlein 1970, as va keimyn s'odjey jeant ayns 1974 as 1981.<ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026 |lang=en}}</ref>
Va'n raad er ny aahroggal 'sy 20oo eash yeianagh. Ta Tashtlann Ashoonagh Vannin recortyssey planyn aahroggal 'sy vlein 1987, treealtyssyn son towshan-çheerey aa-yannoo rea ec goal Vayr ny h-Albey, Imman y Venrein, as Raad Ghoolish 'sy vlein 1991, as cassan-breck treealit 'sy vlein 1997.<ref>{{cite web |title=Plan: Albany Road Reconstruction Cross Sections Plan in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Boaldyn 1987 |url=https://archives.gov.im/Record.aspx?AddBasket=S5%2FA41%2F1485&id=S5%2FA41%2F1485&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Douglas Road, Queens Drive, Albany Road, Peel. Survey plan |publisher=Manx National Archives |date=Mayrnt 1991 |url=https://archives.gov.im/Record.aspx?id=S5%2FA41%2F1727&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Proposed Zebra Crossing at Albany Road in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Luanistyn 1997 |url=https://archives.gov.im/record/catalog/S5/A41/4262 |access-date=30 Luanistyn 2026}}</ref>
'Sy chied eash as feed, haghyr lhiasaghey mooie veih Bayr ny h-Albey, goaill stiagh mooadaghey Ynnyd Lheihys Phurt ny h-Inshey as aalhiasaghey co-hroggalys thieys coadit Westlands, Cooyrt Vac Guilley Chreest as Cooyrt Valkyrs.<ref>{{cite web |title=Alterations, erection of extension to Medical Centre, and demolition of Nos. 1–4 Westlands in order to provide additional parking provision |publisher=Isle of Man Planning Portal |date=22 Jerrey Souree 2019 |url=https://planningportal.im/a/29750-german-peel-gp-surgery-demolition-extension |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Public Session |publisher=Barrantee Skeerey Marooney |date=19 Toshiaght Arree 2025 |url=https://marown.im/filemanager/250219a%20minutes.pdf |access-date=30 Luanistyn 2026}}</ref>
== Sleih kianglt rish y raad ==
* [[Edmund Goodwin|Edmund Evans Greaves Goodwin]] – scoillar as çhyndaader ny Gaelgey as ughtar y lioar ''[[First Lessons in Manx]]''<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/gazateer/gyards/mlang.htm |title=Manx Language Epitaphs |website=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* [[George Goodwin]] – screeudeyr shennaghys as peinteyr thie, ren cummal er Bayr ny h-Albey as va listit ayns ''Brown's Directory'' 'sy vlein 1894.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peel.htm |title=Peel Alphabetical List |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* Annie Cowley as Jennie Cowley – olteynyn y [[Yn Çheshaght Ghailckagh|Çheshaght Ghailckagh]], ren cummal er Bayr ny h-Albey as va listit ayn 'sy vlein 1922.<ref>{{cite web |url=https://isle-of-man.com/manxnotebook/mquart/mq28039.htm |title=List of Members Yn Cheshaght Ghailckagh, 1922 |work=Manx Quarterly |issue=28 |date=1922 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
==Imraaghyn==
{{reflist}}
{{Straidyn ayns Purt ny h-Inshey}}
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Purt ny h-Inshey]]
92z4o969keciaob9rjr5s5lgnumypu0
392659
392655
2026-09-01T16:54:36Z
MacTire02
219
++
392659
wikitext
text/x-wiki
{{Kishtey fys straid
|ennym = Bayr ny h-Albey
|ennym_elley = {{lang|en|''Albany Road''}} {{small|([[Baarle]])}}
|soiaghey = [[Purt ny h-Inshey]], Mannin
|lhiurid_ft = 770
|imraa_lhiurid= <ref name=OSM/>
|kione_a = [[Raad Derby, Purt ny-Inshey|Raad Derby]]
|troa_a = hwoaie
|kione_b = [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] / [[A1 (raad ayns Mannin)|A1]]
|troa_b = yiass
|co-ordnaidyn ={{coord|54.2211|N|4.6900|W|display=title,inline}}
}}
She bayr ayns [[Purt ny h-Inshey]], [[Mannin]], eh '''Bayr ny h-Albey''' ny '''Bayr ny Halbey''' ({{lang-en|Albany Road}}). T'eh kianglaghey ny raaidyn [[A1 (Mannin)|A1]] as [[A20 (Mannin)|A20]] rish y cheilley as t'eh croo ayrn jeh'n voggyl raaidey 'sy lieh hiar jeh'n valley.<ref name=NLS>{{cite web |url=https://maps.nls.uk/geo/find/marker/#zoom=17&lat=54.2215&lon=-4.6890&f=1&z=1&marker=54.2203,-4.6910&from=1450&to=2000 |title=Map Finder |website=Lioarlann Ashoonagh ny h-Albey |access-date=30 Luanistyn 2026}}</ref>
== Soiaghey ==
Ta Bayr ny h-Albey roie dy faggyssagh veih'n jiass dys y twoaie eddyr [[Bayr Tinvaal, Purt ny h-Inshey|Bayr Tinvaal]] (yn A1) as [[Bayr Derby, Purt ny h-Inshey|Bayr Derby]] (yn A20).<ref name=NLS/> Ta'n raad roie trooid ard cummaltagh er y chooid smoo. She raad giare t'eh nagh vel agh {{cvt|770|ft|m}} er lhiurid.<ref name=OSM>{{cite web |url=https://www.openstreetmap.org/way/25987495 |title=Way: Albany Road (25987495) |website=OpenStreetMap |publisher=OpenStreetMap Foundation |access-date=30 Luanistyn 2026 }}</ref> Ta [[Ynnyd Lheihys Phurt ny h-Inshey]] soit er Close ny h-Albey, beggan mooie veih Bayr ny h-Albey.<ref>{{cite web |url=https://www.gov.im/categories/health-and-wellbeing/doctors/peel-medical-centre/ |title=Ynnyd Lheihys Phurt ny h-Inshey (Peel Medical Centre) |lang=en |publisher=Reiltys Vannin |access-date=29 Luanistyn 2026}}</ref>
== Shennaghys ==
Va Bayr ny h-Albey er ny hroggal eddyr 1890 as 1894 car mooadaghey Phurt ny h-Inshey 'sy 19oo eash yeianagh. Cha nel y raad ry-akin er y chaslys-çheerey 25 oarleeyn lesh yn ''Ordnance Survey'' lurg y towshan-çheerey v'er ny yannoo eddyr 1868 as 1869, agh va'n ennym Baarlagh {{lang|en|''Albany-road''}} ymmydit 'sy vlein 1894 ayns ''Brown's Directory'' tra ren eh listal Edward Anderson, seyr as troggeyder, as eh cummal er y raad.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peelc.htm |title=Peel |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026|lang=en}}</ref>
Car y feedoo eash va lhiasaghey undinyssagh as thieys coadit currit rish cowrey cummaltagh y raad. Va Thie Cooinaghtyn Corrin foshlit er Bayr ny h-Albey 'sy vlein 1956 as v'eh obbrit myr thie kiarail cummaltagh da sleih aasit derrey v'eh er ny ghooney ayns Jerrey Souree 2021.<ref>{{cite news |title=Old people's home to shut |work=Isle of Man Today |date=23 Averil 2021 |url=https://www.iomtoday.co.im/news/old-peoples-home-to-shut-240648 |access-date=30 Luanistyn 2026}}</ref> 'Sy vlein 1969 va Bing Thieys Phurt ny h-Inshey as Slyst Heear bunnit dy lhiasaghey thieys coadit ec Westlands, beggan mooie veih Bayr ny h-Albey; haink jerrey rish troggal y chied cheim as ny chied vungalowyn 'sy vlein 1970, as va keimyn s'odjey jeant ayns 1974 as 1981.<ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026 |lang=en}}</ref>
Va'n raad er ny aahroggal 'sy 20oo eash yeianagh. Ta Tashtlann Ashoonagh Vannin recortyssey planyn aahroggal 'sy vlein 1987, treealtyssyn son towshan-çheerey aa-yannoo rea ec goal Vayr ny h-Albey, Imman y Venrein, as Raad Ghoolish 'sy vlein 1991, as cassan-breck treealit 'sy vlein 1997.<ref>{{cite web |title=Plan: Albany Road Reconstruction Cross Sections Plan in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Boaldyn 1987 |url=https://archives.gov.im/Record.aspx?AddBasket=S5%2FA41%2F1485&id=S5%2FA41%2F1485&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Douglas Road, Queens Drive, Albany Road, Peel. Survey plan |publisher=Manx National Archives |date=Mayrnt 1991 |url=https://archives.gov.im/Record.aspx?id=S5%2FA41%2F1727&src=CalmView.Catalog |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Plan: Proposed Zebra Crossing at Albany Road in Peel |publisher=Tashtlann Ashoonagh Vannin |date=Luanistyn 1997 |url=https://archives.gov.im/record/catalog/S5/A41/4262 |access-date=30 Luanistyn 2026}}</ref>
'Sy chied eash as feed, haghyr lhiasaghey mooie veih Bayr ny h-Albey, goaill stiagh mooadaghey Ynnyd Lheihys Phurt ny h-Inshey as aalhiasaghey co-hroggalys thieys coadit Westlands, Cooyrt Vac Guilley Chreest as Cooyrt Valkyrs.<ref>{{cite web |title=Alterations, erection of extension to Medical Centre, and demolition of Nos. 1–4 Westlands in order to provide additional parking provision |publisher=Isle of Man Planning Portal |date=22 Jerrey Souree 2019 |url=https://planningportal.im/a/29750-german-peel-gp-surgery-demolition-extension |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Hospice Isle of Man Open Gardens Brochure |page=15 |date=2021 |url=https://fliphtml5.com/hzcy/lcpd/Hospice_Isle_of_Man_Open_Gardens_Brochure/15/ |access-date=30 Luanistyn 2026}}</ref><ref>{{cite web |title=Public Session |publisher=Barrantee Skeerey Marooney |date=19 Toshiaght Arree 2025 |url=https://marown.im/filemanager/250219a%20minutes.pdf |access-date=30 Luanistyn 2026}}</ref>
== Sleih kianglt rish y raad ==
* [[Edmund Goodwin|Edmund Evans Greaves Goodwin]] – scoillar as çhyndaader ny Gaelgey as ughtar y lioar ''[[First Lessons in Manx]]''<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/gazateer/gyards/mlang.htm |title=Manx Language Epitaphs |website=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* [[George Goodwin]] – screeudeyr shennaghys as peinteyr thie, ren cummal er Bayr ny h-Albey as va listit ayns ''Brown's Directory'' 'sy vlein 1894.<ref>{{cite web |url=https://www.isle-of-man.com/manxnotebook/fulltext/bd1894/peel.htm |title=Peel Alphabetical List |work=Brown's Directory |date=1894 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
* Annie Cowley as Jennie Cowley – olteynyn y [[Yn Çheshaght Ghailckagh|Çheshaght Ghailckagh]], ren cummal er Bayr ny h-Albey as va listit ayn 'sy vlein 1922.<ref>{{cite web |url=https://isle-of-man.com/manxnotebook/mquart/mq28039.htm |title=List of Members Yn Cheshaght Ghailckagh, 1922 |work=Manx Quarterly |issue=28 |date=1922 |publisher=Manx Notebook |access-date=30 Luanistyn 2026}}</ref>
==Imraaghyn==
{{reflist}}
{{Straidyn ayns Purt ny h-Inshey}}
{{gurneil eaghtyrys}}
[[Ronney:Straidyn ayns Purt ny h-Inshey]]
24dr3moozi0ea6ug3v1f2v4noararzn
Yn Amason
0
22049
392690
368677
2026-09-01T23:13:06Z
MacTire02
219
392690
wikitext
text/x-wiki
{{Kishtey fys awin
| ennym = Yn Amason
| jalloo = Rio_Amazonas_-_Parintins.jpg
| mooadys_jalloo =
| fo-heidyl = Yn Amason
| moir = [[Río Apurimac]], [[Mullagh Mismi]], [[Ard Arequipa]], [[Yn Pheroo|y Pheroo]]
| inver = [[Yn Keayn Sheealtagh|Y Keayn Sheealtagh]], [[Yn Vrasseel|y Vrasseel]]
| çheeraghyn_awintragh= [[Yn Pheroo|Y Pheroo]]<br />[[Ecuador]]<br />[[Yn Cholombey|Y Cholombey]]<br />[[Yn Volivia|Y Volivia]]<br />[[Yn Veneswaaley|Y Veneswaaley]]<br />[[Geeaaney]]<br />[[Yn Vrasseel|Y Vrasseel]]
| lhiurid = 6,992 km
| dreeym_ushtey = 6,743,,000 km<sup>2</sup>
| lhiggey_magh = 209,103 m<sup>3</sup>/s
}}
'''Yn Amason''' ({{lang-es|Río Amazonas}}, {{lang-pt|Rio Amazonas}}) ayns [[America Yiass]], she yn awin smoo 'sy theihll rere lhiggey magh ushtey as t'ee 'sy chied ynnyd marish [[Yn Neel|y Neel]] myr yn awin s'liurey 'sy theihll.
[[Coadan:Amazonrivermap.svg|left|thumb|Yn Amason as yn awin-tragh eck]]
{{gurneil eaghtyrys}}
{{DEFAULTSORT:Amason, Yn}}
{{bun}}
[[Ronney:Yn Amason| ]]
[[Ronney:Awintragh yn Amason]]
[[Ronney:Keyll liaghee yn Amason]]
[[Ronney:Awinyn ayns America Yiass]]
[[Ronney:Awinyn eddyrashoonagh ayns America Yiass]]
[[Ronney:Awinyn 'sy Cholombey]]
[[Ronney:Awinyn 'sy Pheroo]]
[[Ronney:Awinyn ayns Amapá]]
[[Ronney:Awinyn ayns Amazonas (steat Brasseelagh)]]
[[Ronney:Awinyn ayns Ard Loreto]]
[[Ronney:Awinyn ayns Pará]]
[[Ronney:Awinyn 'sy Vrasseel]]
tjno8gftszs5as4k3rheo7a2u2022s8
392699
392690
2026-09-02T00:41:11Z
MacTire02
219
++
392699
wikitext
text/x-wiki
{{Kishtey fys awin
| ennym = Yn Amason
| jalloo = Rio_Amazonas_-_Parintins.jpg
| mooadys_jalloo =
| fo-heidyl = Yn Amason
| moir = [[Río Apurimac]], [[Mullagh Mismi]], [[Ard Arequipa]], [[Yn Pheroo|y Pheroo]]
| inver = [[Yn Keayn Sheealtagh|Y Keayn Sheealtagh]], [[Yn Vrasseel|y Vrasseel]]
| çheeraghyn_awintragh= [[Yn Pheroo|Y Pheroo]]<br />[[Ecuador]]<br />[[Yn Cholombey|Y Cholombey]]<br />[[Yn Volivia|Y Volivia]]<br />[[Yn Veneswaaley|Y Veneswaaley]]<br />[[Geeaaney]]<br />[[Yn Vrasseel|Y Vrasseel]]
| lhiurid = 6,992 km
| dreeym_ushtey = 6,743,,000 km<sup>2</sup>
| lhiggey_magh = 209,103 m<sup>3</sup>/s
}}
{{Infobox river
| ennym = Yn Amason
| ennym_dooghyssagh = {{native name|pt|Amazonas}}
| ennym_elley = {{lang|pt|Rio Amazonas}}, {{lang|es|Río Amazonas}}
| jalloo = Amazon River ESA387332.jpg
| mooadys_jalloo = 250
| fo-heidyl_jalloo = Satellite image of the [[Amazon Delta]]
| caslys-çheerey = Amazonrivermap.svg
| mooadys_caslys-çheerey = 250
| fo-heidyl_caslys-çheerey = Amazon River and [[Amazon basin|its drainage basin]]
| pushpin_map =
| mooadys_caslys-çheerey_freeney = 250
| pushpin_caption =
| sorçh_aarheynn1 = Çheer
| ennym_aarheynn1 = [[Yn Pheroo|Y Pheroo]], [[Yn Cholombey|y Cholombey]], [[Yn Vrasseel|y Vrasseel]]
| ard-valjyn = [[Iquitos]] (y Pheroo); [[Leticia, Amazonas|Leticia]] (y Cholombey); [[Tabatinga]] (y Vrasseel); [[Tefé]] (y Vrasseel); [[Itacoatiara, Amazonas|Itacoatiara]] (y Vrasseel) [[Parintins]] (y Vrasseel); [[Óbidos, Pará|Óbidos]] (y Vrasseel); [[Santarém, Pará|Santarém]] (y Vrasseel); [[Almeirim, Pará|Almeirim]] (y Vrasseel); [[Macapá]] (y Vrasseel);<br />[[Manaus]] (y Vrasseel)
| lhiurid ={{cvt|6,575|km|mi|abbr=on}}{{refn|name=length|group=n|Co-strooan ny h-awinyn Marañón as Ucayali dys yn inver {{cvt|3,750|km|mi|abbr=on}}.<ref name="The Amazon River">{{cite web|url=https://en.aguasamazonicas.org/basins/amazon-main-stem/the-main-stem|title=The Amazon River|date=28 Boaldyn 2014 }}</ref><ref name="Aguas Amazónicas–El río Amazonas">{{cite web|url=https://aguasamazonicas.org/cuencas/canal-principal-del-amazonas/rio-amazonas|title=Aguas Amazónicaa-El río Amazonas |date=7 Jerrey Souree 2022 }}</ref><ref name="Rio Amazonas">{{cite web|title=Rio Amazonas|url=https://waterwaymap.org/river/Rio%20Amazonas%20000031026450|website=waterwaymap.org}}</ref>
*''Yn Amason–[[Awin Ucayali|Ucayali]]–[[Awin Tambo (y Pheroo)|Tambo]]–[[Awin Ene|Ené]]–[[Awin Apurímac|Apurímac]]–Hornillos'' {{cvt|6,575|km|mi|abbr=on}}<ref name=liu-etal-river-length/>
*''Yn Amason–[[Awin Marañón|Marañón]]'' {{cvt|5,700|km|mi|abbr=on}}<ref name="The Amazon River"/>
*T'eh raait dy vel lhiurid yn Amason {{cvt|6,400|km|sp=us}} er y chooid sloo,<ref name="britannica-amazon">{{cite encyclopedia |url=https://www.britannica.com/place/Amazon-River |title=Amazon River |encyclopedia=Encyclopædia Britannica |url-status=live |archive-url=https://web.archive.org/web/20201108222644/https://www.britannica.com/place/Amazon-River |archive-date=8 Mee Houney 2020}}</ref><ref name="Aguas Amazónicas–Ucayali">{{cite web|url=https://aguasamazonicas.org/cuencas/cuencas-principales/ucayali|title=Aguas Amazónicas–Ucayali |date=7 Jerrey Souree 2022 }}</ref> agh ta leaghyn recortyssit eddyr {{cvt|6,275|as|7,025|km|sp=us}}.<ref name=liu-etal-river-length/>
The length measurements of many rivers are only approximations and differ from each other because many factors determine the calculated river length, such as the position of the geographical source and the mouth, the scale of measurement, and the length measuring techniques (for details see also [[List of rivers by length]]).<ref name=liu-etal-river-length/><ref name=river-source>{{Cite web |url=https://news.nationalgeographic.com/news/2014/02/140213-amazon-river-length-source-maps-science/ |title=Where Does the Amazon River Begin? |date=15 February 2014 |website=National Geographic News |access-date=25 December 2018 |archive-url=https://web.archive.org/web/20190327091707/https://news.nationalgeographic.com/news/2014/02/140213-amazon-river-length-source-maps-science/ |archive-date=27 March 2019 }}</ref>}}
| width_min = {{cvt|700|m}} (Upper Amazon); {{cvt|1.5|km|mi}} ([[Itacoatiara, Amazonas|Itacoatiara]], Lower Amazon)<ref name="Issues of local and global use of water from the Amazon"/>
| width_avg = {{cvt|3|km|mi}} (Middle Amazon); {{cvt|5|km|mi}} (Lower Amazon)<ref name="Issues of local and global use of water from the Amazon"/><ref name="Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil)">{{cite web |url=https://www.researchgate.net/publication/333157040 |title=Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil) |last1=Anderson da Silva |first1=Layes |last2=Marcondes Silva |first2=E. Silva |last3=Genilson Pereira |first3=Santana}}</ref>
| width_max = {{cvt|10–14|km|mi}} (Lower Amazon);<ref name="Issues of local and global use of water from the Amazon"/><ref name="Amazon River-Hydrology">{{cite web |url=https://www.britannica.com/place/Amazon-River/Hydrology |title=Amazon River-Hidrology |access-date=2 November 2022 |archive-date=14 October 2023 |archive-url=https://web.archive.org/web/20231014092545/https://www.britannica.com/place/Amazon-River/Hydrology |url-status=live }}</ref> {{cvt|340|km|mi}} (estuary)<ref name="Aguas Amazonicas">{{cite web |url=https://www.amazonwaters.org/ |title=Aguas Amazonicas |access-date=1 November 2022 |archive-date=3 July 2023 |archive-url=https://web.archive.org/web/20230703195120/https://amazonwaters.org/ |url-status=live }}</ref>
| depth_min =
| depth_avg = {{cvt|15–45|m}} (Middle Amazon); {{cvt|20–50|m}} (Lower Amazon)<ref name="Issues of local and global use of water from the Amazon"/>
| depth_max = {{cvt|150|m}} ([[Itacoatiara, Amazonas|Itacoatiara]]); {{cvt|130|m}} ([[Óbidos, Brazil|Óbidos]])<ref name="Issues of local and global use of water from the Amazon">{{cite web |url=https://unesdoc.unesco.org/ark:/48223/pf0000136195 |title=Issues of local and global use of water from the Amazon |access-date=1 November 2022 |archive-date=14 October 2023 |archive-url=https://web.archive.org/web/20231014093334/https://unesdoc.unesco.org/ark:/48223/pf0000136195 |url-status=live }}</ref><ref name="Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil)"/>
| source1 = [[Apurímac River]], [[Nevado Mismi|Mismi Peak]]
| source1_location = [[Arequipa Region]], [[Peru]]
| source1_coordinates = {{coord|15|31|04|S|71|41|37|W|display=inline,title}}
| source1_elevation = {{cvt|5,220|m|sp=us}}
| mouth = [[Atlantic Ocean]]
| mouth_location = [[Brazil]]
| mouth_coordinates = {{coord|0|42|28|N|50|5|22|W|type:_river}}
| progression =
| river_system = Amazon River
| basin_size ={{cvt|6,925,674|km2|mi2|abbr=on}}<ref name="Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome">{{cite report|url=
https://wwfint.awsassets.panda.org/downloads/amazon_vision_powpa_cbd_cop10_2010_engl_1.pdf|title=Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome|author=RedParques|publisher=Convenio sobre la Diversidad Biológica (CDB), International Union for Conservation of Nature (IUCN), World Wide Fund for Nature (WWF)|page=148|date=2010|website=wwfint.awsassets.panda.org}}</ref>{{refn|name=basin size|group=n|Entire Amazon–[[Tocantins River|Tocantins]] basin ({{cvt|6,743,000–7,050,000|km2|mi2|abbr=on}}.<ref name="osinfor22e">{{cite web |url=https://www.osinfor.gob.pe/portal/data/documentos/osinfor_minambiente/29102015/22e.pdf |title=CORPOAMAZONIA - TRÁMITES PARA APROVECHAMIENTO FORESTAL |access-date=8 October 2021 |archive-date=6 January 2023 |archive-url=https://web.archive.org/web/20230106052443/https://www.osinfor.gob.pe/portal/data/documentos/osinfor_minambiente/29102015/22e.pdf |url-status=live }}</ref><ref name="Hydrologie du bassin amazonien">{{cite book|url=https://horizon.documentation.ird.fr/exl-doc/pleins_textes/2022-02/010010558.pdf|title=Hydrologie du bassin amazonien|date=1997|isbn=2-7011-1532-9|last1=Théry |first1=Hervé |last2=Maurence |first2=Pascale |publisher=Belin }}</ref><ref name="Amazon">{{cite web|url=https://www.riversnetwork.org/V1/index.php/component/content/?view=article&id=43&catid=191&Itemid=179|title=Amazon|last=Eric|first=Tilman|website=www.riversnetwork.org}}</ref><ref name="britannica-amazon"/> Amazon without Tocantins {{cvt|5,956,000–6,112,000|km2|mi2|abbr=on}}<ref name="erudit"/><ref name="Estimating cell-to-cell land surface drainage paths from digital channel networks, with an application to the Amazon basin">{{cite journal|title=Estimating cell-to-cell land surface drainage paths from digital channel networks, with an application to the Amazon basin|last1=Emilio|first1=Mayorga|last2=Miles G.|first2=Longsdon|last3=Maria Victoria|first3=R. Ballester|last4=Jeffrey E.|first4=Richey|journal=Journal of Hydrology |year=2005|volume=315 |issue=1–4 |pages=167–182 |doi=10.1016/J.JHYDROL.2005.03.023|s2cid=8107631 }}</ref><ref name="Hydrologie du bassin amazonien"/>}}
| tributaries_left = [[Marañón River|Marañón]], [[Nanay River|Nanay]], [[Napo River|Napo]], [[Putumayo River|Putumayo]], [[Japurá River|Japurá]], [[Badajós River|Badajós]], [[Manacapuru River|Manacapuru]], [[Rio Negro (Amazon)|Rio Negro]], [[Urubu River (Amazonas)|Urubu]], [[Uatumã River|Uatumã]], [[Nhamundá River|Nhamundá]], [[Trombetas River|Trombetas]], [[Maicuru River|Maicurú]], [[Curuá River (Amazon River tributary)|Curuá]], [[Paru River|Paru]], [[Jari River|Jari]]
| tributaries_right = [[Ucayali River|Ucayali]], [[Jandiatuba River|Jandiatuba]], [[Javary River|Javary]], [[Jutai River|Jutaí]], [[Juruá]], [[Tefé River|Tefé]], [[Coari River|Coari]], [[Purús River|Purús]], [[Madeira River|Madeira]], [[Canumã River|Paraná do Ramos]], [[Tapajós River|Tapajós]], [[Curuá Una River|Curuá-Una]], [[Xingu River|Xingu]], [[Pará River|Pará]], [[Tocantins River|Tocantins]], [[Acará River|Acará]], [[Guamá River|Guamá]]
| custom_label =
| custom_data =
| extra =
| discharge1_location = [[Amazon Delta]]
| discharge1_min = {{cvt|83,400|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America">{{cite journal|journal=Global Biogeochemical Cycles|doi=10.1029/GB003i003p00241|url=https://doi.org/10.1029/GB003i003p00241|last1=Charles J.|first1=Vörösmarty|last2=Berrien|first2=Moore III|last3=Annette L.|first3=Grace|last4=M. Patricia|first4=Gildea|last5=Jerry M.|first5=Melille|last6=Bruce|first6=Peterson|last7=Edward|first7=B. Rastetter|last8=Paul|first8=A. Steudler|title=Continental scale models of water balance and fluvial transport: An application to South America|date=1989|volume=3|issue=3|pages=241–265|bibcode=1989GBioC...3..241V |url-access=subscription}}</ref>
| discharge1_avg ={{cvt|223,700|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>{{refn|name=discharge1|group=n|Amazon without Tocantins {{cvt|206,000–215,000|m3/s|sp=us}} and 209,000 m³/s (1973–1990);<ref name="erudit">Jacques Callède et. al.: ''[https://id.erudit.org/iderudit/044688ar Les apports en eau de l'Amazone à l'Océan Atlantique] {{Webarchive|url=https://web.archive.org/web/20231102051620/https://www.erudit.org/fr/revues/rseau/2010-v23-n3-rseau3946/044688ar/ |date=2 November 2023 }}.'' In: ''Revue des sciences de l'eau / Journal of Water Science.'' Bd. 23, Nr. 3, Montreal 2010, S. 247–273 (retrieved 19 August 2013)</ref><ref name="Hydrologie du bassin amazonien"/><ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
*The [[Pará River|Rio Pará]] is a tidally influenced estuary south of the Amazon River and [[Marajó|Marajó Island]]. From the mouth of the [[Anapu River]] and the [[Furo do Tajapuru]] Channel (Amazon branch) to the [[Atlantic Ocean]], it is about 350 km long. From the mouth of the [[Tocantins River|Tocantins]] River, it is called the [[Marajó Bay]]. The Rio Pará estuary receives a significant amount of water from the north through the Amazon River. Some scientists advocate classifying it as part of the Amazon basin, since a significant amount of water (on average 6,000 m³/s) enters the system from the Amazon.<ref name="erudit"/> If Amazon with Rio Pará considered as a water system, the catchment area is 6,925,674 km²,<ref name="Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome"/> the total discharge averages at [[Amazon Delta]] 223,700 m³/s (or 220,800 m³/s for the period 1973–1990; 230,000 m³/s for the period 2003–2015).<ref name="osinfor22e"/><ref name="ref01">{{cite web |url=https://horizon.documentation.ird.fr/exl-doc/pleins_textes/divers16-04/010014008.pdf |archive-url=https://ghostarchive.org/archive/20221009/https://horizon.documentation.ird.fr/exl-doc/pleins_textes/divers16-04/010014008.pdf |archive-date=2022-10-09 |url-status=live |title=EAUX, GLACIERS & CHANGEMENTS CLIMATIQUES DANS LES ANDES TROPICALES - Institut Français d'Études Andines - Institut Français de Recherche Scientifique pour le Développement en Cooperation |last1=Pierre |first1=Ribstein |last2=Bernard |first2=Francou |last3=Anne |first3=Coudrain Ribstein |last4=Philippe |first4=Mourguiart |year=1995}}</ref><ref name="hy1">{{cite web |title=Hydrological Control on the Temporal Variability of Trace Element Concentration in the Amazon River and its Main Tributaries |last=Seyler |first=Patrick |author2=Laurence Maurice-Bourgoin |author3=Jean Loup Guyot |publisher=Geological Survey of Brazil (CPRM) |url=http://www.cprm.gov.br/pgagem/Manuscripts/seylerp.htm |access-date=24 July 2010 |url-status=live |archive-url=https://web.archive.org/web/20110721224824/http://www.cprm.gov.br/pgagem/Manuscripts/seylerp.htm |archive-date=21 July 2011 }}</ref><ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="Hydrologie du bassin amazonien"/><ref name="A discharge stationary model for the Pará-Amazon estuarine system">{{cite journal |last1=Prestes |first1=Yuri Onça |last2=Borba |first2=Thais Angélica da Costa |last3=Silva |first3=Alex Costa da |last4=Rollnic |first4=Marcelo |title=A discharge stationary model for the Pará-Amazon estuarine system |journal=Journal of Hydrology: Regional Studies |year=2020 |volume=28 |article-number=100668 |doi=10.1016/j.ejrh.2020.100668 |s2cid=213143882 |doi-access=free }}</ref><ref name="The Estuary">{{cite web|url=https://en.aguasamazonicas.org/basins/estuary-coast/the-estuary|title=The Estuary|website=aguasamazonicas.org}}</ref><ref name="Marajó Bay">{{cite web|url=https://en.aguasamazonicas.org/basins/estuary-coast/marajo-bay|title=Marajó Bay|website=aguasamazonicas.org}}</ref><ref name="Conjuntura dos Recursos Hídricos no Brasil: regiões hidrográficas brasileiras">{{cite report|url=https://www.snirh.gov.br/portal/snirh/centrais-de-conteudos/conjuntura-dos-recursos-hidricos/regioeshidrograficas2014.pdf|title=Conjuntura dos Recursos Hídricos no Brasil: regiões hidrográficas brasileiras|docket=Edição Especial|author=Agéncia Nacional de Águas (ANA)|publisher=Superintendência de Planegiamento de Recursos Hídricos (SPR)|page=163|isbn=978-85-8210-027-1|date=2015|website=www.snirh.gov.br}}</ref><ref name="The River Amazon water contribution to the Atlantic Ocean">{{cite journal|journal=Journal of Water Science|url=https://id.erudit.org/iderudit/044688ar|doi=10.7202/044688ar|title=The River Amazon water contribution to the Atlantic Ocean|last1=Jacques|first1=Callède|last2=Gérard|first2=Cochonneau|last3=Fabrício|first3=Vieira Alves|last4=Jean-Loup|first4=Guyot|last5=Valdemar|first5=Santos Guimarães|last6=Eurides|first6=De Oliveira|volume=23|number=3|date=2010|pages=247–273}}</ref>}}
| discharge1_max={{cvt|329,500|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| discharge2_location =[[Santarém, Pará|Santarém]]
| discharge2_min = {{cvt|76,500|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="River and Reservoir Watch Version 4.5-148">{{cite web|url=https://floodobservatory.colorado.edu/SiteDisplays/148data.htm|title=River and Reservoir Watch Version 4.5-148}}</ref>
| discharge2_avg ={{cvt|188,600|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| discharge2_max ={{cvt|271,100|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="River and Reservoir Watch Version 4.5-148"/>
| discharge3_location = [[Óbidos, Brazil|Óbidos]]
| discharge3_avg ={{cvt|172,100|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>{{refn|name=discharge3|group=n|(Period: 1903–2023) {{cvt|165,829.6|m3/s|cuft/s|abbr=on}}<ref name="ANA">{{cite web|url=https://www.gov.br/ana/pt-br|title=ANA|website=www.gov.br}}</ref>
(Period: 1971–2000) {{cvt|173,272.6|m3/s|cuft/s}}<ref name="Amazon"/>
(Period: 1928–1996) {{cvt|176,177|m3/s|cuft/s}}<ref name="GRDC">GRDC: [https://www.compositerunoff.sr.unh.edu/html/Polygons/P3629000.html Daten des Pegels ''Óbidos''] {{Webarchive|url=https://web.archive.org/web/20220809114257/https://www.compositerunoff.sr.unh.edu/html/Polygons/P3629000.html |date=9 August 2022 }}</ref>
(Period: 1997–2015) {{cvt|178,193.9|m3/s|cuft/s}}<ref name="Assess1">{{cite web |url=https://hess.copernicus.org/articles/23/3057/2019/hess-23-3057-2019-supplement.pdf |title=Assessing the performance of global hydrological models for capturing peak river flows in the Amazon basin |last=Jamie |first=Towner |year=2019 |access-date=28 March 2022 |archive-date=14 October 2023 |archive-url=https://web.archive.org/web/20231014093200/https://hess.copernicus.org/articles/23/3057/2019/hess-23-3057-2019-supplement.pdf |url-status=live }}</ref>}}
| discharge3_min ={{cvt|71,700|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| discharge3_max ={{cvt|241,200|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| discharge4_location = [[Manacapuru]]
| discharge4_min={{cvt|58,800|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI">{{cite report|title=Amazonía y Agua: Desarollo sostenible en el siglo XXI|url=https://www.ehu.eus/cdsea/web/wp-content/uploads/2016/11/Libro_Amazonia_Agua.pdf|last=Hernando Bernal|first=Zamudio|publisher=Unesco Etxea|location=Brasilia (Brazil)|isbn=978-84-934779-8-1|page=503|date=2009|website=www.ehu.eus}}</ref>
| discharge4_avg =
{{cvt|102,600|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| discharge4_max =
{{cvt|139,000|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| discharge5_location =[[Tamshiyacu|Tamshiyaçu]]
| stroo-magh5_min =
{{cvt|16,400|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| discharge5_avg ={{cvt|31,700|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| discharge5_max =
{{cvt|46,700|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
}}
'''Yn Amason''' ({{lang-es|Río Amazonas}}, {{lang-pt|Rio Amazonas}}) ayns [[America Yiass]], she yn awin smoo 'sy theihll rere lhiggey magh ushtey as t'ee 'sy chied ynnyd marish [[Yn Neel|y Neel]] myr yn awin s'liurey 'sy theihll.
[[Coadan:Amazonrivermap.svg|left|thumb|Yn Amason as yn awin-tragh eck]]
{{gurneil eaghtyrys}}
{{DEFAULTSORT:Amason, Yn}}
{{bun}}
[[Ronney:Yn Amason| ]]
[[Ronney:Awintragh yn Amason]]
[[Ronney:Keyll liaghee yn Amason]]
[[Ronney:Awinyn ayns America Yiass]]
[[Ronney:Awinyn eddyrashoonagh ayns America Yiass]]
[[Ronney:Awinyn 'sy Cholombey]]
[[Ronney:Awinyn 'sy Pheroo]]
[[Ronney:Awinyn ayns Amapá]]
[[Ronney:Awinyn ayns Amazonas (steat Brasseelagh)]]
[[Ronney:Awinyn ayns Ard Loreto]]
[[Ronney:Awinyn ayns Pará]]
[[Ronney:Awinyn 'sy Vrasseel]]
o4j56ga49lqlfjixlcxzfnj3rur40ng
392718
392699
2026-09-02T02:28:34Z
MacTire02
219
++
392718
wikitext
text/x-wiki
{{Kishtey fys awin
| ennym = Yn Amason
| ennym_dooghyssagh = {{native name|pt|Amazonas}}
| ennym_elley = {{lang|pt|Rio Amazonas}}, {{lang|es|Río Amazonas}}
| jalloo = Amazon River ESA387332.jpg
| mooadys_jalloo = 250
| fo-heidyl_jalloo = Satellite image of the [[Amazon Delta]]
| sorçh_aarheynn1 = Çheer
| ennym_aarheynn1 = [[Yn Pheroo|Y Pheroo]], [[Yn Cholombey|y Cholombey]], [[Yn Vrasseel|y Vrasseel]]
| ard-valjyn = [[Iquitos]] (y Pheroo); [[Leticia, Amazonas|Leticia]] (y Cholombey); [[Tabatinga]] (y Vrasseel); [[Tefé]] (y Vrasseel); [[Itacoatiara, Amazonas|Itacoatiara]] (y Vrasseel) [[Parintins]] (y Vrasseel); [[Óbidos, Pará|Óbidos]] (y Vrasseel); [[Santarém, Pará|Santarém]] (y Vrasseel); [[Almeirim, Pará|Almeirim]] (y Vrasseel); [[Macapá]] (y Vrasseel);<br />[[Manaus]] (y Vrasseel)
| lhiurid ={{cvt|6,575|km|mi|abbr=on}}{{refn|name=length|group=n|Co-strooan ny h-awinyn Marañón as Ucayali dys yn inver {{cvt|3,750|km|mi|abbr=on}}.<ref name="The Amazon River">{{cite web|url=https://en.aguasamazonicas.org/basins/amazon-main-stem/the-main-stem|title=The Amazon River|date=28 Boaldyn 2014 }}</ref><ref name="Aguas Amazónicas–El río Amazonas">{{cite web|url=https://aguasamazonicas.org/cuencas/canal-principal-del-amazonas/rio-amazonas|title=Aguas Amazónicaa-El río Amazonas |date=7 Jerrey Souree 2022 }}</ref><ref name="Rio Amazonas">{{cite web|title=Rio Amazonas|url=https://waterwaymap.org/river/Rio%20Amazonas%20000031026450|website=waterwaymap.org}}</ref>
*''Yn Amason–[[Awin Ucayali|Ucayali]]–[[Awin Tambo (y Pheroo)|Tambo]]–[[Awin Ene|Ené]]–[[Awin Apurímac|Apurímac]]–Hornillos'' {{cvt|6,575|km|mi|abbr=on}}<ref name=liu-etal-river-length/>
*''Yn Amason–[[Awin Marañón|Marañón]]'' {{cvt|5,700|km|mi|abbr=on}}<ref name="The Amazon River"/>
*T'eh raait dy vel lhiurid yn Amason {{cvt|6,400|km|sp=us}} er y chooid sloo,<ref name="britannica-amazon">{{cite encyclopedia |url=https://www.britannica.com/place/Amazon-River |title=Amazon River |encyclopedia=Encyclopædia Britannica |url-status=live |archive-url=https://web.archive.org/web/20201108222644/https://www.britannica.com/place/Amazon-River |archive-date=8 Mee Houney 2020}}</ref><ref name="Aguas Amazónicas–Ucayali">{{cite web|url=https://aguasamazonicas.org/cuencas/cuencas-principales/ucayali|title=Aguas Amazónicas–Ucayali |date=7 Jerrey Souree 2022 }}</ref> agh ta leaghyn recortyssit eddyr {{cvt|6,275|as|7,025|km|sp=us}}.<ref name=liu-etal-river-length/>
Foddee towshanyn lhiurid ram awinyn ve nyn vaggyssaghtyn as foddee ad anchasley voish y cheilley er-yn-oyr dy vel ram faghteyryn ayn son son dy chronnaghey lhiurid awinyn, lheid as soiaghey yn voir heer-oaylleeagh as yn inver, scaailley yn towshan, as çhaghnyssyn towshanagh y lhiurid (son sonreeaghtyn, jeeagh er [[Rolley awinyn rere lhiurid]]).<ref name=liu-etal-river-length/><ref name=river-source>{{Cite web |url=https://news.nationalgeographic.com/news/2014/02/140213-amazon-river-length-source-maps-science/ |title=Where Does the Amazon River Begin? |date=15 Toshiaght Arree 2014 |website=National Geographic News |access-date=25 Mee ny Nollick 2018 |archive-url=https://web.archive.org/web/20190327091707/https://news.nationalgeographic.com/news/2014/02/140213-amazon-river-length-source-maps-science/ |archive-date=27 Mayrnt 2019 }}</ref>}}
| lheead_min = {{cvt|700|m}} (Yn Amason Heose); {{cvt|1.5|km|mi}} ([[Itacoatiara, Amazonas|Itacoatiara]], Yn Amason Heese)<ref name="Issues of local and global use of water from the Amazon"/>
| lheead_mean = {{cvt|3|km|mi}} (Yn Amason Veanagh); {{cvt|5|km|mi}} (Yn Amason Heese)<ref name="Issues of local and global use of water from the Amazon"/><ref name="Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil)">{{cite web |url=https://www.researchgate.net/publication/333157040 |title=Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil) |last1=Anderson da Silva |first1=Layes |last2=Marcondes Silva |first2=E. Silva |last3=Genilson Pereira |first3=Santana}}</ref>
| lheead_max = {{cvt|10–14|km|mi}} (Yn Amason Heese);<ref name="Issues of local and global use of water from the Amazon"/><ref name="Amazon River-Hydrology">{{cite web |url=https://www.britannica.com/place/Amazon-River/Hydrology |title=Amazon River-Hidrology |access-date=2 Mee Houney 2022 |archive-date=14 Jerrey Fouyir 2023 |archive-url=https://web.archive.org/web/20231014092545/https://www.britannica.com/place/Amazon-River/Hydrology |url-status=live }}</ref> {{cvt|340|km|mi}} (inver)<ref name="Aguas Amazonicas">{{cite web |url=https://www.amazonwaters.org/ |title=Aguas Amazonicas |access-date=1 Mee Houney 2022 |archive-date=3 Jerrey Souree 2023 |archive-url=https://web.archive.org/web/20230703195120/https://amazonwaters.org/ |url-status=live }}</ref>
| diunid_min =
| diunid_mean = {{cvt|15–45|m}} (yn Amason Veanagh); {{cvt|20–50|m}} (yn Amason Heese)<ref name="Issues of local and global use of water from the Amazon"/>
| diunid_max = {{cvt|150|m}} ([[Itacoatiara, Amazonas|Itacoatiara]]); {{cvt|130|m}} ([[Óbidos, y Vrasseel|Óbidos]])<ref name="Issues of local and global use of water from the Amazon">{{cite web |url=https://unesdoc.unesco.org/ark:/48223/pf0000136195 |title=Issues of local and global use of water from the Amazon |access-date=1 Mee Houney 2022 |archive-date=14 Jerrey Fouyir 2023 |archive-url=https://web.archive.org/web/20231014093334/https://unesdoc.unesco.org/ark:/48223/pf0000136195 |url-status=live }}</ref><ref name="Seasonal assessment of groundwater quality in the cities of Itacoatiara and Manacapuru (Amazon, Brazil)"/>
| moir1 = [[Awin Apurímac]], [[Nevado Mismi|Beinn Mismi]]
| soiaghey_moir1 = [[Ard Arequipa]], y [[Yn Pheroo|Pheroo]]
| co-ordnaidyn_moir1 = {{coord|15|31|04|S|71|41|37|W|display=inline,title}}
| yrjid_moir1 = {{cvt|5,220|m|sp=us}}
| inver = [[Yn Keayn Sheear|Y Keayn Sheear]]
| soiaghey_inver = [[Yn Vrasseel|Y Vrasseel]]
| co-ordnaidyn_inver = {{coord|0|42|28|N|50|5|22|W|type:_river}}
| progression =
| corys_awiney = Yn Amason
| mooadys_awintragh ={{cvt|6,925,674|km2|mi2|abbr=on}}<ref name="Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome">{{cite report|url=
https://wwfint.awsassets.panda.org/downloads/amazon_vision_powpa_cbd_cop10_2010_engl_1.pdf|title=Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome|author=RedParques|publisher=Convenio sobre la Diversidad Biológica (CDB), International Union for Conservation of Nature (IUCN), World Wide Fund for Nature (WWF)|page=148|date=2010|website=wwfint.awsassets.panda.org}}</ref>{{refn|name=basin size|group=n|Slane awintragh yn Amason–[[Awin Tocantins|Tocantins]] ({{cvt|6,743,000–7,050,000|km2|mi2|abbr=on}}.<ref name="osinfor22e">{{cite web |url=https://www.osinfor.gob.pe/portal/data/documentos/osinfor_minambiente/29102015/22e.pdf |title=CORPOAMAZONIA - TRÁMITES PARA APROVECHAMIENTO FORESTAL |access-date=8 Jerrey Fouyir 2021 |archive-date=6 Jerrey Geuree 2023 |archive-url=https://web.archive.org/web/20230106052443/https://www.osinfor.gob.pe/portal/data/documentos/osinfor_minambiente/29102015/22e.pdf |url-status=live }}</ref><ref name="Hydrologie du bassin amazonien">{{cite book|url=https://horizon.documentation.ird.fr/exl-doc/pleins_textes/2022-02/010010558.pdf|title=Hydrologie du bassin amazonien|date=1997|isbn=2-7011-1532-9|last1=Théry |first1=Hervé |last2=Maurence |first2=Pascale |publisher=Belin }}</ref><ref name="Amazon">{{cite web|url=https://www.riversnetwork.org/V1/index.php/component/content/?view=article&id=43&catid=191&Itemid=179|title=Amazon|last=Eric|first=Tilman|website=www.riversnetwork.org}}</ref><ref name="britannica-amazon"/> Yn Amason gyn Tocantins {{cvt|5,956,000–6,112,000|km2|mi2|abbr=on}}<ref name="erudit"/><ref name="Estimating cell-to-cell land surface drainage paths from digital channel networks, with an application to the Amazon basin">{{cite journal|title=Estimating cell-to-cell land surface drainage paths from digital channel networks, with an application to the Amazon basin|last1=Emilio|first1=Mayorga|last2=Miles G.|first2=Longsdon|last3=Maria Victoria|first3=R. Ballester|last4=Jeffrey E.|first4=Richey|journal=Journal of Hydrology |year=2005|volume=315 |issue=1–4 |pages=167–182 |doi=10.1016/J.JHYDROL.2005.03.023|s2cid=8107631 }}</ref><ref name="Hydrologie du bassin amazonien"/>}}
| crouw-awinyn_toshtal = [[Awin Marañón|Marañón]], [[Awin Nanay|Nanay]], [[Awin Napo|Napo]], [[Awin Putumayo|Putumayo]], [[Awin Japurá|Japurá]], [[Awin Badajós|Badajós]], [[Awin Manacapuru|Manacapuru]], [[Rio Negro (yn Amason)|Rio Negro]], [[Awin Urubu (Amazonas)|Urubu]], [[Awin Uatumã|Uatumã]], [[Awin Nhamundá|Nhamundá]], [[Awin Trombetas|Trombetas]], [[Awin Maicuru|Maicurú]], [[Awin Curuá (crouw-awin yn Amason)|Curuá]], [[Awin Paru|Paru]], [[Awin Jari|Jari]]
| crouw-awinyn_jesh = [[Awin Ucayali|Ucayali]], [[Awin Jandiatuba|Jandiatuba]], [[Awin Javary|Javary]], [[Awin Jutai|Jutaí]], [[Juruá]], [[Awin Tefé|Tefé]], [[Awin Coari|Coari]], [[Awin Purús|Purús]], [[Awin Madeira|Madeira]], [[Awin Canumã|Paraná do Ramos]], [[Awin Tapajós|Tapajós]], [[Awin Curuá Una|Curuá-Una]], [[Awin Xingu|Xingu]], [[Awin Pará|Pará]], [[Awin Tocantins|Tocantins]], [[Awin Acará|Acará]], [[Awin Guamá|Guamá]]
| soiaghey_stroo-magh1 = [[Deltey yn Amason]]
| stroo-magh1_min = {{cvt|83,400|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America">{{cite journal|journal=Global Biogeochemical Cycles|doi=10.1029/GB003i003p00241|url=https://doi.org/10.1029/GB003i003p00241|last1=Charles J.|first1=Vörösmarty|last2=Berrien|first2=Moore III|last3=Annette L.|first3=Grace|last4=M. Patricia|first4=Gildea|last5=Jerry M.|first5=Melille|last6=Bruce|first6=Peterson|last7=Edward|first7=B. Rastetter|last8=Paul|first8=A. Steudler|title=Continental scale models of water balance and fluvial transport: An application to South America|date=1989|volume=3|issue=3|pages=241–265|bibcode=1989GBioC...3..241V |url-access=subscription}}</ref>
| stroo-magh1_mean ={{cvt|223,700|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>{{refn|name=discharge1|group=n|Yn Amason gyn Tocantins {{cvt|206,000–215,000|m3/s|sp=us}} as {{cvt|209,000|m3/s}} (1973–1990);<ref name="erudit">Jacques Callède et. al.: ''[https://id.erudit.org/iderudit/044688ar Les apports en eau de l'Amazone à l'Océan Atlantique] {{Webarchive|url=https://web.archive.org/web/20231102051620/https://www.erudit.org/fr/revues/rseau/2010-v23-n3-rseau3946/044688ar/ |date=2 Mee Houney 2023 }}.'' Ayns: ''Revue des sciences de l'eau / Journal of Water Science.'' Bd. 23, Nr. 3, Montreal 2010, S. 247–273 (feddynit magh er 19 Luanistyn 2013)</ref><ref name="Hydrologie du bassin amazonien"/><ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
*She inver tidee çheu yiass veih'n Amason as veih [[Marajó|Ellan Marajó]] eh [[Awin Pará|Rio Pará]]. T'eh {{cvt|350|km}} er lhiurid veih inver yn [[Awin Anapu]] as Ammyr [[Furo do Tajapuru]] (crouw yn Amason) dys y [[Yn Keayn Sheear|Cheayn Sheear]]. Veih inveryn awin [[Awin Tocantins|Tocantins]], t'eh enmyssit [[Baie Marajó]]. Ta inver Rio Pará geddyn kuse vooar d'ushtey veih'n twoaie trooid Awin yn Amason. Ta sheanseyryn eigsoylagh shirrey eh dy enmyssey myr ayrn jeh awintragh yn Amason er-yn-oyr dy vel kuse vooar ({{cvt|6,000|m3/s}}) goll stiagh 'sy chorys veih'n Amason.<ref name="erudit"/> My vel yn Amason marish Rio Pará coontit myr un chorys awiney, ta'n awintragh {{cvt|6,925,674|km2}} er eaghtyr,<ref name="Progress Report – ln the Development of the Program of Work on Protected Areas Region: Amazon Biome"/> as ta'n slane stroo-magh meanagh ec [[Deltey yn Amason]] er {{cvt|223,700|m3/s}} (ny {{cvt|220,800|m3/s}} da'n earish eddyr 1973 as 1990; {{cvt|230,000|m3/s}} da'n earish eddyr 2003 as 2015).<ref name="osinfor22e"/><ref name="ref01">{{cite web |url=https://horizon.documentation.ird.fr/exl-doc/pleins_textes/divers16-04/010014008.pdf |archive-url=https://ghostarchive.org/archive/20221009/https://horizon.documentation.ird.fr/exl-doc/pleins_textes/divers16-04/010014008.pdf |archive-date=2022-10-09 |url-status=live |title=EAUX, GLACIERS & CHANGEMENTS CLIMATIQUES DANS LES ANDES TROPICALES - Institut Français d'Études Andines - Institut Français de Recherche Scientifique pour le Développement en Cooperation |last1=Pierre |first1=Ribstein |last2=Bernard |first2=Francou |last3=Anne |first3=Coudrain Ribstein |last4=Philippe |first4=Mourguiart |year=1995}}</ref><ref name="hy1">{{cite web |title=Hydrological Control on the Temporal Variability of Trace Element Concentration in the Amazon River and its Main Tributaries |last=Seyler |first=Patrick |author2=Laurence Maurice-Bourgoin |author3=Jean Loup Guyot |publisher=Towshan-çheerey Creg-oaylleeagh y Vrasseel (CPRM) |url=http://www.cprm.gov.br/pgagem/Manuscripts/seylerp.htm |access-date=24 Jerrey Souree 2010 |url-status=live |archive-url=https://web.archive.org/web/20110721224824/http://www.cprm.gov.br/pgagem/Manuscripts/seylerp.htm |archive-date=21 Jerrey Souree 2011 }}</ref><ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="Hydrologie du bassin amazonien"/><ref name="A discharge stationary model for the Pará-Amazon estuarine system">{{cite journal |last1=Prestes |first1=Yuri Onça |last2=Borba |first2=Thais Angélica da Costa |last3=Silva |first3=Alex Costa da |last4=Rollnic |first4=Marcelo |title=A discharge stationary model for the Pará-Amazon estuarine system |journal=Journal of Hydrology: Regional Studies |year=2020 |volume=28 |article-number=100668 |doi=10.1016/j.ejrh.2020.100668 |s2cid=213143882 |doi-access=free }}</ref><ref name="The Estuary">{{cite web|url=https://en.aguasamazonicas.org/basins/estuary-coast/the-estuary|title=The Estuary|website=aguasamazonicas.org}}</ref><ref name="Marajó Bay">{{cite web|url=https://en.aguasamazonicas.org/basins/estuary-coast/marajo-bay|title=Marajó Bay|website=aguasamazonicas.org}}</ref><ref name="Conjuntura dos Recursos Hídricos no Brasil: regiões hidrográficas brasileiras">{{cite report|url=https://www.snirh.gov.br/portal/snirh/centrais-de-conteudos/conjuntura-dos-recursos-hidricos/regioeshidrograficas2014.pdf|title=Conjuntura dos Recursos Hídricos no Brasil: regiões hidrográficas brasileiras|docket=Edição Especial|author=Agéncia Nacional de Águas (ANA)|publisher=Superintendência de Planegiamento de Recursos Hídricos (SPR)|page=163|isbn=978-85-8210-027-1|date=2015|website=www.snirh.gov.br}}</ref><ref name="The River Amazon water contribution to the Atlantic Ocean">{{cite journal|journal=Journal of Water Science|url=https://id.erudit.org/iderudit/044688ar|doi=10.7202/044688ar|title=The River Amazon water contribution to the Atlantic Ocean|last1=Jacques|first1=Callède|last2=Gérard|first2=Cochonneau|last3=Fabrício|first3=Vieira Alves|last4=Jean-Loup|first4=Guyot|last5=Valdemar|first5=Santos Guimarães|last6=Eurides|first6=De Oliveira|volume=23|number=3|date=2010|pages=247–273}}</ref>}}
| stroo-magh1_max={{cvt|329,500|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| soiaghey_stroo-magh2 =[[Santarém, Pará|Santarém]]
| stroo-magh2_min = {{cvt|76,500|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="River and Reservoir Watch Version 4.5-148">{{cite web|url=https://floodobservatory.colorado.edu/SiteDisplays/148data.htm|title=River and Reservoir Watch Version 4.5-148}}</ref>
| stroo-magh2_mean ={{cvt|188,600|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| stroo-magh2_max ={{cvt|271,100|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/><ref name="River and Reservoir Watch Version 4.5-148"/>
| soiaghey_stroo-magh3 = [[Óbidos, y Vrasseel|Óbidos]]
| stroo-magh3_mean ={{cvt|172,100|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>{{refn|name=discharge3|group=n|(Earish: 1903–2023) {{cvt|165,829.6|m3/s|cuft/s|abbr=on}}<ref name="ANA">{{cite web|url=https://www.gov.br/ana/pt-br|title=ANA|website=www.gov.br}}</ref>
(Earish: 1971–2000) {{cvt|173,272.6|m3/s|cuft/s}}<ref name="Amazon"/>
(Earish: 1928–1996) {{cvt|176,177|m3/s|cuft/s}}<ref name="GRDC">GRDC: [https://www.compositerunoff.sr.unh.edu/html/Polygons/P3629000.html Daten des Pegels ''Óbidos''] {{Webarchive|url=https://web.archive.org/web/20220809114257/https://www.compositerunoff.sr.unh.edu/html/Polygons/P3629000.html |date=9 Luanistyn 2022 }}</ref>
(Earish: 1997–2015) {{cvt|178,193.9|m3/s|cuft/s}}<ref name="Assess1">{{cite web |url=https://hess.copernicus.org/articles/23/3057/2019/hess-23-3057-2019-supplement.pdf |title=Assessing the performance of global hydrological models for capturing peak river flows in the Amazon basin |last=Jamie |first=Towner |year=2019 |access-date=28 Mayrnt 2022 |archive-date=14 Jerrey Fouyir 2023 |archive-url=https://web.archive.org/web/20231014093200/https://hess.copernicus.org/articles/23/3057/2019/hess-23-3057-2019-supplement.pdf |url-status=live }}</ref>}}
| stroo-magh3_min ={{cvt|71,700|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| stroo-magh3_max ={{cvt|241,200|m3/s|cuft/s|abbr=on}}<ref name="Continental scale models of water balance and fluvial transport: An application to South America"/>
| soiaghey_stroo-magh4 = [[Manacapuru]]
| stroo-magh4_min={{cvt|58,800|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI">{{cite report|title=Amazonía y Agua: Desarollo sostenible en el siglo XXI|url=https://www.ehu.eus/cdsea/web/wp-content/uploads/2016/11/Libro_Amazonia_Agua.pdf|last=Hernando Bernal|first=Zamudio|publisher=Unesco Etxea|location=Brasilia (y Vrasseel)|isbn=978-84-934779-8-1|page=503|date=2009|website=www.ehu.eus}}</ref>
| stroo-magh4_mean =
{{cvt|102,600|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| stroo-magh4_max =
{{cvt|139,000|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| soiaghey_stroo-magh5=[[Tamshiyacu|Tamshiyaçu]]
| stroo-magh5_min =
{{cvt|16,400|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| stroo-magh5_mean ={{cvt|31,700|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
| stroo-magh5_max =
{{cvt|46,700|m3/s|cuft/s|abbr=on}}<ref name="Amazonía y Agua: Desarollo sostenible en el siglo XXI"/>
}}
[[Coadan:Amazonas und Reliefkarte.png|thumb|upright=1.3|Boayl-oaylleeaght Awintragh yn Amason]]
She '''yn Amason''' ny '''Awin yn Amason''' ({{langx|pt|rio Amazonas}}, {{langx|es|río Amazonas}}) ayns [[America Yiass]] yn [[Rolley awinyn rere stroo-magh|awin smoo 'sy theihll rere mooad yn ushtey t'eh stroo magh]], as y [[Rolley coryssyn awiney rere lhiurid|nah awin s'liurey ny yn awin s'liurey]], enmys fo arganeys lesh y [[Yn Neel|Neel]].<ref name="britannica-amazon"/><ref>{{cite journal |last1=Uereyen |first1=Soner |last2=Kuenzer |first2=Claudia |title=A Review of Earth Observation-Based Analyses for Major River Basins |journal=Remote Sensing |date=9 Mee ny Nollick 2019 |volume=11 |issue=24 |page=2951 |doi=10.3390/rs11242951 |bibcode=2019RemS...11.2951U |doi-access=free| issn = 2072-4292}}.</ref>{{refn|Dy cadjin, t'eh craait dy nee yn [[Yn Neel|Neel]] yn awin s'liurey 'sy theihll, as eh mysh {{cvt|6,650|km|mi}} er lhiurid,<ref name=britannica-nile/> as dy nee yn Amason y nah awin s'liurey 'sy theihll, as eh {{cvt|6,400|km|mi}} er lhiurid er y chooid sloo.<ref name=britannica-amazon/> Ayns ny bleeantyn 2007 as 2008, ren sheanseyryn ennagh fogrey magh dy row yn Amason {{cvt|6,992|km|mi}} er lhiurid as dy row eh ny s'liurey na'n Neel, v'er ny cho-earrooaghey er {{cvt|6,853|km|mi}} er lhiurid.<ref name=bbc-amazon/><ref name=Roach>{{cite magazine|last1=Roach|first1=John|date=2007-06-18|location=[[Washington D.C.]]|title=Amazon Longer Than Nile River, Scientists Say|url=https://www.nationalgeographic.com/science/article/amazon-longer-than-nile-river|url-access= |trans-title= |format= |department= |magazine=[[National Geographic]]|language=en-US|publisher=[[National Geographic Partners]]|issn=0027-9358|oclc=643483454|url-status=live|archive-url=https://web.archive.org/web/20241215180734/https://www.nationalgeographic.com/science/article/amazon-longer-than-nile-river|archive-date=2024-12-15|access-date=2017-08-15}}</ref> Ta art [[scrutaghey coasan|scrutit lesh coasanyn]], v'er ny hoilshaghey magh 'sy vlein 2009, genmyssey lhiurid er {{cvt|7,088|km|mi}} da'n Neel as {{cvt|6,575|km|mi}} da'n Amason, as ad er ny ve towshit lesh mestey oltscarrey jallooyn cruinlag as ronsaghtyn magheragh dys ny moir-ardjyn.<ref name="liu-etal-river-length">{{Cite journal |last1=Liu |first1=Shaochuang |last2=Lu |first2=P |last3=Liu |first3=D |last4=Jin |first4=P |last5=Wang |first5=W |date=1 Mayrnt 2009 |title=Pinpointing the sources and measuring the lengths of the principal rivers of the world |url=https://www.researchgate.net/publication/220473241 |journal=Int. J. Digit. Earth |volume=2 |issue=1 |pages=80–87 |doi=10.1080/17538940902746082 |bibcode=2009IJDE....2...80L |s2cid=27548511 |access-date=29 Mee ny Nollick 2018 |archive-url=https://web.archive.org/web/20181223211543/https://www.researchgate.net/publication/220473241_Pinpointing_the_sources_and_measuring_the_lengths_of_the_principal_rivers_of_the_world |archive-date=23 Mee ny Nollick 2018 |url-status=live}}</ref>
Rere [[Encyclopædia Britannica]], roish 2020, ta lhiurid yn Amason foast foshlit, croghey er bree as bun as ta foast fo arganeys.<ref name="britannica-amazon"/><ref name="britannica-amazon-length">{{Cite web |url=https://www.britannica.com/story/how-long-is-the-amazon-river |title=How Long Is the Amazon River? |website=Encyclopedia Britannica |language=en |access-date=24 Mee ny Nollick 2018 |archive-url=https://web.archive.org/web/20181224171204/https://www.britannica.com/story/how-long-is-the-amazon-river |archive-date=24 Mee ny Nollick 2018 |url-status=live}}</ref>|name=longest|group=n}}
<!--The headwaters of the [[Apurímac River]] on [[Nevado Mismi]] in [[Peru]] had been considered, for nearly a century, the [[Amazon basin]]'s most distant source until a 2014 study found it to be the headwaters of the [[Mantaro River]] on the Cordillera Rumi Cruz in Peru.<ref name="ContosTripcevich">{{cite journal |author1=James Contos |author2=Nicholas Tripcevich |title=Correct placement of the most distant source of the Amazon River in the Mantaro River drainage |journal=Area |date=March 2014 |volume=46 |issue=1 |pages=27–39 |doi=10.1111/area.12069 |bibcode=2014Area...46...27C |url=https://escholarship.org/content/qt6js988dk/qt6js988dk.pdf?t=nmjqr2 |access-date=30 August 2019 |archive-date=26 January 2021 |archive-url=https://web.archive.org/web/20210126182635/https://escholarship.org/content/qt6js988dk/qt6js988dk.pdf?t=nmjqr2 |url-status=live }}</ref> The Mantaro and Apurímac rivers join, and with other tributaries form the [[Ucayali River]], which in turn meets the [[Marañón River]] upstream of [[Iquitos]], Peru, forming what countries other than [[Brazil]] consider to be the [[main stem]] of the Amazon. Brazilians call this section the [[Solimões River]] above its confluence with the [[Rio Negro (Amazon)|Rio Negro]]<ref name=Penn>{{cite book |last=Penn |first=James R. |title=Rivers of the World |year=2001 |publisher=ABC-CLIO |isbn=978-1-57607-042-0 |url=https://archive.org/details/riversofworldsoc00penn |url-access=registration |page=[https://archive.org/details/riversofworldsoc00penn/page/8 8] }}</ref> forming what Brazilians call the Amazon at the [[Meeting of Waters]] ({{langx|pt|Encontro das Águas}}) at [[Manaus]], the largest city on the river.
The Amazon River has an average discharge of about {{convert|215,000|to|230,000|m3/s|sp=us}}—approximately {{convert|6,591|to|7,570|km3|cumi|sp=us}} per year, greater than the next seven largest independent rivers combined. Two of the top ten rivers by discharge are [[tributaries]] of the Amazon river. The Amazon represents 20% of the global riverine discharge into oceans.<ref name="auto">{{cite journal |last1=Moura |first1=Rodrigo L. |last2=Amado-Filho |first2=Gilberto M. |last3=Moraes |first3=Fernando C. |last4=Brasileiro |first4=Poliana S. |last5=Salomon |first5=Paulo S. |last6=Mahiques |first6=Michel M. |last7=Bastos |first7=Alex C. |last8=Almeida |first8=Marcelo G. |last9=Silva |first9=Jomar M.|last10=Araujo|first10=Beatriz F. |last11=Brito |first11=Frederico P. |last12=Rangel |first12=Thiago P. |last13=Oliveira |first13=Braulio C.V. |last14=Bahia |first14=Ricardo G. |last15=Paranhos |first15=Rodolfo P. |last16=Dias |first16=Rodolfo J. S. |last17=Siegle |first17=Eduardo |last18=Figueiredo |first18=Alberto G. |last19=Pereira |first19=Renato C.|last20=Leal|first20=Camellia V. |last21=Hajdu |first21=Eduardo |last22=Asp |first22=Nils E. |last23=Gregoracci |first23=Gustavo B. |last24=Neumann-Leitão |first24=Sigrid |last25=Yager |first25=Patricia L. |last26=Francini-Filho |first26=Ronaldo B. |last27=Fróes |first27=Adriana |last28=Campeão |first28=Mariana |last29=Silva |first29=Bruno S.|last30=Moreira|first30=Ana P.B. |last31=Oliveira |first31=Louisi |last32=Soares |first32=Ana C. |last33=Araujo |first33=Lais |last34=Oliveira |first34=Nara L. |last35=Teixeira |first35=João B. |last36=Valle |first36=Rogerio A.B. |last37=Thompson |first37=Cristiane C. |last38=Rezende |first38=Carlos E. |last39=Thompson |first39=Fabiano L. |title=An extensive reef system at the Amazon River mouth |journal=[[Science Advances]] |date=1 April 2016 |volume=2 |issue=4 |article-number=e1501252 |doi=10.1126/sciadv.1501252 |language=en |pmc=4846441 |pmid=27152336 |bibcode=2016SciA....2E1252M}}</ref> The Amazon basin is the largest [[drainage basin]] in the world, with an area of approximately {{convert|7,000,000|km2|sp=us}}.<ref name="britannica-amazon"/> The portion of the river's drainage basin in Brazil alone is larger than any other river's basin. The Amazon enters Brazil with only one-fifth of the flow it finally discharges into the [[Atlantic Ocean]] yet already has a greater flow at this point than the discharge of any other river in the world.<ref name="sterling">Tom Sterling: ''Der Amazonas''. Time-Life Bücher 1979, 7th German Printing, p. 19.</ref><ref name=smith>{{cite book |last=Smith |first=Nigel J.H. |title=Amazon Sweet Sea: Land, Life, and Water at the River's Mouth |year=2003 |publisher=University of Texas Press |isbn=978-0-292-77770-5 |url=https://books.google.com/books?id=SywgnV96puYC&pg=PA1 |pages=1–2 |url-status=live |archive-url=https://web.archive.org/web/20150915123518/https://books.google.com/books?id=SywgnV96puYC&pg=PA1 |archive-date=15 September 2015 }}</ref> It has a recognized length of {{convert|6,400|km|mi|sp=us}}, but according to some reports, its length varies from {{convert|6,575|to|7,062|km|mi|sp=us}}.<ref name="Pinpointing the sources and measuring the lengths of the principal rivers of the world">{{cite journal|journal=International Journal of Digital Earth|doi=10.1080/17538940902746082|url=https://www.tandfonline.com/doi/full/10.1080/17538940902746082|title=Pinpointing the sources and measuring the lengths of the principal rivers of the world|last1=S.|first1=Liu|last2=P.|first2=Lu|last3=D.|first3= Liu|last4=P.|first4=Jin|last5=W.|first5=Wang|pages=80–87|volume=2|issue=1|date=2009 |bibcode=2009IJDE....2...80L |url-access=subscription}}</ref><ref name="Estudo do INPE indica que o rio Amazonas é 140 km mais extenso do que o Nilo">{{cite web|url=https://www.inpe.br/noticias/noticia.php?Cod_Noticia=1501|title=Estudo do INPE indica que o rio Amazonas é 140 km mais extenso do que o Nilo}}</ref><ref name="A New Survey of Sources of the Amazon">[https://www.researchgate.net/publication/294373863_A_New_Survey_of_Sources_of_the_Amazon/fulltext/5fea5b4aa6fdccdcb812e603/A-New-Survey-of-Sources-of-the-Amazon.pdf A New Survey of Sources of the Amazon] (PDF; 3,5 MB)</ref><ref name="The River Amazon water contribution to the Atlantic Ocean">{{cite journal|journal=Journal of Water Science|url=https://id.erudit.org/iderudit/044688ar|doi=10.7202/044688ar|title=The River Amazon water contribution to the Atlantic Ocean|last1=Jacques|first1=Callède|last2=Gérard|first2=Cochonneau|last3=Fabrício|first3=Vieira Alves|last4=Jean-Loup|first4=Guyot|last5=Valdemar|first5=Santos Guimarães|last6=Eurides|first6=De Oliveira|volume=23|number=3|date=2010|pages=247–273}}</ref>
-->
== Jeeagh er neesht ==
* [[Ard najooragh yn Amason]], 'sy Cholombey
* [[Yn Amason Pherooagh]] 'sy Pheroo
==Noteyn==
{{reflist|group=n|30em}}
==Imraaghyn==
{{reflist}}
{{gurneil eaghtyrys}}
{{DEFAULTSORT:Amason, Yn}}
{{bun}}
[[Ronney:Yn Amason| ]]
[[Ronney:Awintragh yn Amason]]
[[Ronney:Keyll liaghee yn Amason]]
[[Ronney:Awinyn ayns America Yiass]]
[[Ronney:Awinyn eddyrashoonagh ayns America Yiass]]
[[Ronney:Awinyn 'sy Cholombey]]
[[Ronney:Awinyn 'sy Pheroo]]
[[Ronney:Awinyn ayns Amapá]]
[[Ronney:Awinyn ayns Amazonas (steat Brasseelagh)]]
[[Ronney:Awinyn ayns Ard Loreto]]
[[Ronney:Awinyn ayns Pará]]
[[Ronney:Awinyn 'sy Vrasseel]]
2bo0t90rnlxpvdl2vjtxoyhmn0u33qt
Module:Convert
828
23832
392700
367576
2026-09-02T00:43:56Z
MacTire02
219
++
392700
Scribunto
text/plain
-- Convert a value from one unit of measurement to another.
-- Example: {{convert|123|lb|kg}} --> 123 pounds (56 kg)
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
local MINUS = '−' -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92)
local abs = math.abs
local floor = math.floor
local format = string.format
local log10 = math.log10
local ustring = mw.ustring
local ulen = ustring.len
local usub = ustring.sub
-- Configuration options to keep magic values in one location.
-- Conversion data and message text are defined in separate modules.
local config, maxsigfig
local numdot -- must be '.' or ',' or a character which works in a regex
local numsep, numsep_remove, numsep_remove2
local data_code, all_units
local text_code
local varname -- can be a code to use variable names that depend on value
local from_en_table -- to translate an output string of en digits to local language
local to_en_table -- to translate an input string of digits in local language to en
-- Use translation_table in convert/text to change the following.
local en_default -- true uses lang=en unless convert has lang=local or local digits
local group_method = 3 -- code for how many digits are in a group
local per_word = 'per' -- for units like "liters per kilometer"
local plural_suffix = 'yn' -- only other useful value is probably '' to disable plural unit names
local omitsep -- true to omit separator before local symbol/name
-- All units should be defined in the data module. However, to cater for quick changes
-- and experiments, any unknown unit is looked up in an extra data module, if it exists.
-- That module would be transcluded in only a small number of pages, so there should be
-- little server overhead from making changes, and changes should propagate quickly.
local extra_module -- name of module with extra units
local extra_units -- nil or table of extra units from extra_module
-- Some options in the invoking template can set variables used later in the module.
local currency_text -- for a user-defined currency symbol: {{convert|12|$/ha|$=€}} (euro replaces dollar)
local function from_en(text)
-- Input is a string representing a number in en digits with '.' decimal mark,
-- without digit grouping (which is done just after calling this).
-- Return the translation of the string with numdot and digits in local language.
if numdot ~= '.' then
text = text:gsub('%.', numdot)
end
if from_en_table then
text = text:gsub('%d', from_en_table)
end
return text
end
local function to_en(text)
-- Input is a string representing a number in the local language with
-- an optional numdot decimal mark and numsep digit grouping.
-- Return the translation of the string with '.' mark and en digits,
-- and no separators (they have to be removed here to handle cases like
-- numsep = '.' and numdot = ',' with input "1.234.567,8").
if to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
return text
end
local function decimal_mark(text)
-- Return ',' if text probably is using comma for decimal mark, or has no decimal mark.
-- Return '.' if text probably is using dot for decimal mark.
-- Otherwise return nothing (decimal mark not known).
if not text:find('[.,]') then return ',' end
text = text:gsub('^%-', ''):gsub('%+%d+/%d+$', ''):gsub('[Ee]%-?%d+$', '')
local decimal =
text:match('^0?([.,])%d+$') or
text:match('%d([.,])%d?%d?$') or
text:match('%d([.,])%d%d%d%d+$')
if decimal then return decimal end
if text:match('%.%d+%.') then return ',' end
if text:match('%,%d+,') then return '.' end
end
local add_warning, with_separator -- forward declarations
local function to_en_with_check(text, parms)
-- Version of to_en() for a wiki using numdot = ',' and numsep = '.' to check
-- text (an input number as a string) which might have been copied from enwiki.
-- For example, in '1.234' the '.' could be a decimal mark or a group separator.
-- From viwiki.
if to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if decimal_mark(text) == '.' then
local original = text
text = text:gsub(',', '') -- for example, interpret "1,234.5" as an enwiki value
if parms then
add_warning(parms, 0, 'cvt_enwiki_num', original, with_separator({}, text))
end
else
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
end
return text
end
local function omit_separator(id)
-- Return true if there should be no separator before id (a unit symbol or name).
-- For zhwiki, there should be no separator if id uses local characters.
-- The following kludge should be a sufficient test.
if omitsep then
if id:sub(1, 2) == '-{' then -- for "-{...}-" content language variant
return true
end
if id:byte() > 127 then
local first = usub(id, 1, 1)
if first ~= 'Å' and first ~= '°' and first ~= 'µ' then
return true
end
end
end
return id:sub(1, 1) == '/' -- no separator before units like "/ha"
end
local spell_module -- name of module that can spell numbers
local speller -- function from that module to handle spelling (set if needed)
local wikidata_module, wikidata_data_module -- names of Wikidata modules
local wikidata_code, wikidata_data -- exported tables from those modules (set if needed)
local function set_config(args)
-- Set configuration options from template #invoke or defaults.
config = args
maxsigfig = config.maxsigfig or 14 -- maximum number of significant figures
local data_module, text_module
local sandbox = config.sandbox and ('/' .. config.sandbox) or ''
data_module = "Module:Convert/data" .. sandbox
text_module = "Module:Convert/text" .. sandbox
extra_module = "Module:Convert/extra" .. sandbox
wikidata_module = "Module:Convert/wikidata" .. sandbox
wikidata_data_module = "Module:Convert/wikidata/data" .. sandbox
spell_module = "Module:ConvertNumeric"
data_code = mw.loadData(data_module)
text_code = mw.loadData(text_module)
all_units = data_code.all_units
local translation = text_code.translation_table
if translation then
numdot = translation.numdot
numsep = translation.numsep
if numdot == ',' and numsep == '.' then
if text_code.all_messages.cvt_enwiki_num then
to_en = to_en_with_check
end
end
if translation.group then
group_method = translation.group
end
if translation.per_word then
per_word = translation.per_word
end
if translation.plural_suffix then
plural_suffix = translation.plural_suffix
end
varname = translation.varname
from_en_table = translation.from_en
local use_workaround = true
if use_workaround then
-- 2013-07-05 workaround bug by making a copy of the required table.
-- mw.ustring.gsub fails with a table (to_en_table) as the replacement,
-- if the table is accessed via mw.loadData.
local source = translation.to_en
if source then
to_en_table = {}
for k, v in pairs(source) do
to_en_table[k] = v
end
end
else
to_en_table = translation.to_en
end
if translation.lang == 'en default' then
en_default = true -- for hiwiki
end
omitsep = translation.omitsep -- for zhwiki
end
numdot = config.numdot or numdot or '.' -- decimal mark before fractional digits
numsep = config.numsep or numsep or ',' -- group separator for numbers
-- numsep should be ',' or '.' or '' or ' ' or a Unicode character.
-- numsep_remove must work in a regex to identify separators to be removed.
if numsep ~= '' then
numsep_remove = (numsep == '.') and '%.' or numsep
end
if numsep ~= ',' and numdot ~= ',' then
numsep_remove2 = ',' -- so numbers copied from enwiki will work
end
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,
}
end
local function divide(numerator, denominator)
-- Return integers quotient, remainder resulting from dividing the two
-- given numbers, which should be unsigned integers.
local quotient, remainder = floor(numerator / denominator), numerator % denominator
if not (0 <= remainder and remainder < denominator) then
-- Floating point limits may need this, as in {{convert|160.02|Ym|ydftin}}.
remainder = 0
end
return quotient, remainder
end
local function split(text, delimiter)
-- Return a numbered table with fields from splitting text.
-- The delimiter is used in a regex without escaping (for example, '.' would fail).
-- Each field has any leading/trailing whitespace removed.
local t = {}
text = text .. delimiter -- to get last item
for item in text:gmatch('%s*(.-)%s*' .. delimiter) do
table.insert(t, item)
end
return t
end
local function strip(text)
-- If text is a string, return its content with no leading/trailing
-- whitespace. Otherwise return nil (a nil argument gives a nil result).
if type(text) == 'string' then
return text:match("^%s*(.-)%s*$")
end
end
local function table_len(t)
-- Return length (<100) of a numbered table to replace #t which is
-- documented to not work if t is accessed via mw.loadData().
for i = 1, 100 do
if t[i] == nil then
return i - 1
end
end
end
local function wanted_category(catkey, catsort, want_warning)
-- Return message category if it is wanted in current namespace,
-- otherwise return ''.
local cat
local title = mw.title.getCurrentTitle()
if title then
local nsdefault = '0' -- default namespace: '0' = article; '0,10' = article and template
local namespace = title.namespace
for _, v in ipairs(split(config.nscat or nsdefault, ',')) do
if namespace == tonumber(v) then
cat = text_code.all_categories[want_warning and 'warning' or catkey]
if catsort and catsort ~= '' and cat:sub(-2) == ']]' then
cat = cat:sub(1, -3) .. '|' .. mw.text.nowiki(usub(catsort, 1, 20)) .. ']]'
end
break
end
end
end
return cat or ''
end
local function message(parms, mcode, is_warning)
-- Return wikitext for an error message, including category if specified
-- for the message type.
-- mcode = numbered table specifying the message:
-- mcode[1] = 'cvt_xxx' (string used as a key to get message info)
-- mcode[2] = 'parm1' (string to replace '$1' if any in message)
-- mcode[3] = 'parm2' (string to replace '$2' if any in message)
-- mcode[4] = 'parm3' (string to replace '$3' if any in message)
local msg
if type(mcode) == 'table' then
if mcode[1] == 'cvt_no_output' then
-- Some errors should cause convert to output an empty string,
-- for example, for an optional field in an infobox.
return ''
end
msg = text_code.all_messages[mcode[1]]
end
parms.have_problem = true
local function subparm(fmt, ...)
local rep = {}
for i, v in ipairs({...}) do
rep['$' .. i] = v
end
return (fmt:gsub('$%d+', rep))
end
if msg then
local parts = {}
local regex, replace = msg.regex, msg.replace
for i = 1, 3 do
local limit = 40
local s = mcode[i + 1]
if s then
if regex and replace then
s = s:gsub(regex, replace)
limit = nil -- allow long "should be" messages
end
-- Escape user input so it does not break the message.
-- To avoid tags (like {{convert|1<math>23</math>|m}}) breaking
-- the mouseover title, any strip marker starting with char(127) is
-- replaced with '...' (text not needing i18n).
local append
local pos = s:find(string.char(127), 1, true)
if pos then
append = '...'
s = s:sub(1, pos - 1)
end
if limit and ulen(s) > limit then
s = usub(s, 1, limit)
append = '...'
end
s = mw.text.nowiki(s) .. (append or '')
else
s = '?'
end
parts['$' .. i] = s
end
local function ispreview()
-- Return true if a prominent message should be shown.
if parms.test == 'preview' or parms.test == 'nopreview' then
-- For testing, can preview a real message or simulate a preview
-- when running automated tests.
return parms.test == 'preview'
end
local success, revid = pcall(function ()
return (parms.frame):preprocess('{{REVISIONID}}') end)
return success and (revid == '')
end
local want_warning = is_warning and
not config.warnings and -- show unobtrusive warnings if config.warnings not configured
not msg.nowarn -- but use msg settings, not standard warning, if specified
local title = string.gsub(msg[1] or 'Missing message', '$%d+', parts)
local text = want_warning and '*' or msg[2] or 'Missing message'
local cat = wanted_category(msg[3], mcode[2], want_warning)
local anchor = msg[4] or ''
local fmtkey = ispreview() and 'cvt_format_preview' or
(want_warning and 'cvt_format2' or msg.format or 'cvt_format')
local fmt = text_code.all_messages[fmtkey] or 'convert: bug'
return subparm(fmt, title:gsub('"', '"'), text, cat, anchor)
end
return 'Convert internal error: unknown message'
end
function add_warning(parms, level, key, text1, text2) -- for forward declaration above
-- If enabled, add a warning that will be displayed after the convert result.
-- A higher level is more verbose: more kinds of warnings are displayed.
-- To reduce output noise, only the first warning is displayed.
if level <= (tonumber(config.warnings) or 1) then
if parms.warnings == nil then
parms.warnings = message(parms, { key, text1, text2 }, true)
end
end
end
local function spell_number(parms, inout, number, numerator, denominator)
-- Return result of spelling (number, numerator, denominator), or
-- return nil if spelling is not available or not supported for given text.
-- Examples (each value must be a string or nil):
-- number numerator denominator output
-- ------ --------- ----------- -------------------
-- "1.23" nil nil one point two three
-- "1" "2" "3" one and two thirds
-- nil "2" "3" two thirds
if not speller then
local function get_speller(module)
return require(module).spell_number
end
local success
success, speller = pcall(get_speller, spell_module)
if not success or type(speller) ~= 'function' then
add_warning(parms, 1, 'cvt_no_spell', 'spell')
return nil
end
end
local case
if parms.spell_upper == inout then
case = true
parms.spell_upper = nil -- only uppercase first word in a multiple unit
end
local sp = not parms.opt_sp_us
local adj = parms.opt_adjectival
return speller(number, numerator, denominator, case, sp, adj)
end
------------------------------------------------------------------------
-- BEGIN: Code required only for built-in units.
-- LATER: If need much more code, move to another module to simplify this module.
local function speed_of_sound(altitude)
-- This is for the Mach built-in unit of speed.
-- Return speed of sound in metres per second at given altitude in feet.
-- If no altitude given, use default (zero altitude = sea level).
-- Table gives speed of sound in miles per hour at various altitudes:
-- altitude = -17,499 to 402,499 feet
-- mach_table[a + 4] = s where
-- a = (altitude / 5000) rounded to nearest integer (-3 to 80)
-- s = speed of sound (mph) at that altitude
-- LATER: Should calculate result from an interpolation between the next
-- lower and higher altitudes in table, rather than rounding to nearest.
-- From: http://www.aerospaceweb.org/question/atmosphere/q0112.shtml
local mach_table = { -- a =
799.5, 787.0, 774.2, 761.207051, -- -3 to 0
748.0, 734.6, 721.0, 707.0, 692.8, 678.3, 663.5, 660.1, 660.1, 660.1, -- 1 to 10
660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6, -- 11 to 20
677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6, -- 21 to 30
737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.0, -- 31 to 40
695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7, -- 41 to 50
639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5, -- 51 to 60
614.4, 615.3, 616.7, 619.8, 623.4, 629.7, 635.0, 641.1, 650.6, 660.0, -- 61 to 70
672.5, 674.3, 676.1, 677.9, 679.7, 681.5, 683.3, 685.1, 686.8, 688.6, -- 71 to 80
}
altitude = altitude or 0
local a = (altitude < 0) and -altitude or altitude
a = floor(a / 5000 + 0.5)
if altitude < 0 then
a = -a
end
if a < -3 then
a = -3
elseif a > 80 then
a = 80
end
return mach_table[a + 4] * 0.44704 -- mph converted to m/s
end
-- END: Code required only for built-in units.
------------------------------------------------------------------------
local function add_style(parms, class)
-- Add selected template style to parms if not already present.
parms.templatestyles = parms.templatestyles or {}
if not parms.templatestyles[class] then
parms.templatestyles[class] = parms.frame:extensionTag({
name = 'templatestyles', args = { src = text_code.titles[class] }
})
end
end
local function get_styles(parms)
-- Return string of required template styles, empty if none.
if parms.templatestyles then
local t = {}
for _, v in pairs(parms.templatestyles) do
table.insert(t, v)
end
return table.concat(t)
end
return ''
end
local function get_range(word)
if word == "as" then
word = "and"
end
local ranges = text_code.ranges
return ranges.types[word] or ranges.types[ranges.aliases[word]]
end
local function check_mismatch(unit1, unit2)
-- If unit1 cannot be converted to unit2, return an error message table.
-- This allows conversion between units of the same type, and between
-- Nm (normally torque) and ftlb (energy), as in gun-related articles.
-- This works because Nm is the base unit (scale = 1) for both the
-- primary type (torque), and the alternate type (energy, where Nm = J).
-- A match occurs if the primary types are the same, or if unit1 matches
-- the alternate type of unit2, and vice versa. That provides a whitelist
-- of which conversions are permitted between normally incompatible types.
if unit1.utype == unit2.utype or
(unit1.utype == unit2.alttype and unit1.alttype == unit2.utype) then
return nil
end
return { 'cvt_mismatch', unit1.utype, unit2.utype }
end
local function override_from(out_table, in_table, fields)
-- Copy the specified fields from in_table to out_table, but do not
-- copy nil fields (keep any corresponding field in out_table).
for _, field in ipairs(fields) do
if in_table[field] then
out_table[field] = in_table[field]
end
end
end
local function shallow_copy(t)
-- Return a shallow copy of table t.
-- Do not need the features and overhead of the Scribunto mw.clone().
local result = {}
for k, v in pairs(t) do
result[k] = v
end
return result
end
local unit_mt = {
-- Metatable to get missing values for a unit that does not accept SI prefixes.
-- Warning: The boolean value 'false' is returned for any missing field
-- so __index is not called twice for the same field in a given unit.
__index = function (self, key)
local value
if key == 'name1' or key == 'sym_us' then
value = self.symbol
elseif key == 'name2' then
value = self.name1 .. plural_suffix
elseif key == 'name1_us' then
value = self.name1
if not rawget(self, 'name2_us') then
-- If name1_us is 'foot', do not make name2_us by appending plural_suffix.
self.name2_us = self.name2
end
elseif key == 'name2_us' then
local raw1_us = rawget(self, 'name1_us')
if raw1_us then
value = raw1_us .. plural_suffix
else
value = self.name2
end
elseif key == 'link' then
value = self.name1
else
value = false
end
rawset(self, key, value)
return value
end
}
local function prefixed_name(unit, name, index)
-- Return unit name with SI prefix inserted at correct position.
-- index = 1 (name1), 2 (name2), 3 (name1_us), 4 (name2_us).
-- The position is a byte (not character) index, so use Lua's sub().
local pos = rawget(unit, 'prefix_position')
if type(pos) == 'string' then
pos = tonumber(split(pos, ',')[index])
end
if pos then
return name:sub(1, pos - 1) .. unit.si_name .. name:sub(pos)
end
return unit.si_name .. name
end
local unit_prefixed_mt = {
-- Metatable to get missing values for a unit that accepts SI prefixes.
-- Before use, fields si_name, si_prefix must be defined.
-- The unit must define _symbol, _name1 and
-- may define _sym_us, _name1_us, _name2_us
-- (_sym_us, _name2_us may be defined for a language using sp=us
-- to refer to a variant unrelated to U.S. units).
__index = function (self, key)
local value
if key == 'symbol' then
value = self.si_prefix .. self._symbol
elseif key == 'sym_us' then
value = rawget(self, '_sym_us')
if value then
value = self.si_prefix .. value
else
value = self.symbol
end
elseif key == 'name1' then
value = prefixed_name(self, self._name1, 1)
elseif key == 'name2' then
value = rawget(self, '_name2')
if value then
value = prefixed_name(self, value, 2)
else
value = self.name1 .. plural_suffix
end
elseif key == 'name1_us' then
value = rawget(self, '_name1_us')
if value then
value = prefixed_name(self, value, 3)
else
value = self.name1
end
elseif key == 'name2_us' then
value = rawget(self, '_name2_us')
if value then
value = prefixed_name(self, value, 4)
elseif rawget(self, '_name1_us') then
value = self.name1_us .. plural_suffix
else
value = self.name2
end
elseif key == 'link' then
value = self.name1
else
value = false
end
rawset(self, key, value)
return value
end
}
local unit_per_mt = {
-- Metatable to get values for a per unit of form "x/y".
-- This is never called to determine a unit name or link because per units
-- are handled as a special case.
-- Similarly, the default output is handled elsewhere, and for a symbol
-- this is only called from get_default() for default_exceptions.
__index = function (self, key)
local value
if key == 'symbol' then
local per = self.per
local unit1, unit2 = per[1], per[2]
if unit1 then
value = unit1[key] .. '/' .. unit2[key]
else
value = '/' .. unit2[key]
end
elseif key == 'sym_us' then
value = self.symbol
elseif key == 'scale' then
local per = self.per
local unit1, unit2 = per[1], per[2]
value = (unit1 and unit1.scale or 1) * self.scalemultiplier / unit2.scale
else
value = false
end
rawset(self, key, value)
return value
end
}
local function make_per(unitcode, unit_table, ulookup)
-- Return true, t where t is a per unit with unit codes expanded to unit tables,
-- or return false, t where t is an error message table.
local result = {
unitcode = unitcode,
utype = unit_table.utype,
per = {}
}
override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' })
result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation
local prefix
for i, v in ipairs(unit_table.per) do
if i == 1 and v == '' then
-- First unit symbol can be empty; that gives a nil first unit table.
elseif i == 1 and text_code.currency[v] then
prefix = currency_text or v
else
local success, t = ulookup(v)
if not success then return false, t end
result.per[i] = t
end
end
local multiplier = unit_table.multiplier
if not result.utype then
-- Creating an automatic per unit.
local unit1 = result.per[1]
local utype = (unit1 and unit1.utype or prefix or '') .. '/' .. result.per[2].utype
local t = data_code.per_unit_fixups[utype]
if t then
if type(t) == 'table' then
utype = t.utype or utype
result.link = result.link or t.link
multiplier = multiplier or t.multiplier
else
utype = t
end
end
result.utype = utype
end
result.scalemultiplier = multiplier or 1
result.vprefix = prefix or false -- set to non-nil to avoid calling __index
return true, setmetatable(result, unit_per_mt)
end
local function lookup(parms, unitcode, what, utable, fails, depth)
-- Return true, t where t is a copy of the unit's converter table,
-- or return false, t where t is an error message table.
-- Parameter 'what' determines whether combination units are accepted:
-- 'no_combination' : single unit only
-- 'any_combination' : single unit or combination or output multiple
-- 'only_multiple' : single unit or output multiple only
-- Parameter unitcode is a symbol (like 'g'), with an optional SI prefix (like 'kg').
-- If, for example, 'kg' is in this table, that entry is used;
-- otherwise the prefix ('k') is applied to the base unit ('g').
-- If unitcode is a known combination code (and if allowed by what),
-- a table of output multiple unit tables is included in the result.
-- For compatibility with the old template, an underscore in a unitcode is
-- replaced with a space so usage like {{convert|350|board_feet}} works.
-- Wikignomes may also put two spaces or " " in combinations, so
-- replace underscore, " ", and multiple spaces with a single space.
utable = utable or parms.unittable or all_units
fails = fails or {}
depth = depth and depth + 1 or 1
if depth > 9 then
-- There are ways to mistakenly define units which result in infinite
-- recursion when lookup() is called. That gives a long delay and very
-- confusing error messages, so the depth parameter is used as a guard.
return false, { 'cvt_lookup', unitcode }
end
if unitcode == nil or unitcode == '' then
return false, { 'cvt_no_unit' }
end
unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ')
local function call_make_per(t)
return make_per(unitcode, t,
function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end
)
end
local t = utable[unitcode]
if t then
if t.shouldbe then
return false, { 'cvt_should_be', t.shouldbe }
end
if t.sp_us then
parms.opt_sp_us = true
end
local target = t.target -- nil, or unitcode is an alias for this target
if target then
local success, result = lookup(parms, target, what, utable, fails, depth)
if not success then return false, result end
override_from(result, t, { 'customary', 'default', 'link', 'symbol', 'symlink' })
local multiplier = t.multiplier
if multiplier then
result.multiplier = tostring(multiplier)
result.scale = result.scale * multiplier
end
return true, result
end
if t.per then
return call_make_per(t)
end
local combo = t.combination -- nil or a table of unitcodes
if combo then
local multiple = t.multiple
if what == 'no_combination' or (what == 'only_multiple' and not multiple) then
return false, { 'cvt_bad_unit', unitcode }
end
-- Recursively create a combination table containing the
-- converter table of each unitcode.
local result = { utype = t.utype, multiple = multiple, combination = {} }
local cvt = result.combination
for i, v in ipairs(combo) do
local success, t = lookup(parms, v, multiple and 'no_combination' or 'only_multiple', utable, fails, depth)
if not success then return false, t end
cvt[i] = t
end
return true, result
end
local result = shallow_copy(t)
result.unitcode = unitcode
if result.prefixes then
result.si_name = ''
result.si_prefix = ''
return true, setmetatable(result, unit_prefixed_mt)
end
return true, setmetatable(result, unit_mt)
end
local SIprefixes = text_code.SIprefixes
for plen = SIprefixes[1] or 2, 1, -1 do
-- Look for an SI prefix; should never occur with an alias.
-- Check for longer prefix first ('dam' is decametre).
-- SIprefixes[1] = prefix maximum #characters (as seen by mw.ustring.sub).
local prefix = usub(unitcode, 1, plen)
local si = SIprefixes[prefix]
if si then
local t = utable[usub(unitcode, plen+1)]
if t and t.prefixes then
local result = shallow_copy(t)
result.unitcode = unitcode
result.si_name = parms.opt_sp_us and si.name_us or si.name
result.si_prefix = si.prefix or prefix
result.scale = t.scale * 10 ^ (si.exponent * t.prefixes)
return true, setmetatable(result, unit_prefixed_mt)
end
end
end
-- Accept user-defined combinations like "acre+m2+ha" or "acre m2 ha" for output.
-- If '+' is used, each unit code can include a space, and any error is fatal.
-- If ' ' is used and if each space-separated word is a unit code, it is a combo,
-- but errors are not fatal so the unit code can be looked up as an extra unit.
local err_is_fatal
local combo = collection()
if unitcode:find('+', 1, true) then
err_is_fatal = true
for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do
if item ~= '' then
combo:add(item)
end
end
elseif unitcode:find('%s') then
for item in unitcode:gmatch('%S+') do
combo:add(item)
end
end
if combo.n > 1 then
local function lookup_combo()
if what == 'no_combination' or what == 'only_multiple' then
return false, { 'cvt_bad_unit', unitcode }
end
local result = { combination = {} }
local cvt = result.combination
for i, v in ipairs(combo) do
local success, t = lookup(parms, v, 'only_multiple', utable, fails, depth)
if not success then return false, t end
if i == 1 then
result.utype = t.utype
else
local mismatch = check_mismatch(result, t)
if mismatch then
return false, mismatch
end
end
cvt[i] = t
end
return true, result
end
local success, result = lookup_combo()
if success or err_is_fatal then
return success, result
end
end
-- Accept any unit with an engineering notation prefix like "e6cuft"
-- (million cubic feet), but not chained prefixes like "e3e6cuft",
-- and not if the unit is a combination or multiple,
-- and not if the unit has an offset or is a built-in.
-- Only en digits are accepted.
local exponent, baseunit = unitcode:match('^e(%d+)(.*)')
if exponent then
local engscale = text_code.eng_scales[exponent]
if engscale then
local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth)
if success and not (result.offset or result.builtin or result.engscale) then
result.unitcode = unitcode -- 'e6cuft' not 'cuft'
result.defkey = unitcode -- key to lookup default exception
result.engscale = engscale
result.scale = result.scale * 10 ^ tonumber(exponent)
return true, result
end
end
end
-- Look for x/y; split on right-most slash to get scale correct (x/y/z is x/y per z).
local top, bottom = unitcode:match('^(.-)/([^/]+)$')
if top and not unitcode:find('e%d') then
-- If valid, create an automatic per unit for an "x/y" unit code.
-- The unitcode must not include extraneous spaces.
-- Engineering notation (apart from at start and which has been stripped before here),
-- is not supported so do not make a per unit if find text like 'e3' in unitcode.
local success, result = call_make_per({ per = {top, bottom} })
if success then
return true, result
end
end
if not parms.opt_ignore_error and not get_range(unitcode) then
-- Want the "what links here" list for the extra_module to show only cases
-- where an extra unit is used, so do not require it if invoked from {{val}}
-- or if looking up a range word which cannot be a unit.
if not extra_units then
local success, extra = pcall(function () return require(extra_module).extra_units end)
if success and type(extra) == 'table' then
extra_units = extra
end
end
if extra_units then
-- A unit in one data table might refer to a unit in the other table, so
-- switch between them, relying on fails or depth to terminate loops.
if not fails[unitcode] then
fails[unitcode] = true
local other = (utable == all_units) and extra_units or all_units
local success, result = lookup(parms, unitcode, what, other, fails, depth)
if success then
return true, result
end
end
end
end
if to_en_table then
-- At fawiki it is common to translate all digits so a unit like "km2" becomes "km۲".
local en_code = ustring.gsub(unitcode, '%d', to_en_table)
if en_code ~= unitcode then
return lookup(parms, en_code, what, utable, fails, depth)
end
end
return false, { 'cvt_unknown', unitcode }
end
local function valid_number(num)
-- Return true if num is a valid number.
-- In Scribunto (different from some standard Lua), when expressed as a string,
-- overflow or other problems are indicated with text like "inf" or "nan"
-- which are regarded as invalid here (each contains "n").
if type(num) == 'number' and tostring(num):find('n', 1, true) == nil then
return true
end
end
local function hyphenated(name, parts)
-- Return a hyphenated form of given name (for adjectival usage).
-- The name may be linked and the target of the link must not be changed.
-- Hypothetical examples:
-- [[long ton|ton]] → [[long ton|ton]] (no change)
-- [[tonne|long ton]] → [[tonne|long-ton]]
-- [[metric ton|long ton]] → [[metric ton|long-ton]]
-- [[long ton]] → [[long ton|long-ton]]
-- Input can also have multiple links in a single name like:
-- [[United States customary units|U.S.]] [[US gallon|gallon]]
-- [[mile]]s per [[United States customary units|U.S.]] [[quart]]
-- [[long ton]]s per [[short ton]]
-- Assume that links cannot be nested (never like "[[abc[[def]]ghi]]").
-- This uses a simple and efficient procedure that works for most cases.
-- Some units (if used) would require more, and can later think about
-- adding a method to handle exceptions.
-- The procedure is to replace each space with a hyphen, but
-- not a space after ')' [for "(pre-1954 US) nautical mile"], and
-- not spaces immediately before '(' or in '(...)' [for cases like
-- "British thermal unit (ISO)" and "Calorie (International Steam Table)"].
if name:find(' ', 1, true) then
if parts then
local pos
if name:sub(1, 1) == '(' then
pos = name:find(')', 1, true)
if pos then
return name:sub(1, pos+1) .. name:sub(pos+2):gsub(' ', '-')
end
elseif name:sub(-1) == ')' then
pos = name:find('(', 1, true)
if pos then
return name:sub(1, pos-2):gsub(' ', '-') .. name:sub(pos-1)
end
end
return name:gsub(' ', '-')
end
parts = collection()
for before, item, after in name:gmatch('([^[]*)(%[%[[^[]*%]%])([^[]*)') do
if item:find(' ', 1, true) then
local prefix
local plen = item:find('|', 1, true)
if plen then
prefix = item:sub(1, plen)
item = item:sub(plen + 1, -3)
else
prefix = item:sub(1, -3) .. '|'
item = item:sub(3, -3)
end
item = prefix .. hyphenated(item, parts) .. ']]'
end
parts:add(before:gsub(' ', '-') .. item .. after:gsub(' ', '-'))
end
if parts.n == 0 then
-- No link like "[[...]]" was found in the original name.
parts:add(hyphenated(name, parts))
end
return table.concat(parts)
end
return name
end
local function hyphenated_maybe(parms, want_name, sep, id, inout)
-- Return s, f where
-- s = id, possibly modified
-- f = true if hyphenated
-- Possible modifications: hyphenate; prepend '-'; append mid text.
if id == nil or id == '' then
return ''
end
local mid = (inout == (parms.opt_flip and 'out' or 'in')) and parms.mid or ''
if want_name then
if parms.opt_adjectival then
return '-' .. hyphenated(id) .. mid, true
end
if parms.opt_add_s and id:sub(-1) ~= 's' then
id = id .. 's' -- for nowiki
end
end
return sep .. id .. mid
end
local function use_minus(text)
-- Return text with Unicode minus instead of '-', if present.
if text:sub(1, 1) == '-' then
return MINUS .. text:sub(2)
end
return text
end
local function digit_groups(parms, text, method)
-- Return a numbered table of groups of digits (left-to-right, in local language).
-- Parameter method is a number or nil:
-- 3 for 3-digit grouping (default), or
-- 2 for 3-then-2 grouping (only for digits before decimal mark).
local len_right
local len_left = text:find('.', 1, true)
if len_left then
len_right = #text - len_left
len_left = len_left - 1
else
len_left = #text
end
local twos = method == 2 and len_left > 5
local groups = collection()
local run = len_left
local n
if run < 4 or (run == 4 and parms.opt_comma5) then
if parms.opt_gaps then
n = run
else
n = #text
end
elseif twos then
n = run % 2 == 0 and 1 or 2
else
n = run % 3 == 0 and 3 or run % 3
end
while run > 0 do
groups:add(n)
run = run - n
n = (twos and run > 3) and 2 or 3
end
if len_right then
if groups.n == 0 then
groups:add(0)
end
if parms.opt_gaps and len_right > 3 then
local want4 = not parms.opt_gaps3 -- true gives no gap before trailing single digit
local isfirst = true
run = len_right
while run > 0 do
n = (want4 and run == 4) and 4 or (run > 3 and 3 or run)
if isfirst then
isfirst = false
groups[groups.n] = groups[groups.n] + 1 + n
else
groups:add(n)
end
run = run - n
end
else
groups[groups.n] = groups[groups.n] + 1 + len_right
end
end
local pos = 1
for i, length in ipairs(groups) do
groups[i] = from_en(text:sub(pos, pos + length - 1))
pos = pos + length
end
return groups
end
function with_separator(parms, text) -- for forward declaration above
-- Input text is a number in en digits with optional '.' decimal mark.
-- Return an equivalent, formatted for display:
-- with a custom decimal mark instead of '.', if wanted
-- with thousand separators inserted, if wanted
-- digits in local language
-- The given text is like '123' or '123.' or '12345.6789'.
-- The text has no sign (caller inserts that later, if necessary).
-- When using gaps, they are inserted before and after the decimal mark.
-- Separators are inserted only before the decimal mark.
-- A trailing dot (as in '123.') is removed because their use appears to
-- be accidental, and such a number should be shown as '123' or '123.0'.
-- It is useful for convert to suppress the dot so, for example, '4000.'
-- is a simple way of indicating that all the digits are significant.
if text:sub(-1) == '.' then
text = text:sub(1, -2)
end
if #text < 4 or parms.opt_nocomma or numsep == '' then
return from_en(text)
end
local groups = digit_groups(parms, text, group_method)
if parms.opt_gaps then
if groups.n <= 1 then
return groups[1] or ''
end
local nowrap = '<span style="white-space: nowrap">'
local gap = '<span style="margin-left: 0.25em">'
local close = '</span>'
return nowrap .. groups[1] .. gap .. table.concat(groups, close .. gap, 2, groups.n) .. close .. close
end
return table.concat(groups, numsep)
end
-- An input value like 1.23e12 is displayed using scientific notation (1.23×10¹²).
-- That also makes the output use scientific notation, except for small values.
-- In addition, very small or very large output values use scientific notation.
-- Use format(fmtpower, significand, '10', exponent) where each argument is a string.
local fmtpower = '%s<span style="margin:0 .15em 0 .25em">×</span>%s<sup>%s</sup>'
local function with_exponent(parms, show, exponent)
-- Return wikitext to display the implied value in scientific notation.
-- Input uses en digits; output uses digits in local language.
return format(fmtpower, with_separator(parms, show), from_en('10'), use_minus(from_en(tostring(exponent))))
end
local function make_sigfig(value, sigfig)
-- Return show, exponent that are equivalent to the result of
-- converting the number 'value' (where value >= 0) to a string,
-- rounded to 'sigfig' significant figures.
-- The returned items are:
-- show: a string of digits; no sign and no dot;
-- there is an implied dot before show.
-- exponent: a number (an integer) to shift the implied dot.
-- Resulting value = tonumber('.' .. show) * 10^exponent.
-- Examples:
-- make_sigfig(23.456, 3) returns '235', 2 (.235 * 10^2).
-- make_sigfig(0.0023456, 3) returns '235', -2 (.235 * 10^-2).
-- make_sigfig(0, 3) returns '000', 1 (.000 * 10^1).
if sigfig <= 0 then
sigfig = 1
elseif sigfig > maxsigfig then
sigfig = maxsigfig
end
if value == 0 then
return string.rep('0', sigfig), 1
end
local exp, fracpart = math.modf(log10(value))
if fracpart >= 0 then
fracpart = fracpart - 1
exp = exp + 1
end
local digits = format('%.0f', 10^(fracpart + sigfig))
if #digits > sigfig then
-- Overflow (for sigfig=3: like 0.9999 rounding to "1000"; need "100").
digits = digits:sub(1, sigfig)
exp = exp + 1
end
assert(#digits == sigfig, 'Bug: rounded number has wrong length')
return digits, exp
end
-- Fraction output format.
local fracfmt = {
{ -- Like {{frac}} (fraction slash).
'<span class="frac" role="math">{SIGN}<span class="num">{NUM}</span>⁄<span class="den">{DEN}</span></span>', -- 1/2
'<span class="frac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="num">{NUM}</span>⁄<span class="den">{DEN}</span></span>', -- 1+2/3
style = 'frac',
},
{ -- Like {{sfrac}} (stacked fraction, that is, horizontal bar).
'<span class="sfrac tion" role="math">{SIGN}<span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span>', -- 1//2
'<span class="sfrac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="tion"><span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span></span>', -- 1+2//3
style = 'sfrac',
},
}
local function format_fraction(parms, inout, negative, wholestr, numstr, denstr, do_spell, style)
-- Return wikitext for a fraction, possibly spelled.
-- Inputs use en digits and have no sign; output uses digits in local language.
local wikitext
if not style then
style = parms.opt_fraction_horizontal and 2 or 1
end
if wholestr == '' then
wholestr = nil
end
local substitute = {
SIGN = negative and MINUS or '',
WHOLE = wholestr and with_separator(parms, wholestr),
NUM = from_en(numstr),
DEN = from_en(denstr),
}
wikitext = fracfmt[style][wholestr and 2 or 1]:gsub('{(%u+)}', substitute)
if do_spell then
if negative then
if wholestr then
wholestr = '-' .. wholestr
else
numstr = '-' .. numstr
end
end
local s = spell_number(parms, inout, wholestr, numstr, denstr)
if s then
return s
end
end
add_style(parms, fracfmt[style].style)
return wikitext
end
local function format_number(parms, show, exponent, isnegative)
-- Parameter show is a string or a table containing strings.
-- Each string is a formatted number in en digits and optional '.' decimal mark.
-- A table represents a fraction: integer, numerator, denominator;
-- if a table is given, exponent must be nil.
-- Return t where t is a table with fields:
-- show = wikitext formatted to display implied value
-- (digits in local language)
-- is_scientific = true if show uses scientific notation
-- clean = unformatted show (possibly adjusted and with inserted '.')
-- (en digits)
-- sign = '' or MINUS
-- exponent = exponent (possibly adjusted)
-- The clean and exponent fields can be used to calculate the
-- rounded absolute value, if needed.
--
-- The value implied by the arguments is found from:
-- exponent is nil; and
-- show is a string of digits (no sign), with an optional dot;
-- show = '123.4' is value 123.4, '1234' is value 1234.0;
-- or:
-- exponent is an integer indicating where dot should be;
-- show is a string of digits (no sign and no dot);
-- there is an implied dot before show;
-- show does not start with '0';
-- show = '1234', exponent = 3 is value 0.1234*10^3 = 123.4.
--
-- The formatted result:
-- * Is for an output value and is spelled if wanted and possible.
-- * Includes a Unicode minus if isnegative and not spelled.
-- * Uses a custom decimal mark, if wanted.
-- * Has digits grouped where necessary, if wanted.
-- * Uses scientific notation if requested, or for very small or large values
-- (which forces result to not be spelled).
-- * Has no more than maxsigfig significant digits
-- (same as old template and {{#expr}}).
local xhi, xlo -- these control when scientific notation (exponent) is used
if parms.opt_scientific then
xhi, xlo = 4, 2 -- default for output if input uses e-notation
elseif parms.opt_scientific_always then
xhi, xlo = 0, 0 -- always use scientific notation (experimental)
else
xhi, xlo = 10, 4 -- default
end
local sign = isnegative and MINUS or ''
local maxlen = maxsigfig
local tfrac
if type(show) == 'table' then
tfrac = show
show = tfrac.wholestr
assert(exponent == nil, 'Bug: exponent given with fraction')
end
if not tfrac and not exponent then
local integer, dot, decimals = show:match('^(%d*)(%.?)(.*)')
if integer == '0' or integer == '' then
local zeros, figs = decimals:match('^(0*)([^0]?.*)')
if #figs == 0 then
if #zeros > maxlen then
show = '0.' .. zeros:sub(1, maxlen)
end
elseif #zeros >= xlo then
show = figs
exponent = -#zeros
elseif #figs > maxlen then
show = '0.' .. zeros .. figs:sub(1, maxlen)
end
elseif #integer >= xhi then
show = integer .. decimals
exponent = #integer
else
maxlen = maxlen + #dot
if #show > maxlen then
show = show:sub(1, maxlen)
end
end
end
if exponent then
local function zeros(n)
return string.rep('0', n)
end
if #show > maxlen then
show = show:sub(1, maxlen)
end
if exponent > xhi or exponent <= -xlo or (exponent == xhi and show ~= '1' .. zeros(xhi - 1)) then
-- When xhi, xlo = 10, 4 (the default), scientific notation is used if the
-- rounded value satisfies: value >= 1e9 or value < 1e-4 (1e9 = 0.1e10),
-- except if show is '1000000000' (1e9), for example:
-- {{convert|1000000000|m|m|sigfig=10}} → 1,000,000,000 metres (1,000,000,000 m)
local significand
if #show > 1 then
significand = show:sub(1, 1) .. '.' .. show:sub(2)
else
significand = show
end
return {
clean = '.' .. show,
exponent = exponent,
sign = sign,
show = sign .. with_exponent(parms, significand, exponent-1),
is_scientific = true,
}
end
if exponent >= #show then
show = show .. zeros(exponent - #show) -- result has no dot
elseif exponent <= 0 then
show = '0.' .. zeros(-exponent) .. show
else
show = show:sub(1, exponent) .. '.' .. show:sub(exponent+1)
end
end
local formatted_show
if tfrac then
show = tostring(tfrac.value) -- to set clean in returned table
formatted_show = format_fraction(parms, 'out', isnegative, tfrac.wholestr, tfrac.numstr, tfrac.denstr, parms.opt_spell_out)
else
if isnegative and show:match('^0.?0*$') then
sign = '' -- don't show minus if result is negative but rounds to zero
end
formatted_show = sign .. with_separator(parms, show)
if parms.opt_spell_out then
formatted_show = spell_number(parms, 'out', sign .. show) or formatted_show
end
end
return {
clean = show,
sign = sign,
show = formatted_show,
is_scientific = false, -- to avoid calling __index
}
end
local function extract_fraction(parms, text, negative)
-- If text represents a fraction, return
-- value, altvalue, show, denominator
-- where
-- value is a number (value of the fraction in argument text)
-- altvalue is an alternate interpretation of any fraction for the hands
-- unit where "12.1+3/4" means 12 hands 1.75 inches
-- show is a string (formatted text for display of an input value,
-- and is spelled if wanted and possible)
-- denominator is value of the denominator in the fraction
-- Otherwise, return nil.
-- Input uses en digits and '.' decimal mark (input has been translated).
-- Output uses digits in local language and local decimal mark, if any.
------------------------------------------------------------------------
-- Originally this function accepted x+y/z where x, y, z were any valid
-- numbers, possibly with a sign. For example '1.23e+2+1.2/2.4' = 123.5,
-- and '2-3/8' = 1.625. However, such usages were found to be errors or
-- misunderstandings, so since August 2014 the following restrictions apply:
-- x (if present) is an integer or has a single digit after decimal mark
-- y and z are unsigned integers
-- e-notation is not accepted
-- The overall number can start with '+' or '-' (so '12+3/4' and '+12+3/4'
-- and '-12-3/4' are valid).
-- Any leading negative sign is removed by the caller, so only inputs
-- like the following are accepted here (may have whitespace):
-- negative = false false true (there was a leading '-')
-- text = '2/3' '+2/3' '2/3'
-- text = '1+2/3' '+1+2/3' '1-2/3'
-- text = '12.3+1/2' '+12.3+1/2' '12.3-1/2'
-- Values like '12.3+1/2' are accepted, but are intended only for use
-- with the hands unit (not worth adding code to enforce that).
------------------------------------------------------------------------
local leading_plus, prefix, numstr, slashes, denstr =
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$')
if not leading_plus then
-- Accept a single U+2044 fraction slash because that may be pasted.
leading_plus, prefix, numstr, denstr =
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*⁄%s*(%d+)%s*$')
slashes = '/'
end
local numerator = tonumber(numstr)
local denominator = tonumber(denstr)
if numerator == nil or denominator == nil or (negative and leading_plus ~= '') then
return nil
end
local whole, wholestr
if prefix == '' then
wholestr = ''
whole = 0
else
-- Any prefix must be like '12+' or '12-' (whole number and fraction sign);
-- '12.3+' and '12.3-' are also accepted (single digit after decimal point)
-- because '12.3+1/2 hands' is valid (12 hands 3½ inches).
local num1, num2, frac_sign = prefix:match('^(%d+)(%.?%d?)%s*([+%-])$')
if num1 == nil then return nil end
if num2 == '' then -- num2 must be '' or like '.1' but not '.' or '.12'
wholestr = num1
else
if #num2 ~= 2 then return nil end
wholestr = num1 .. num2
end
if frac_sign ~= (negative and '-' or '+') then return nil end
whole = tonumber(wholestr)
if whole == nil then return nil end
end
local value = whole + numerator / denominator
if not valid_number(value) then return nil end
local altvalue = whole + numerator / (denominator * 10)
local style = #slashes -- kludge: 1 or 2 slashes can be used to select style
if style > 2 then style = 2 end
local wikitext = format_fraction(parms, 'in', negative, leading_plus .. wholestr, numstr, denstr, parms.opt_spell_in, style)
return value, altvalue, wikitext, denominator
end
local function extract_number(parms, text, another, no_fraction)
-- Return true, info if can extract a number from text,
-- where info is a table with the result,
-- or return false, t where t is an error message table.
-- Input can use en digits or digits in local language and can
-- have references at the end. Accepting references is intended
-- for use in infoboxes with a field for a value passed to convert.
-- Parameter another = true if the expected value is not the first.
-- Before processing, the input text is cleaned:
-- * Any thousand separators (valid or not) are removed.
-- * Any sign is replaced with '-' (if negative) or '' (otherwise).
-- That replaces Unicode minus with '-'.
-- If successful, the returned info table contains named fields:
-- value = a valid number
-- altvalue = a valid number, usually same as value but different
-- if fraction used (for hands unit)
-- singular = true if value is 1 or -1 (to use singular form of units)
-- clean = cleaned text with any separators and sign removed
-- (en digits and '.' decimal mark)
-- show = text formatted for output, possibly with ref strip markers
-- (digits in local language and custom decimal mark)
-- The resulting show:
-- * Is for an input value and is spelled if wanted and possible.
-- * Has a rounded value, if wanted.
-- * Has digits grouped where necessary, if wanted.
-- * If negative, a Unicode minus is used; otherwise the sign is
-- '+' (if the input text used '+'), or is '' (if no sign in input).
text = strip(text or '')
local reference
local pos = text:find('\127', 1, true)
if pos then
local before = text:sub(1, pos - 1)
local remainder = text:sub(pos)
local refs = {}
while #remainder > 0 do
local ref, spaces
ref, spaces, remainder = remainder:match('^(\127[^\127]*UNIQ[^\127]*%-ref[^\127]*\127)(%s*)(.*)')
if ref then
table.insert(refs, ref)
else
refs = {}
break
end
end
if #refs > 0 then
text = strip(before)
reference = table.concat(refs)
end
end
local clean = to_en(text, parms)
if clean == '' then
return false, { another and 'cvt_no_num2' or 'cvt_no_num' }
end
local isnegative, propersign = false, '' -- most common case
local singular, show, denominator
local value = tonumber(clean)
local altvalue
if value then
local sign = clean:sub(1, 1)
if sign == '+' or sign == '-' then
propersign = (sign == '+') and '+' or MINUS
clean = clean:sub(2)
end
if value < 0 then
isnegative = true
value = -value
end
else
local valstr
for _, prefix in ipairs({ '-', MINUS, '−' }) do
-- Including '-' sets isnegative in case input is a fraction like '-2-3/4'.
local plen = #prefix
if clean:sub(1, plen) == prefix then
valstr = clean:sub(plen + 1)
if valstr:match('^%s') then -- "- 1" is invalid but "-1 - 1/2" is ok
return false, { 'cvt_bad_num', text }
end
break
end
end
if valstr then
isnegative = true
propersign = MINUS
clean = valstr
value = tonumber(clean)
end
if value == nil then
if not no_fraction then
value, altvalue, show, denominator = extract_fraction(parms, clean, isnegative)
end
if value == nil then
return false, { 'cvt_bad_num', text }
end
if value <= 1 then
singular = true -- for example, "½ mile" or "one half mile" (singular unit)
end
end
end
if not valid_number(value) then -- for example, "1e310" may overflow
return false, { 'cvt_invalid_num' }
end
if show == nil then
-- clean is a non-empty string with no spaces, and does not represent a fraction,
-- and value = tonumber(clean) is a number >= 0.
-- If the input uses e-notation, show will be displayed using a power of ten, but
-- we use the number as given so it might not be normalized scientific notation.
-- The input value is spelled if specified so any e-notation is ignored;
-- that allows input like 2e6 to be spelled as "two million" which works
-- because the spell module converts '2e6' to '2000000' before spelling.
local function rounded(value, default, exponent)
local precision = parms.opt_ri
if precision then
local fmt = '%.' .. format('%d', precision) .. 'f'
local result = fmt:format(tonumber(value) + 2e-14) -- fudge for some common cases of bad rounding
if not exponent then
singular = (tonumber(result) == 1)
end
return result
end
return default
end
singular = (value == 1)
local scientific
local significand, exponent = clean:match('^([%d.]+)[Ee]([+%-]?%d+)')
if significand then
show = with_exponent(parms, rounded(significand, significand, exponent), exponent)
scientific = true
else
show = with_separator(parms, rounded(value, clean))
end
show = propersign .. show
if parms.opt_spell_in then
show = spell_number(parms, 'in', propersign .. rounded(value, clean)) or show
scientific = false
end
if scientific then
parms.opt_scientific = true
end
end
if isnegative and (value ~= 0) then
value = -value
altvalue = -(altvalue or value)
end
return true, {
value = value,
altvalue = altvalue or value,
singular = singular,
clean = clean,
show = show .. (reference or ''),
denominator = denominator,
}
end
local function get_number(text)
-- Return v, f where:
-- v = nil (text is not a number)
-- or
-- v = value of text (text is a number)
-- f = true if value is an integer
-- Input can use en digits or digits in local language or separators,
-- but no Unicode minus, and no fraction.
if text then
local number = tonumber(to_en(text))
if number then
local _, fracpart = math.modf(number)
return number, (fracpart == 0)
end
end
end
local function gcd(a, b)
-- Return the greatest common denominator for the given values,
-- which are known to be positive integers.
if a > b then
a, b = b, a
end
if a <= 0 then
return b
end
local r = b % a
if r <= 0 then
return a
end
if r == 1 then
return 1
end
return gcd(r, a)
end
local function fraction_table(value, denominator)
-- Return value as a string or a table:
-- * If result is a string, there is no fraction, and the result
-- is value formatted as a string of en digits.
-- * If result is a table, it represents a fraction with named fields:
-- wholestr, numstr, denstr (strings of en digits for integer, numerator, denominator).
-- The result is rounded to the nearest multiple of (1/denominator).
-- If the multiple is zero, no fraction is included.
-- No fraction is included if value is very large as the fraction would
-- be unhelpful, particularly if scientific notation is required.
-- Input value is a non-negative number.
-- Input denominator is a positive integer for the desired fraction.
if value <= 0 then
return '0'
end
if denominator <= 0 or value > 1e8 then
return format('%.2f', value)
end
local integer, decimals = math.modf(value)
local numerator = floor((decimals * denominator) +
0.5 + 2e-14) -- add fudge for some common cases of bad rounding
if numerator >= denominator then
integer = integer + 1
numerator = 0
end
local wholestr = tostring(integer)
if numerator > 0 then
local div = gcd(numerator, denominator)
if div > 1 then
numerator = numerator / div
denominator = denominator / div
end
return {
wholestr = (integer > 0) and wholestr or '',
numstr = tostring(numerator),
denstr = tostring(denominator),
value = value,
}
end
return wholestr
end
local function preunits(count, preunit1, preunit2)
-- If count is 1:
-- ignore preunit2
-- return p1
-- else:
-- preunit1 is used for preunit2 if the latter is empty
-- return p1, p2
-- where:
-- p1 is text to insert before the input unit
-- p2 is text to insert before the output unit
-- p1 or p2 may be nil to mean "no preunit"
-- Using '+' gives output like "5+ feet" (no space before, but space after).
local function withspace(text, wantboth)
-- Return text with space before and, if wantboth, after.
-- However, no space is added if there is a space or ' ' or '-'
-- at that position ('-' is for adjectival text).
-- There is also no space if text starts with '&'
-- (e.g. '°' would display a degree symbol with no preceding space).
local char = text:sub(1, 1)
if char == '&' then
return text -- an html entity can be used to specify the exact display
end
if not (char == ' ' or char == '-' or char == '+') then
text = ' ' .. text
end
if wantboth then
char = text:sub(-1, -1)
if not (char == ' ' or char == '-' or text:sub(-6, -1) == ' ') then
text = text .. ' '
end
end
return text
end
local PLUS = '+ '
preunit1 = preunit1 or ''
local trim1 = strip(preunit1)
if count == 1 then
if trim1 == '' then
return nil
end
if trim1 == '+' then
return PLUS
end
return withspace(preunit1, true)
end
preunit1 = withspace(preunit1)
preunit2 = preunit2 or ''
local trim2 = strip(preunit2)
if trim1 == '+' then
if trim2 == '' or trim2 == '+' then
return PLUS, PLUS
end
preunit1 = PLUS
end
if trim2 == '' then
if trim1 == '' then
return nil, nil
end
preunit2 = preunit1
elseif trim2 == '+' then
preunit2 = PLUS
elseif trim2 == ' ' then -- trick to make preunit2 empty
preunit2 = nil
else
preunit2 = withspace(preunit2)
end
return preunit1, preunit2
end
local function range_text(range, want_name, parms, before, after, inout, options)
-- Return before .. rtext .. after
-- where rtext is the text that separates two values in a range.
local rtext, adj_text, exception
options = options or {}
if type(range) == 'table' then
-- Table must specify range text for ('off' and 'on') or ('input' and 'output'),
-- and may specify range text for 'adj=on',
-- and may specify exception = true.
rtext = range[want_name and 'off' or 'on'] or
range[((inout == 'in') == (parms.opt_flip == true)) and 'output' or 'input']
adj_text = range['adj']
exception = range['exception']
else
rtext = range
end
if parms.opt_adjectival then
if want_name or (exception and parms.abbr_org == 'on') then
rtext = adj_text or rtext:gsub(' ', '-'):gsub(' ', '-')
end
end
if rtext == '–' and (options.spaced or after:sub(1, #MINUS) == MINUS) then
rtext = ' – '
end
return before .. rtext .. after
end
local function get_composite(parms, iparm, in_unit_table)
-- Look for a composite input unit. For example, {{convert|1|yd|2|ft|3|in}}
-- would result in a call to this function with
-- iparm = 3 (parms[iparm] = "2", just after the first unit)
-- in_unit_table = (unit table for "yd"; contains value 1 for number of yards)
-- Return true, iparm, unit where
-- iparm = index just after the composite units (7 in above example)
-- unit = composite unit table holding all input units,
-- or return true if no composite unit is present in parms,
-- or return false, t where t is an error message table.
local default, subinfo
local composite_units, count = { in_unit_table }, 1
local fixups = {}
local total = in_unit_table.valinfo[1].value
local subunit = in_unit_table
while subunit.subdivs do -- subdivs is nil or a table of allowed subdivisions
local subcode = strip(parms[iparm+1])
local subdiv = subunit.subdivs[subcode] or subunit.subdivs[(all_units[subcode] or {}).target]
if not subdiv then
break
end
local success
success, subunit = lookup(parms, subcode, 'no_combination')
if not success then return false, subunit end -- should never occur
success, subinfo = extract_number(parms, parms[iparm])
if not success then return false, subinfo end
iparm = iparm + 2
subunit.inout = 'in'
subunit.valinfo = { subinfo }
-- Recalculate total as a number of subdivisions.
-- subdiv[1] = number of subdivisions per previous unit (integer > 1).
total = total * subdiv[1] + subinfo.value
if not default then -- set by the first subdiv with a default defined
default = subdiv.default
end
count = count + 1
composite_units[count] = subunit
if subdiv.unit or subdiv.name then
fixups[count] = { unit = subdiv.unit, name = subdiv.name, valinfo = subunit.valinfo }
end
end
if count == 1 then
return true -- no error and no composite unit
end
for i, fixup in pairs(fixups) do
local unit = fixup.unit
local name = fixup.name
if not unit or (count > 2 and name) then
composite_units[i].fixed_name = name
else
local success, alternate = lookup(parms, unit, 'no_combination')
if not success then return false, alternate end -- should never occur
alternate.inout = 'in'
alternate.valinfo = fixup.valinfo
composite_units[i] = alternate
end
end
return true, iparm, {
utype = in_unit_table.utype,
scale = subunit.scale, -- scale of last (least significant) unit
valinfo = { { value = total, clean = subinfo.clean, denominator = subinfo.denominator } },
composite = composite_units,
default = default or in_unit_table.default
}
end
local function translate_parms(parms, kv_pairs)
-- Update fields in parms by translating each key:value in kv_pairs to terms
-- used by this module (may involve translating from local language to English).
-- Also, checks are performed which may display warnings, if enabled.
-- Return true if successful or return false, t where t is an error message table.
currency_text = nil -- local testing can hold module in memory; must clear globals
if kv_pairs.adj and kv_pairs.sing then
-- For enwiki (before translation), warn if attempt to use adj and sing
-- as the latter is a deprecated alias for the former.
if kv_pairs.adj ~= kv_pairs.sing and kv_pairs.sing ~= '' then
add_warning(parms, 1, 'cvt_unknown_option', 'sing=' .. kv_pairs.sing)
end
kv_pairs.sing = nil
end
kv_pairs.comma = kv_pairs.comma or config.comma -- for plwiki who want default comma=5
for loc_name, loc_value in pairs(kv_pairs) do
local en_name = text_code.en_option_name[loc_name]
if en_name then
local en_value = text_code.en_option_value[en_name]
if en_value == 'INTEGER' then -- altitude_ft, altitude_m, frac, sigfig
en_value = nil
if loc_value == '' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
else
local minimum
local number, is_integer = get_number(loc_value)
if en_name == 'sigfig' then
minimum = 1
elseif en_name == 'frac' then
minimum = 2
if number and number < 0 then
parms.opt_fraction_horizontal = true
number = -number
end
else
minimum = -1e6
end
if number and is_integer and number >= minimum then
en_value = number
else
local m
if en_name == 'frac' then
m = 'cvt_bad_frac'
elseif en_name == 'sigfig' then
m = 'cvt_bad_sigfig'
else
m = 'cvt_bad_altitude'
end
add_warning(parms, 1, m, loc_name .. '=' .. loc_value)
end
end
elseif en_value == 'TEXT' then -- $, input, qid, qual, stylein, styleout, tracking
en_value = loc_value ~= '' and loc_value or nil -- accept non-empty user text with no validation
if not en_value and (en_name == '$' or en_name == 'qid' or en_name == 'qual') then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
elseif en_name == '$' then
-- Value should be a single character like "€" for the euro currency symbol, but anything is accepted.
currency_text = (loc_value == 'euro') and '€' or loc_value
elseif en_name == 'input' then
-- May have something like {{convert|input=}} (empty input) if source is an infobox
-- with optional fields. In that case, want to output nothing rather than an error.
parms.input_text = loc_value -- keep input because parms.input is nil if loc_value == ''
end
else
en_value = en_value[loc_value]
if en_value and en_value:sub(-1) == '?' then
en_value = en_value:sub(1, -2)
add_warning(parms, -1, 'cvt_deprecated', loc_name .. '=' .. loc_value)
end
if en_value == nil then
if loc_value == '' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
end
elseif en_value == '' then
en_value = nil -- an ignored option like adj=off
elseif type(en_value) == 'string' and en_value:sub(1, 4) == 'opt_' then
for _, v in ipairs(split(en_value, ',')) do
local lhs, rhs = v:match('^(.-)=(.+)$')
if rhs then
parms[lhs] = tonumber(rhs) or rhs
else
parms[v] = true
end
end
en_value = nil
end
end
parms[en_name] = en_value
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
end
end
local abbr_entered = parms.abbr
local cfg_abbr = config.abbr
if cfg_abbr then
-- Don't warn if invalid because every convert would show that warning.
if cfg_abbr == 'on always' then
parms.abbr = 'on'
elseif cfg_abbr == 'off always' then
parms.abbr = 'off'
elseif parms.abbr == nil then
if cfg_abbr == 'on default' then
parms.abbr = 'on'
elseif cfg_abbr == 'off default' then
parms.abbr = 'off'
end
end
end
if parms.abbr then
if parms.abbr == 'unit' then
parms.abbr = 'on'
parms.number_word = true
end
parms.abbr_org = parms.abbr -- original abbr, before any flip
elseif parms.opt_hand_hh then
parms.abbr_org = 'on'
parms.abbr = 'on'
else
parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name)
end
if parms.opt_order_out then
-- Disable options that do not work in a useful way with order=out.
parms.opt_flip = nil -- override adj=flip
parms.opt_spell_in = nil
parms.opt_spell_out = nil
parms.opt_spell_upper = nil
end
if parms.opt_spell_out and not abbr_entered then
parms.abbr = 'off' -- should show unit name when spelling the output value
end
if parms.opt_flip then
local function swap_in_out(option)
local value = parms[option]
if value == 'in' then
parms[option] = 'out'
elseif value == 'out' then
parms[option] = 'in'
end
end
swap_in_out('abbr')
swap_in_out('lk')
if parms.opt_spell_in and not parms.opt_spell_out then
-- For simplicity, and because it does not appear to be needed,
-- user cannot set an option to spell the output only.
parms.opt_spell_in = nil
parms.opt_spell_out = true
end
end
if parms.opt_spell_upper then
parms.spell_upper = parms.opt_flip and 'out' or 'in'
end
if parms.opt_table or parms.opt_tablecen then
if abbr_entered == nil and parms.lk == nil then
parms.opt_values = true
end
parms.table_align = parms.opt_table and 'right' or 'center'
end
if parms.table_align or parms.opt_sortable_on then
parms.need_table_or_sort = true
end
local disp_joins = text_code.disp_joins
local default_joins = disp_joins['b']
parms.join_between = default_joins[3] or '; '
local disp = parms.disp
if disp == nil then -- special case for the most common setting
parms.joins = default_joins
elseif disp == 'x' then
-- Later, parms.joins is set from the input parameters.
else
-- Old template does this.
local abbr = parms.abbr
if disp == 'slash' then
if abbr_entered == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
disp = 'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
parms.joins = disp_joins[disp] or default_joins
parms.join_between = parms.joins[3] or parms.join_between
parms.wantname = parms.joins.wantname
end
if (en_default and not parms.opt_lang_local and (parms[1] or ''):find('%d')) or parms.opt_lang_en then
from_en_table = nil
end
if en_default and from_en_table then
-- For hiwiki: localized symbol/name is defined with the US symbol/name field,
-- and is used if output uses localized numbers.
parms.opt_sp_us = true
end
return true
end
local function get_values(parms)
-- If successful, update parms and return true, v, i where
-- v = table of input values
-- i = index to next entry in parms after those processed here
-- or return false, t where t is an error message table.
local valinfo = collection() -- numbered table of input values
local range = collection() -- numbered table of range items (having, for example, 2 range items requires 3 input values)
local had_nocomma -- true if removed "nocomma" kludge from second parameter (like "tonocomma")
local parm2 = strip(parms[2])
if parm2 and parm2:sub(-7, -1) == 'nocomma' then
parms[2] = strip(parm2:sub(1, -8))
parms.opt_nocomma = true
had_nocomma = true
end
local function extractor(i)
-- If the parameter is not a value, try unpacking it as a range ("1-23" for "1 to 23").
-- However, "-1-2/3" is a negative fraction (-1⅔), so it must be extracted first.
-- Do not unpack a parameter if it is like "3-1/2" which is sometimes incorrectly
-- used instead of "3+1/2" (and which should not be interpreted as "3 to ½").
-- Unpacked items are inserted into the parms table.
-- The tail recursion allows combinations like "1x2 to 3x4".
local valstr = strip(parms[i]) -- trim so any '-' as a negative sign will be at start
local success, result = extract_number(parms, valstr, i > 1)
if not success and valstr and i < 20 then -- check i to limit abuse
local lhs, sep, rhs = valstr:match('^(%S+)%s+(%S+)%s+(%S.*)')
if lhs and not (sep == '-' and rhs:match('/')) then
if sep:find('%d') then
return success, result -- to reject {{convert|1 234 567|m}} with a decent message (en only)
end
parms[i] = rhs
table.insert(parms, i, sep)
table.insert(parms, i, lhs)
return extractor(i)
end
if not valstr:match('%-.*/') then
for _, sep in ipairs(text_code.ranges.words) do
local start, stop = valstr:find(sep, 2, true) -- start at 2 to skip any negative sign for range '-'
if start then
parms[i] = valstr:sub(stop + 1)
table.insert(parms, i, sep)
table.insert(parms, i, valstr:sub(1, start - 1))
return extractor(i)
end
end
end
end
return success, result
end
local i = 1
local is_change
while true do
local success, info = extractor(i) -- need to set parms.opt_nocomma before calling this
if not success then return false, info end
i = i + 1
if is_change then
info.is_change = true -- value is after "±" and so is a change (significant for range like {{convert|5|±|5|°C}})
is_change = nil
end
valinfo:add(info)
local range_item = get_range(strip(parms[i]))
if not range_item then
break
end
i = i + 1
range:add(range_item)
if type(range_item) == 'table' then
-- For range "x", if append unit to some values, append it to all.
parms.in_range_x = parms.in_range_x or range_item.in_range_x
parms.out_range_x = parms.out_range_x or range_item.out_range_x
parms.abbr_range_x = parms.abbr_range_x or range_item.abbr_range_x
is_change = range_item.is_range_change
end
end
if range.n > 0 then
if range.n > 30 then -- limit abuse, although 4 is a more likely upper limit
return false, { 'cvt_invalid_num' } -- misleading message but it will do
end
parms.range = range
elseif had_nocomma then
return false, { 'cvt_unknown', parm2 }
end
return true, valinfo, i
end
local function simple_get_values(parms)
-- If input is like "{{convert|valid_value|valid_unit|...}}",
-- return true, i, in_unit, in_unit_table
-- i = index in parms of what follows valid_unit, if anything.
-- The valid_value is not negative and does not use a fraction, and
-- no options requiring further processing of the input are used.
-- Otherwise, return nothing or return false, parm1 for caller to interpret.
-- Testing shows this function is successful for 96% of converts in articles,
-- and that on average it speeds up converts by 8%.
local clean = to_en(strip(parms[1] or ''), parms)
if parms.opt_ri or parms.opt_spell_in or #clean > 10 or not clean:match('^[0-9.]+$') then
return false, clean
end
local value = tonumber(clean)
if not value then return end
local info = {
value = value,
altvalue = value,
singular = (value == 1),
clean = clean,
show = with_separator(parms, clean),
}
local in_unit = strip(parms[2])
local success, in_unit_table = lookup(parms, in_unit, 'no_combination')
if not success then return end
in_unit_table.valinfo = { info }
return true, 3, in_unit, in_unit_table
end
local function wikidata_call(parms, operation, ...)
-- Return true, s where s is the result of a Wikidata operation,
-- or return false, t where t is an error message table.
local function worker(...)
wikidata_code = wikidata_code or require(wikidata_module)
wikidata_data = wikidata_data or mw.loadData(wikidata_data_module)
return wikidata_code[operation](wikidata_data, ...)
end
local success, status, result = pcall(worker, ...)
if success then
return status, result
end
if parms.opt_sortable_debug then
-- Use debug=yes to crash if an error while accessing Wikidata.
error('Error accessing Wikidata: ' .. status, 0)
end
return false, { 'cvt_wd_fail' }
end
local function get_parms(parms, args)
-- If successful, update parms and return true, unit where
-- parms is a table of all arguments passed to the template
-- converted to named arguments, and
-- unit is the input unit table;
-- or return false, t where t is an error message table.
-- For special processing (not a convert), can also return
-- true, wikitext where wikitext is the final result.
-- The returned input unit table may be for a fake unit using the specified
-- unit code as the symbol and name, and with bad_mcode = message code table.
-- MediaWiki removes leading and trailing whitespace from the values of
-- named arguments. However, the values of numbered arguments include any
-- whitespace entered in the template, and whitespace is used by some
-- parameters (example: the numbered parameters associated with "disp=x").
local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it
for k, v in pairs(args) do
if type(k) == 'number' or k == 'test' then -- parameter "test" is reserved for testing and is not translated
parms[k] = v
else
kv_pairs[k] = v
end
end
if parms.test == 'wikidata' then
local ulookup = function (ucode)
-- Use empty table for parms so it does not accumulate results when used repeatedly.
return lookup({}, ucode, 'no_combination')
end
return wikidata_call(parms, '_listunits', ulookup)
end
local success, msg = translate_parms(parms, kv_pairs)
if not success then return false, msg end
if parms.input then
success, msg = wikidata_call(parms, '_adjustparameters', parms, 1)
if not success then return false, msg end
end
local success, i, in_unit, in_unit_table = simple_get_values(parms)
if not success then
if type(i) == 'string' and i:match('^NNN+$') then
-- Some infoboxes have examples like {{convert|NNN|m}} (3 or more "N").
-- Output an empty string for these.
return false, { 'cvt_no_output' }
end
local valinfo
success, valinfo, i = get_values(parms)
if not success then return false, valinfo end
in_unit = strip(parms[i])
i = i + 1
success, in_unit_table = lookup(parms, in_unit, 'no_combination')
if not success then
in_unit = in_unit or ''
if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}})
in_unit_table = '' -- suppress error message and prevent processing of output unit
end
in_unit_table = setmetatable({
symbol = in_unit, name2 = in_unit, utype = in_unit,
scale = 1, default = '', defkey = '', linkey = '',
bad_mcode = in_unit_table }, unit_mt)
end
in_unit_table.valinfo = valinfo
end
if parms.test == 'msg' then
-- Am testing the messages produced when no output unit is specified, and
-- the input unit has a missing or invalid default.
-- Set two units for testing that.
-- LATER: Remove this code.
if in_unit == 'chain' then
in_unit_table.default = nil -- no default
elseif in_unit == 'rd' then
in_unit_table.default = "ft!X!m" -- an invalid expression
end
end
in_unit_table.inout = 'in' -- this is an input unit
if not parms.range then
local success, inext, composite_unit = get_composite(parms, i, in_unit_table)
if not success then return false, inext end
if composite_unit then
in_unit_table = composite_unit
i = inext
end
end
if in_unit_table.builtin == 'mach' then
-- As with old template, a number following Mach as the input unit is the altitude.
-- That is deprecated: should use altitude_ft=NUMBER or altitude_m=NUMBER.
local success, info
success = tonumber(parms[i]) -- this will often work and will give correct result for values like 2e4 without forcing output scientific notation
if success then
info = { value = success }
else
success, info = extract_number(parms, parms[i], false, true)
end
if success then
i = i + 1
in_unit_table.altitude = info.value
end
end
local word = strip(parms[i])
i = i + 1
local precision, is_bad_precision
local function set_precision(text)
local number, is_integer = get_number(text)
if number then
if is_integer then
precision = number
else
precision = text
is_bad_precision = true
end
return true -- text was used for precision, good or bad
end
end
if word and not set_precision(word) then
parms.out_unit = parms.out_unit or word
if set_precision(strip(parms[i])) then
i = i + 1
end
end
if parms.opt_adj_mid then
word = parms[i]
i = i + 1
if word then -- mid-text words
if word:sub(1, 1) == '-' then
parms.mid = word
else
parms.mid = ' ' .. word
end
end
end
if parms.opt_one_preunit then
parms[parms.opt_flip and 'preunit2' or 'preunit1'] = preunits(1, parms[i])
i = i + 1
end
if parms.disp == 'x' then
-- Following is reasonably compatible with the old template.
local first = parms[i] or ''
local second = parms[i+1] or ''
i = i + 2
if strip(first) == '' then -- user can enter ' ' rather than ' ' to avoid the default
first = ' [ ' .. first
second = ' ]' .. second
end
parms.joins = { first, second }
elseif parms.opt_two_preunits then
local p1, p2 = preunits(2, parms[i], parms[i+1])
i = i + 2
if parms.preunit1 then
-- To simplify documentation, allow unlikely use of adj=pre with disp=preunit
-- (however, an output unit must be specified with adj=pre and with disp=preunit).
parms.preunit1 = parms.preunit1 .. p1
parms.preunit2 = p2
else
parms.preunit1, parms.preunit2 = p1, p2
end
end
if precision == nil then
if set_precision(strip(parms[i])) then
i = i + 1
end
end
if is_bad_precision then
add_warning(parms, 1, 'cvt_bad_prec', precision)
else
parms.precision = precision
end
for j = i, i + 3 do
local parm = parms[j] -- warn if find a non-empty extraneous parameter
if parm and parm:match('%S') then
add_warning(parms, 1, 'cvt_unknown_option', parm)
break
end
end
return true, in_unit_table
end
local function record_default_precision(parms, out_current, precision)
-- If necessary, adjust parameters and return a possibly adjusted precision.
-- When converting a range of values where a default precision is required,
-- that default is calculated for each value because the result sometimes
-- depends on the precise input and output values. This function may cause
-- the entire convert process to be repeated in order to ensure that the
-- same default precision is used for each individual convert.
-- If that were not done, a range like 1000 to 1000.4 may give poor results
-- because the first output could be heavily rounded, while the second is not.
-- For range 1000.4 to 1000, this function can give the second convert the
-- same default precision that was used for the first.
if not parms.opt_round_each then
local maxdef = out_current.max_default_precision
if maxdef then
if maxdef < precision then
parms.do_convert_again = true
out_current.max_default_precision = precision
else
precision = out_current.max_default_precision
end
else
out_current.max_default_precision = precision
end
end
return precision
end
local function default_precision(parms, invalue, inclean, denominator, outvalue, in_current, out_current, extra)
-- Return a default value for precision (an integer like 2, 0, -2).
-- If denominator is not nil, it is the value of the denominator in inclean.
-- Code follows procedures used in old template.
local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too
local prec, minprec, adjust
local subunit_ignore_trailing_zero
local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in"
local composite = in_current.composite
if composite then
subunit_ignore_trailing_zero = true -- input "|2|st|10|lb" has precision 0, not -1
if composite[#composite].exception == 'subunit_more_precision' then
subunit_more_precision = true -- do not use standard precision with input like "|2|ft|6|in"
end
end
if denominator and denominator > 0 then
prec = math.max(log10(denominator), 1)
else
-- Count digits after decimal mark, handling cases like '12.345e6'.
local exponent
local integer, dot, decimals, expstr = inclean:match('^(%d*)(%.?)(%d*)(.*)')
local e = expstr:sub(1, 1)
if e == 'e' or e == 'E' then
exponent = tonumber(expstr:sub(2))
end
if dot == '' then
prec = subunit_ignore_trailing_zero and 0 or -integer:match('0*$'):len()
else
prec = #decimals
end
if exponent then
-- So '1230' and '1.23e3' both give prec = -1, and '0.00123' and '1.23e-3' give 5.
prec = prec - exponent
end
end
if in_current.istemperature and out_current.istemperature then
-- Converting between common temperatures (°C, °F, °R, K); not keVT.
-- Kelvin value can be almost zero, or small but negative due to precision problems.
-- Also, an input value like -300 C (below absolute zero) gives negative kelvins.
-- Calculate minimum precision from absolute value.
adjust = 0
local kelvin = abs((invalue - in_current.offset) * in_current.scale)
if kelvin < 1e-8 then -- assume nonzero due to input or calculation precision problem
minprec = 2
else
minprec = 2 - floor(log10(kelvin) + fudge) -- 3 sigfigs in kelvin
end
else
if invalue == 0 or outvalue <= 0 then
-- We are never called with a negative outvalue, but it might be zero.
-- This is special-cased to avoid calculation exceptions.
return record_default_precision(parms, out_current, 0)
end
if out_current.exception == 'integer_more_precision' and floor(invalue) == invalue then
-- With certain output units that sometimes give poor results
-- with default rounding, use more precision when the input
-- value is equal to an integer. An example of a poor result
-- is when input 50 gives a smaller output than input 49.5.
-- Experiment shows this helps, but it does not eliminate all
-- surprises because it is not clear whether "50" should be
-- interpreted as "from 45 to 55" or "from 49.5 to 50.5".
adjust = -log10(in_current.scale)
elseif subunit_more_precision then
-- Conversion like "{{convert|6|ft|1|in|cm}}" (where subunit is "in")
-- has a non-standard adjust value, to give more output precision.
adjust = log10(out_current.scale) + 2
else
adjust = log10(abs(invalue / outvalue))
end
adjust = adjust + log10(2)
-- Ensure that the output has at least two significant figures.
minprec = 1 - floor(log10(outvalue) + fudge)
end
if extra then
adjust = extra.adjust or adjust
minprec = extra.minprec or minprec
end
return record_default_precision(parms, out_current, math.max(floor(prec + adjust), minprec))
end
local function convert(parms, invalue, info, in_current, out_current)
-- Convert given input value from one unit to another.
-- Return output_value (a number) if a simple convert, or
-- return f, t where
-- f = true, t = table of information with results, or
-- f = false, t = error message table.
local inscale = in_current.scale
local outscale = out_current.scale
if not in_current.iscomplex and not out_current.iscomplex then
return invalue * (inscale / outscale) -- minimize overhead for most common case
end
if in_current.invert or out_current.invert then
-- Inverted units, such as inverse length, inverse time, or
-- fuel efficiency. Built-in units do not have invert set.
if (in_current.invert or 1) * (out_current.invert or 1) < 0 then
return 1 / (invalue * inscale * outscale)
end
return invalue * (inscale / outscale)
elseif in_current.offset then
-- Temperature (there are no built-ins for this type of unit).
if info.is_change then
return invalue * (inscale / outscale)
end
return (invalue - in_current.offset) * (inscale / outscale) + out_current.offset
else
-- Built-in unit.
local in_builtin = in_current.builtin
local out_builtin = out_current.builtin
if in_builtin and out_builtin then
if in_builtin == out_builtin then
return invalue
end
-- There are no cases (yet) where need to convert from one
-- built-in unit to another, so this should never occur.
return false, { 'cvt_bug_convert' }
end
if in_builtin == 'mach' or out_builtin == 'mach' then
-- Should check that only one altitude is given but am planning to remove
-- in_current.altitude (which can only occur when Mach is the input unit),
-- and out_current.altitude cannot occur.
local alt = parms.altitude_ft or in_current.altitude
if not alt and parms.altitude_m then
alt = parms.altitude_m / 0.3048 -- 1 ft = 0.3048 m
end
local spd = speed_of_sound(alt)
if in_builtin == 'mach' then
inscale = spd
return invalue * (inscale / outscale)
end
outscale = spd
local adjust = 0.1 / inscale
return true, {
outvalue = invalue * (inscale / outscale),
adjust = log10(adjust) + log10(2),
}
elseif in_builtin == 'hand' then
-- 1 hand = 4 inches; 1.2 hands = 6 inches.
-- Decimals of a hand are only defined for the first digit, and
-- the first fractional digit should be a number of inches (1, 2 or 3).
-- However, this code interprets the entire fractional part as the number
-- of inches / 10 (so 1.75 inches would be 0.175 hands).
-- A value like 12.3 hands is exactly 12*4 + 3 inches; base default precision on that.
local integer, fracpart = math.modf(invalue)
local inch_value = 4 * integer + 10 * fracpart -- equivalent number of inches
local factor = inscale / outscale
if factor == 4 then
-- Am converting to inches: show exact result, and use "inches" not "in" by default.
if parms.abbr_org == nil then
out_current.usename = true
end
local show = format('%g', abs(inch_value)) -- show and clean are unsigned
if not show:find('e', 1, true) then
return true, {
invalue = inch_value,
outvalue = inch_value,
clean = show,
show = show,
}
end
end
local outvalue = (integer + 2.5 * fracpart) * factor
local fracstr = info.clean:match('%.(.*)') or ''
local fmt
if fracstr == '' then
fmt = '%.0f'
else
fmt = '%.' .. format('%d', #fracstr - 1) .. 'f'
end
return true, {
invalue = inch_value,
clean = format(fmt, inch_value),
outvalue = outvalue,
minprec = 0,
}
end
end
return false, { 'cvt_bug_convert' } -- should never occur
end
local function user_style(parms, i)
-- Return text for a user-specified style for a table cell, or '' if none,
-- given i = 1 (input style) or 2 (output style).
local style = parms[(i == 1) and 'stylein' or 'styleout']
if style then
style = style:gsub('"', '')
if style ~= '' then
if style:sub(-1) ~= ';' then
style = style .. ';'
end
return style
end
end
return ''
end
local function make_table_or_sort(parms, invalue, info, in_current, scaled_top)
-- Set options to handle output for a table or a sort key, or both.
-- The text sort key is based on the value resulting from converting
-- the input to a fake base unit with scale = 1, and other properties
-- required for a conversion derived from the input unit.
-- For other modules, return the sort key in a hidden span element, and
-- the scaled value used to generate the sort key.
-- If scaled_top is set, it is the scaled value of the numerator of a per unit
-- to be combined with this unit (the denominator) to make the sort key.
-- Scaling only works with units that convert with a factor (not temperature).
local sortkey, scaled_value
if parms.opt_sortable_on then
local base = { -- a fake unit with enough fields for a valid convert
scale = 1,
invert = in_current.invert and 1,
iscomplex = in_current.iscomplex,
offset = in_current.offset and 0,
}
local outvalue, extra = convert(parms, invalue, info, in_current, base)
if extra then
outvalue = extra.outvalue
end
if in_current.istemperature then
-- Have converted to kelvin; assume numbers close to zero have a
-- rounding error and should be zero.
if abs(outvalue) < 1e-12 then
outvalue = 0
end
end
if scaled_top and outvalue ~= 0 then
outvalue = scaled_top / outvalue
end
scaled_value = outvalue
if not valid_number(outvalue) then
if outvalue < 0 then
sortkey = '1000000000000000000'
else
sortkey = '9000000000000000000'
end
elseif outvalue == 0 then
sortkey = '5000000000000000000'
else
local mag = floor(log10(abs(outvalue)) + 1e-14)
local prefix
if outvalue > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
outvalue = outvalue + 10^(mag+1)
end
sortkey = format('%d', prefix) .. format('%015.0f', floor(outvalue * 10^(14-mag)))
end
end
local sortspan
if sortkey and not parms.table_align then
sortspan = parms.opt_sortable_debug and
'<span data-sort-value="' .. sortkey .. '♠"><span style="border:1px solid">' .. sortkey .. '♠</span></span>' or
'<span data-sort-value="' .. sortkey .. '♠"></span>'
parms.join_before = sortspan
end
if parms.table_align then
local sort
if sortkey then
sort = ' data-sort-value="' .. sortkey .. '"'
if parms.opt_sortable_debug then
parms.join_before = '<span style="border:1px solid">' .. sortkey .. '</span>'
end
else
sort = ''
end
local style = 'style="text-align:' .. parms.table_align .. ';'
local joins = {}
for i = 1, 2 do
joins[i] = (i == 1 and '' or '\n|') .. style .. user_style(parms, i) .. '"' .. sort .. '|'
end
parms.table_joins = joins
end
return sortspan, scaled_value
end
local cvt_to_hand
local function cvtround(parms, info, in_current, out_current)
-- Return true, t where t is a table with the conversion results; fields:
-- show = rounded, formatted string with the result of converting value in info,
-- using the rounding specified in parms.
-- singular = true if result (after rounding and ignoring any negative sign)
-- is "1", or like "1.00", or is a fraction with value < 1;
-- (and more fields shown below, and a calculated 'absvalue' field).
-- or return false, t where t is an error message table.
-- Input info.clean uses en digits (it has been translated, if necessary).
-- Output show uses en or non-en digits as appropriate, or can be spelled.
if out_current.builtin == 'hand' then
return cvt_to_hand(parms, info, in_current, out_current)
end
local invalue = in_current.builtin == 'hand' and info.altvalue or info.value
local outvalue, extra = convert(parms, invalue, info, in_current, out_current)
if parms.need_table_or_sort then
parms.need_table_or_sort = nil -- process using first input value only
make_table_or_sort(parms, invalue, info, in_current)
end
if extra then
if not outvalue then return false, extra end
invalue = extra.invalue or invalue
outvalue = extra.outvalue
end
if not valid_number(outvalue) then
return false, { 'cvt_invalid_num' }
end
local isnegative
if outvalue < 0 then
isnegative = true
outvalue = -outvalue
end
local precision, show, exponent
local denominator = out_current.frac
if denominator then
show = fraction_table(outvalue, denominator)
else
precision = parms.precision
if not precision then
if parms.sigfig then
show, exponent = make_sigfig(outvalue, parms.sigfig)
elseif parms.opt_round then
local n = parms.opt_round
if n == 0.5 then
local integer, fracpart = math.modf(floor(2 * outvalue + 0.5) / 2)
if fracpart == 0 then
show = format('%.0f', integer)
else
show = format('%.1f', integer + fracpart)
end
else
show = format('%.0f', floor((outvalue / n) + 0.5) * n)
end
elseif in_current.builtin == 'mach' then
local sigfig = info.clean:gsub('^[0.]+', ''):gsub('%.', ''):len() + 1
show, exponent = make_sigfig(outvalue, sigfig)
else
local inclean = info.clean
if extra then
inclean = extra.clean or inclean
show = extra.show
end
if not show then
precision = default_precision(parms, invalue, inclean, info.denominator, outvalue, in_current, out_current, extra)
end
end
end
end
if precision then
if precision >= 0 then
local fudge
if precision <= 8 then
-- Add a fudge to handle common cases of bad rounding due to inability
-- to precisely represent some values. This makes the following work:
-- {{convert|-100.1|C|K}} and {{convert|5555000|um|m|2}}.
-- Old template uses #expr round, which invokes PHP round().
-- LATER: Investigate how PHP round() works.
fudge = 2e-14
else
fudge = 0
end
local fmt = '%.' .. format('%d', precision) .. 'f'
local success
success, show = pcall(format, fmt, outvalue + fudge)
if not success then
return false, { 'cvt_big_prec', tostring(precision) }
end
else
precision = -precision -- #digits to zero (in addition to any digits after dot)
local shift = 10 ^ precision
show = format('%.0f', outvalue/shift)
if show ~= '0' then
exponent = #show + precision
end
end
end
local t = format_number(parms, show, exponent, isnegative)
if type(show) == 'string' then
-- Set singular using match because on some systems 0.99999999999999999 is 1.0.
if exponent then
t.singular = (exponent == 1 and show:match('^10*$'))
else
t.singular = (show == '1' or show:match('^1%.0*$'))
end
else
t.fraction_table = show
t.singular = (outvalue <= 1) -- cannot have 'fraction == 1', but if it were possible it would be singular
end
t.raw_absvalue = outvalue -- absolute value before rounding
return true, setmetatable(t, {
__index = function (self, key)
if key == 'absvalue' then
-- Calculate absolute value after rounding, if needed.
local clean, exponent = rawget(self, 'clean'), rawget(self, 'exponent')
local value = tonumber(clean) -- absolute value (any negative sign has been ignored)
if exponent then
value = value * 10^exponent
end
rawset(self, key, value)
return value
end
end })
end
function cvt_to_hand(parms, info, in_current, out_current)
-- Convert input to hands, inches.
-- Return true, t where t is a table with the conversion results;
-- or return false, t where t is an error message table.
if parms.abbr_org == nil then
out_current.usename = true -- default is to show name not symbol
end
local precision = parms.precision
local frac = out_current.frac
if not frac and precision and precision > 1 then
frac = (precision == 2) and 2 or 4
end
local out_next = out_current.out_next
if out_next then
-- Use magic knowledge to determine whether the next unit is inches without requiring i18n.
-- The following ensures that when the output combination "hand in" is used, the inches
-- value is rounded to match the hands value. Also, displaying say "61½" instead of 61.5
-- is better as 61.5 implies the value is not 61.4.
if out_next.exception == 'subunit_more_precision' then
out_next.frac = frac
end
end
-- Convert to inches; calculate hands from that.
local dummy_unit_table = { scale = out_current.scale / 4, frac = frac }
local success, outinfo = cvtround(parms, info, in_current, dummy_unit_table)
if not success then return false, outinfo end
local tfrac = outinfo.fraction_table
local inches = outinfo.raw_absvalue
if tfrac then
inches = floor(inches) -- integer part only; fraction added later
else
inches = floor(inches + 0.5) -- a hands measurement never shows decimals of an inch
end
local hands, inches = divide(inches, 4)
outinfo.absvalue = hands + inches/4 -- supposed to be the absolute rounded value, but this is close enough
local inchstr = tostring(inches) -- '0', '1', '2' or '3'
if precision and precision <= 0 then -- using negative or 0 for precision rounds to nearest hand
hands = floor(outinfo.raw_absvalue/4 + 0.5)
inchstr = ''
elseif tfrac then
-- Always show an integer before fraction (like "15.0½") because "15½" means 15-and-a-half hands.
inchstr = numdot .. format_fraction(parms, 'out', false, inchstr, tfrac.numstr, tfrac.denstr)
else
inchstr = numdot .. from_en(inchstr)
end
outinfo.show = outinfo.sign .. with_separator(parms, format('%.0f', hands)) .. inchstr
return true, outinfo
end
local function evaluate_condition(value, condition)
-- Return true or false from applying a conditional expression to value,
-- or throw an error if invalid.
-- A very limited set of expressions is supported:
-- v < 9
-- v * 9 < 9
-- where
-- 'v' is replaced with value
-- 9 is any number (as defined by Lua tonumber)
-- only en digits are accepted
-- '<' can also be '<=' or '>' or '>='
-- In addition, the following form is supported:
-- LHS and RHS
-- where
-- LHS, RHS = any of above expressions.
local function compare(value, text)
local arithop, factor, compop, limit = text:match('^%s*v%s*([*]?)(.-)([<>]=?)(.*)$')
if arithop == nil then
error('Invalid default expression', 0)
elseif arithop == '*' then
factor = tonumber(factor)
if factor == nil then
error('Invalid default expression', 0)
end
value = value * factor
end
limit = tonumber(limit)
if limit == nil then
error('Invalid default expression', 0)
end
if compop == '<' then
return value < limit
elseif compop == '<=' then
return value <= limit
elseif compop == '>' then
return value > limit
elseif compop == '>=' then
return value >= limit
end
error('Invalid default expression', 0) -- should not occur
end
local lhs, rhs = condition:match('^(.-%W)and(%W.*)')
if lhs == nil then
return compare(value, condition)
end
return compare(value, lhs) and compare(value, rhs)
end
local function get_default(value, unit_table)
-- Return true, s where s = name of unit's default output unit,
-- or return false, t where t is an error message table.
-- Some units have a default that depends on the input value
-- (the first value if a range of values is used).
-- If '!' is in the default, the first bang-delimited field is an
-- expression that uses 'v' to represent the input value.
-- Example: 'v < 120 ! small ! big ! suffix' (suffix is optional)
-- evaluates 'v < 120' as a boolean with result
-- 'smallsuffix' if (value < 120), or 'bigsuffix' otherwise.
-- Input must use en digits and '.' decimal mark.
local default = data_code.default_exceptions[unit_table.defkey or unit_table.symbol] or unit_table.default
if not default then
local per = unit_table.per
if per then
local function a_default(v, u)
local success, ucode = get_default(v, u)
if not success then
return '?' -- an unlikely error has occurred; will cause lookup of default to fail
end
-- Attempt to use only the first unit if a combination or output multiple.
-- This is not bulletproof but should work for most cases.
-- Where it does not work, the convert will need to specify the wanted output unit.
local t = all_units[ucode]
if t then
local combo = t.combination
if combo then
-- For a multiple like ftin, the "first" unit (ft) is last in the combination.
local i = t.multiple and table_len(combo) or 1
ucode = combo[i]
end
else
-- Try for an automatically generated combination.
local item = ucode:match('^(.-)%+') or ucode:match('^(%S+)%s')
if all_units[item] then
return item
end
end
return ucode
end
local unit1, unit2 = per[1], per[2]
local def1 = (unit1 and a_default(value, unit1) or unit_table.vprefix or '')
local def2 = a_default(1, unit2) -- 1 because per unit of denominator
return true, def1 .. '/' .. def2
end
return false, { 'cvt_no_default', unit_table.symbol }
end
if default:find('!', 1, true) == nil then
return true, default
end
local t = split(default, '!')
if #t == 3 or #t == 4 then
local success, result = pcall(evaluate_condition, value, t[1])
if success then
default = result and t[2] or t[3]
if #t == 4 then
default = default .. t[4]
end
return true, default
end
end
return false, { 'cvt_bad_default', unit_table.symbol }
end
local linked_pages -- to record linked pages so will not link to the same page more than once
local function unlink(unit_table)
-- Forget that the given unit has previously been linked (if it has).
-- That is needed when processing a range of inputs or outputs when an id
-- for the first range value may have been evaluated, but only an id for
-- the last value is displayed, and that id may need to be linked.
linked_pages[unit_table.unitcode or unit_table] = nil
end
local function make_link(link, id, unit_table)
-- Return wikilink "[[link|id]]", possibly abbreviated as in examples:
-- [[Mile|mile]] --> [[mile]]
-- [[Mile|miles]] --> [[mile]]s
-- However, just id is returned if:
-- * no link given (so caller does not need to check if a link was defined); or
-- * link has previously been used during the current convert (to avoid overlinking).
local link_key
if unit_table then
link_key = unit_table.unitcode or unit_table
else
link_key = link
end
if not link or link == '' or linked_pages[link_key] then
return id
end
linked_pages[link_key] = true
-- Following only works for language en, but it should be safe on other wikis,
-- and overhead of doing it generally does not seem worthwhile.
local l = link:sub(1, 1):lower() .. link:sub(2)
if link == id or l == id then
return '[[' .. id .. ']]'
elseif link .. 's' == id or l .. 's' == id then
return '[[' .. id:sub(1, -2) .. ']]s'
else
return '[[' .. link .. '|' .. id .. ']]'
end
end
local function variable_name(clean, unit_table)
-- For slwiki, a unit name depends on the value.
-- Parameter clean is the unsigned rounded value in en digits, as a string.
-- Value Source Example for "m"
-- integer 1: name1 meter (also is the name of the unit)
-- integer 2: var{1} metra
-- integer 3 and 4: var{2} metri
-- integer else: var{3} metrov (0 and 5 or more)
-- real/fraction: var{4} metra
-- var{i} means the i'th field in unit_table.varname if it exists and has
-- an i'th field, otherwise name2.
-- Fields are separated with "!" and are not empty.
-- A field for a unit using an SI prefix has the prefix name inserted,
-- replacing '#' if found, or before the field otherwise.
local vname
if clean == '1' then
vname = unit_table.name1
elseif unit_table.varname then
local i
if clean == '2' then
i = 1
elseif clean == '3' or clean == '4' then
i = 2
elseif clean:find('.', 1, true) then
i = 4
else
i = 3
end
if i > 1 and varname == 'pl' then
i = i - 1
end
vname = split(unit_table.varname, '!')[i]
end
if vname then
local si_name = rawget(unit_table, 'si_name') or ''
local pos = vname:find('#', 1, true)
if pos then
vname = vname:sub(1, pos - 1) .. si_name .. vname:sub(pos + 1)
else
vname = si_name .. vname
end
return vname
end
return unit_table.name2
end
local function linked_id(parms, unit_table, key_id, want_link, clean)
-- Return final unit id (symbol or name), optionally with a wikilink,
-- and update unit_table.sep if required.
-- key_id is one of: 'symbol', 'sym_us', 'name1', 'name1_us', 'name2', 'name2_us'.
local abbr_on = (key_id == 'symbol' or key_id == 'sym_us')
if abbr_on and want_link then
local symlink = rawget(unit_table, 'symlink')
if symlink then
return symlink -- for exceptions that have the linked symbol built-in
end
end
local multiplier = rawget(unit_table, 'multiplier')
local per = unit_table.per
if per then
local paren1, paren2 = '', '' -- possible parentheses around bottom unit
local unit1 = per[1] -- top unit_table, or nil
local unit2 = per[2] -- bottom unit_table
if abbr_on then
if not unit1 then
unit_table.sep = '' -- no separator in "$2/acre"
end
if not want_link then
local symbol = unit_table.symbol_raw
if symbol then
return symbol -- for exceptions that have the symbol built-in
end
end
if (unit2.symbol):find('⋅', 1, true) then
paren1, paren2 = '(', ')'
end
end
local key_id2 -- unit2 is always singular
if key_id == 'name2' then
key_id2 = 'name1'
elseif key_id == 'name2_us' then
key_id2 = 'name1_us'
else
key_id2 = key_id
end
local result
if abbr_on then
result = '/'
elseif omitsep then
result = per_word
elseif unit1 then
result = ' ' .. per_word .. ' '
else
result = per_word .. ' '
end
if want_link and unit_table.link then
if abbr_on or not varname then
result = (unit1 and linked_id(parms, unit1, key_id, false, clean) or '') .. result .. linked_id(parms, unit2, key_id2, false, '1')
else
result = (unit1 and variable_name(clean, unit1) or '') .. result .. variable_name('1', unit2)
end
if omit_separator(result) then
unit_table.sep = ''
end
return make_link(unit_table.link, result, unit_table)
end
if unit1 then
result = linked_id(parms, unit1, key_id, want_link, clean) .. result
if unit1.sep then
unit_table.sep = unit1.sep
end
elseif omitsep then
unit_table.sep = ''
end
return result .. paren1 .. linked_id(parms, unit2, key_id2, want_link, '1') .. paren2
end
if multiplier then
-- A multiplier (like "100" in "100km") forces the unit to be plural.
multiplier = from_en(multiplier)
if not omitsep then
multiplier = multiplier .. (abbr_on and ' ' or ' ')
end
if not abbr_on then
if key_id == 'name1' then
key_id = 'name2'
elseif key_id == 'name1_us' then
key_id = 'name2_us'
end
end
else
multiplier = ''
end
local id = unit_table.fixed_name or ((varname and not abbr_on) and variable_name(clean, unit_table) or unit_table[key_id])
if omit_separator(id) then
unit_table.sep = ''
end
if want_link then
local link = data_code.link_exceptions[unit_table.linkey or unit_table.symbol] or unit_table.link
if link then
local before = ''
local i = unit_table.customary
if i == 1 and parms.opt_sp_us then
i = 2 -- show "U.S." not "US"
end
if i == 3 and abbr_on then
i = 4 -- abbreviate "imperial" to "imp"
end
local customary = text_code.customary_units[i]
if customary then
-- LATER: This works for language en only, but it's esoteric so ignore for now.
local pertext
if id:sub(1, 1) == '/' then
-- Want unit "/USgal" to display as "/U.S. gal", not "U.S. /gal".
pertext = '/'
id = id:sub(2)
elseif id:sub(1, 4) == 'per ' then
-- Similarly want "per U.S. gallon", not "U.S. per gallon" (but in practice this is unlikely to be used).
pertext = 'per '
id = id:sub(5)
else
pertext = ''
end
-- Omit any "US"/"U.S."/"imp"/"imperial" from start of id since that will be inserted.
local removes = (i < 3) and { 'US ', 'US ', 'U.S. ', 'U.S. ' } or { 'imp ', 'imp ', 'imperial ' }
for _, prefix in ipairs(removes) do
local plen = #prefix
if id:sub(1, plen) == prefix then
id = id:sub(plen + 1)
break
end
end
before = pertext .. make_link(customary.link, customary[1]) .. ' '
end
id = before .. make_link(link, id, unit_table)
end
end
return multiplier .. id
end
local function make_id(parms, which, unit_table)
-- Return id, f where
-- id = unit name or symbol, possibly modified
-- f = true if id is a name, or false if id is a symbol
-- using the value for index 'which', and for 'in' or 'out' (unit_table.inout).
-- Result is '' if no symbol/name is to be used.
-- In addition, set unit_table.sep = ' ' or ' ' or ''
-- (the separator that caller will normally insert before the id).
if parms.opt_values then
unit_table.sep = ''
return ''
end
local inout = unit_table.inout
local info = unit_table.valinfo[which]
local abbr_org = parms.abbr_org
local adjectival = parms.opt_adjectival
local lk = parms.lk
local want_link = (lk == 'on' or lk == inout)
local usename = unit_table.usename
local singular = info.singular
local want_name
if usename then
want_name = true
else
if abbr_org == nil then
if parms.wantname then
want_name = true
end
if unit_table.usesymbol then
want_name = false
end
end
if want_name == nil then
local abbr = parms.abbr
if abbr == 'on' or abbr == inout or (abbr == 'mos' and inout == 'out') then
want_name = false
else
want_name = true
end
end
end
local key
if want_name then
if lk == nil and unit_table.builtin == 'hand' then
want_link = true
end
if parms.opt_use_nbsp then
unit_table.sep = ' '
else
unit_table.sep = ' '
end
if parms.opt_singular then
local value
if inout == 'in' then
value = info.value
else
value = info.absvalue
end
if value then -- some unusual units do not always set value field
value = abs(value)
singular = (0 < value and value < 1.0001)
end
end
if unit_table.engscale then
-- engscale: so "|1|e3kg" gives "1 thousand kilograms" (plural)
singular = false
end
key = (adjectival or singular) and 'name1' or 'name2'
if parms.opt_sp_us then
key = key .. '_us'
end
else
if unit_table.builtin == 'hand' then
if parms.opt_hand_hh then
unit_table.symbol = 'hh' -- LATER: might want i18n applied to this
end
end
unit_table.sep = ' '
key = parms.opt_sp_us and 'sym_us' or 'symbol'
end
return linked_id(parms, unit_table, key, want_link, info.clean), want_name
end
local function decorate_value(parms, unit_table, which, number_word)
-- If needed, update unit_table so values will be shown with extra information.
-- For consistency with the old template (but different from fmtpower),
-- the style to display powers of 10 includes "display:none" to allow some
-- browsers to copy, for example, "10³" as "10^3", rather than as "103".
local info
local engscale = unit_table.engscale
local prefix = unit_table.vprefix
if engscale or prefix then
info = unit_table.valinfo[which]
if info.decorated then
return -- do not redecorate if repeating convert
end
info.decorated = true
if engscale then
local inout = unit_table.inout
local abbr = parms.abbr
if (abbr == 'on' or abbr == inout) and not parms.number_word then
info.show = info.show ..
'<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' ..
from_en('10') ..
'</span></span><s style="display:none">^</s><sup>' ..
from_en(tostring(engscale.exponent)) .. '</sup>'
elseif number_word then
local number_id
local lk = parms.lk
if lk == 'on' or lk == inout then
number_id = make_link(engscale.link, engscale[1])
else
number_id = engscale[1]
end
-- WP:NUMERAL recommends " " in values like "12 million".
info.show = info.show .. (parms.opt_adjectival and '-' or ' ') .. number_id
end
end
if prefix then
info.show = prefix .. info.show
end
end
end
local function process_input(parms, in_current)
-- Processing required once per conversion.
-- Return block of text to represent input (value/unit).
if parms.opt_output_only or parms.opt_output_number_only or parms.opt_output_unit_only then
parms.joins = { '', '' }
return ''
end
local first_unit
local composite = in_current.composite -- nil or table of units
if composite then
first_unit = composite[1]
else
first_unit = in_current
end
local id1, want_name = make_id(parms, 1, first_unit)
local sep = first_unit.sep -- separator between value and unit, set by make_id
local preunit = parms.preunit1
if preunit then
sep = '' -- any separator is included in preunit
else
preunit = ''
end
if parms.opt_input_unit_only then
parms.joins = { '', '' }
if composite then
local parts = { id1 }
for i, unit in ipairs(composite) do
if i > 1 then
table.insert(parts, (make_id(parms, 1, unit)))
end
end
id1 = table.concat(parts, ' ')
end
if want_name and parms.opt_adjectival then
return preunit .. hyphenated(id1)
end
return preunit .. id1
end
if parms.opt_also_symbol and not composite and not parms.opt_flip then
local join1 = parms.joins[1]
if join1 == ' (' or join1 == ' [' then
parms.joins = { ' [' .. first_unit[parms.opt_sp_us and 'sym_us' or 'symbol'] .. ']' .. join1 , parms.joins[2] }
end
end
if in_current.builtin == 'mach' and first_unit.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. ' '
local range = parms.range
local valinfo = first_unit.valinfo
local result = prefix .. valinfo[1].show
if range then
-- For simplicity and because more not needed, handle one range item only.
local prefix2 = make_id(parms, 2, first_unit) .. ' '
result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in', {spaced=true})
end
return preunit .. result
end
if composite then
-- Simplify: assume there is no range, and no decoration.
local mid = (not parms.opt_flip) and parms.mid or ''
local sep1 = ' '
local sep2 = ' '
if parms.opt_adjectival and want_name then
sep1 = '-'
sep2 = '-'
end
if omitsep and sep == '' then
-- Testing the id of the most significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
local parts = { first_unit.valinfo[1].show .. sep1 .. id1 }
for i, unit in ipairs(composite) do
if i > 1 then
table.insert(parts, unit.valinfo[1].show .. sep1 .. (make_id(parms, 1, unit)))
end
end
return table.concat(parts, sep2) .. mid
end
local add_unit = (parms.abbr == 'mos') or
parms[parms.opt_flip and 'out_range_x' or 'in_range_x'] or
(not want_name and parms.abbr_range_x)
local range = parms.range
if range and not add_unit then
unlink(first_unit)
end
local id = range and make_id(parms, range.n + 1, first_unit) or id1
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, 'in')
if was_hyphenated then
add_unit = false
end
local result
local valinfo = first_unit.valinfo
if range then
for i = 0, range.n do
local number_word
if i == range.n then
add_unit = false
number_word = true
end
decorate_value(parms, first_unit, i+1, number_word)
local show = valinfo[i+1].show
if add_unit then
show = show .. first_unit.sep .. (i == 0 and id1 or make_id(parms, i+1, first_unit))
end
if i == 0 then
result = show
else
result = range_text(range[i], want_name, parms, result, show, 'in')
end
end
else
decorate_value(parms, first_unit, 1, true)
result = valinfo[1].show
end
return result .. preunit .. extra
end
local function process_one_output(parms, out_current)
-- Processing required for each output unit.
-- Return block of text to represent output (value/unit).
local inout = out_current.inout -- normally 'out' but can be 'in' for order=out
local id1, want_name = make_id(parms, 1, out_current)
local sep = out_current.sep -- set by make_id
local preunit = parms.preunit2
if preunit then
sep = '' -- any separator is included in preunit
else
preunit = ''
end
if parms.opt_output_unit_only then
if want_name and parms.opt_adjectival then
return preunit .. hyphenated(id1)
end
return preunit .. id1
end
if out_current.builtin == 'mach' and out_current.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. ' '
local range = parms.range
local valinfo = out_current.valinfo
local result = prefix .. valinfo[1].show
if range then
-- For simplicity and because more not needed, handle one range item only.
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout, {spaced=true})
end
return preunit .. result
end
local add_unit = (parms[parms.opt_flip and 'in_range_x' or 'out_range_x'] or
(not want_name and parms.abbr_range_x)) and
not parms.opt_output_number_only
local range = parms.range
if range and not add_unit then
unlink(out_current)
end
local id = range and make_id(parms, range.n + 1, out_current) or id1
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, inout)
if was_hyphenated then
add_unit = false
end
local result
local valinfo = out_current.valinfo
if range then
for i = 0, range.n do
local number_word
if i == range.n then
add_unit = false
number_word = true
end
decorate_value(parms, out_current, i+1, number_word)
local show = valinfo[i+1].show
if add_unit then
show = show .. out_current.sep .. (i == 0 and id1 or make_id(parms, i+1, out_current))
end
if i == 0 then
result = show
else
result = range_text(range[i], want_name, parms, result, show, inout)
end
end
else
decorate_value(parms, out_current, 1, true)
result = valinfo[1].show
end
if parms.opt_output_number_only then
return result
end
return result .. preunit .. extra
end
local function make_output_single(parms, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for a single output (which is not a combination or a multiple);
-- or return false, t where t is an error message table.
if parms.opt_order_out and in_unit_table.unitcode == out_unit_table.unitcode then
out_unit_table.valinfo = in_unit_table.valinfo
else
out_unit_table.valinfo = collection()
for _, v in ipairs(in_unit_table.valinfo) do
local success, info = cvtround(parms, v, in_unit_table, out_unit_table)
if not success then return false, info end
out_unit_table.valinfo:add(info)
end
end
return true, process_one_output(parms, out_unit_table)
end
local function make_output_multiple(parms, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for an output which is a multiple (like 'ftin');
-- or return false, t where t is an error message table.
local inout = out_unit_table.inout -- normally 'out' but can be 'in' for order=out
local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil)
local combos = out_unit_table.combination -- table of unit tables (will not be nil)
local abbr = parms.abbr
local abbr_org = parms.abbr_org
local disp = parms.disp
local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or
not (abbr == 'on' or abbr == inout or abbr == 'mos')
local want_link = (parms.lk == 'on' or parms.lk == inout)
local mid = parms.opt_flip and parms.mid or ''
local sep1 = ' '
local sep2 = ' '
if parms.opt_adjectival and want_name then
sep1 = '-'
sep2 = '-'
end
local do_spell = parms.opt_spell_out
parms.opt_spell_out = nil -- so the call to cvtround does not spell the value
local function make_result(info, isfirst)
local fmt, outvalue, sign
local results = {}
for i = 1, #combos do
local tfrac, thisvalue, strforce
local out_current = combos[i]
out_current.inout = inout
local scale = multiple[i]
if i == 1 then -- least significant unit ('in' from 'ftin')
local decimals
out_current.frac = out_unit_table.frac
local success, outinfo = cvtround(parms, info, in_unit_table, out_current)
if not success then return false, outinfo end
if isfirst then
out_unit_table.valinfo = { outinfo } -- in case output value of first least significant unit is needed
end
sign = outinfo.sign
tfrac = outinfo.fraction_table
if outinfo.is_scientific then
strforce = outinfo.show
decimals = ''
elseif tfrac then
decimals = ''
else
local show = outinfo.show -- number as a string in local language
local p1, p2 = show:find(numdot, 1, true)
decimals = p1 and show:sub(p2 + 1) or '' -- text after numdot, if any
end
fmt = '%.' .. ulen(decimals) .. 'f' -- to reproduce precision
if decimals == '' then
if tfrac then
outvalue = floor(outinfo.raw_absvalue) -- integer part only; fraction added later
else
outvalue = floor(outinfo.raw_absvalue + 0.5) -- keep all integer digits of least significant unit
end
else
outvalue = outinfo.absvalue
end
end
if scale then
outvalue, thisvalue = divide(outvalue, scale)
else
thisvalue = outvalue
end
local id
if want_name then
if varname then
local clean
if strforce or tfrac then
clean = '.1' -- dummy value to force name for floating point
else
clean = format(fmt, thisvalue)
end
id = variable_name(clean, out_current)
else
local key = 'name2'
if parms.opt_adjectival then
key = 'name1'
elseif tfrac then
if thisvalue == 0 then
key = 'name1'
end
elseif parms.opt_singular then
if 0 < thisvalue and thisvalue < 1.0001 then
key = 'name1'
end
else
if thisvalue == 1 then
key = 'name1'
end
end
id = out_current[key]
end
else
id = out_current['symbol']
end
if i == 1 and omit_separator(id) then
-- Testing the id of the least significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
if want_link then
local link = out_current.link
if link then
id = make_link(link, id, out_current)
end
end
local strval
local spell_inout = (i == #combos or outvalue == 0) and inout or '' -- trick so the last value processed (first displayed) has uppercase, if requested
if strforce and outvalue == 0 then
sign = '' -- any sign is in strforce
strval = strforce -- show small values in scientific notation; will only use least significant unit
elseif tfrac then
local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil
strval = format_fraction(parms, spell_inout, false, wholestr, tfrac.numstr, tfrac.denstr, do_spell)
else
strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue))
if do_spell then
strval = spell_number(parms, spell_inout, strval) or strval
end
end
table.insert(results, strval .. sep1 .. id)
if outvalue == 0 then
break
end
fmt = '%.0f' -- only least significant unit can have a non-integral value
end
local reversed, count = {}, #results
for i = 1, count do
reversed[i] = results[count + 1 - i]
end
return true, sign .. table.concat(reversed, sep2)
end
local valinfo = in_unit_table.valinfo
local success, result = make_result(valinfo[1], true)
if not success then return false, result end
local range = parms.range
if range then
for i = 1, range.n do
local success, result2 = make_result(valinfo[i+1])
if not success then return false, result2 end
result = range_text(range[i], want_name, parms, result, result2, inout, {spaced=true})
end
end
return true, result .. mid
end
local function process(parms, in_unit_table, out_unit_table)
-- Return true, s, outunit where s = final wikitext result,
-- or return false, t where t is an error message table.
linked_pages = {}
local success, bad_output
local bad_input_mcode = in_unit_table.bad_mcode -- nil if input unit is a valid convert unit
local out_unit = parms.out_unit
if out_unit == nil or out_unit == '' or type(out_unit) == 'function' then
if bad_input_mcode or parms.opt_input_unit_only then
bad_output = ''
else
local getdef = type(out_unit) == 'function' and out_unit or get_default
success, out_unit = getdef(in_unit_table.valinfo[1].value, in_unit_table)
parms.out_unit = out_unit
if not success then
bad_output = out_unit
end
end
end
if not bad_output and not out_unit_table then
success, out_unit_table = lookup(parms, out_unit, 'any_combination')
if success then
local mismatch = check_mismatch(in_unit_table, out_unit_table)
if mismatch then
bad_output = mismatch
end
else
bad_output = out_unit_table
end
end
local lhs, rhs
local flipped = parms.opt_flip and not bad_input_mcode
if bad_output then
rhs = (bad_output == '') and '' or message(parms, bad_output)
elseif parms.opt_input_unit_only then
rhs = ''
else
local combos -- nil (for 'ft' or 'ftin'), or table of unit tables (for 'm ft')
if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin')
combos = out_unit_table.combination
end
local frac = parms.frac -- nil or denominator of fraction for output values
if frac then
-- Apply fraction to the unit (if only one), or to non-SI units (if a combination),
-- except that if a precision is also specified, the fraction only applies to
-- the hand unit; that allows the following result:
-- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands)
-- However, the following is handled elsewhere as a special case:
-- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in)
if combos then
local precision = parms.precision
for _, unit in ipairs(combos) do
if unit.builtin == 'hand' or (not precision and not unit.prefixes) then
unit.frac = frac
end
end
else
out_unit_table.frac = frac
end
end
local outputs = {}
local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables
if imax == 1 then
parms.opt_order_out = nil -- only useful with an output combination
end
if not flipped and not parms.opt_order_out then
-- Process left side first so any duplicate links (from lk=on) are suppressed
-- on right. Example: {{convert|28|e9pc|e9ly|abbr=off|lk=on}}
lhs = process_input(parms, in_unit_table)
end
for i = 1, imax do
local success, item
local out_current = combos and combos[i] or out_unit_table
out_current.inout = 'out'
if i == 1 then
if imax > 1 and out_current.builtin == 'hand' then
out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination
end
if parms.opt_order_out then
out_current.inout = 'in'
end
end
if out_current.multiple then
success, item = make_output_multiple(parms, in_unit_table, out_current)
else
success, item = make_output_single(parms, in_unit_table, out_current)
end
if not success then return false, item end
outputs[i] = item
end
if parms.opt_order_out then
lhs = outputs[1]
table.remove(outputs, 1)
end
local sep = parms.table_joins and parms.table_joins[2] or parms.join_between
rhs = table.concat(outputs, sep)
end
if flipped or not lhs then
local input = process_input(parms, in_unit_table)
if flipped then
lhs = rhs
rhs = input
else
lhs = input
end
end
if parms.join_before then
lhs = parms.join_before .. lhs
end
local wikitext
if bad_input_mcode then
if bad_input_mcode == '' then
wikitext = lhs
else
wikitext = lhs .. message(parms, bad_input_mcode)
end
elseif parms.table_joins then
wikitext = parms.table_joins[1] .. lhs .. parms.table_joins[2] .. rhs
else
wikitext = lhs .. parms.joins[1] .. rhs .. parms.joins[2]
end
if parms.warnings and not bad_input_mcode then
wikitext = wikitext .. parms.warnings
end
return true, get_styles(parms) .. wikitext, out_unit_table
end
local function main_convert(frame)
-- Do convert, and if needed, do it again with higher default precision.
local parms = { frame = frame } -- will hold template arguments, after translation
set_config(frame.args)
local success, result = get_parms(parms, frame:getParent().args)
if success then
if type(result) ~= 'table' then
return tostring(result)
end
local in_unit_table = result
local out_unit_table
for _ = 1, 2 do -- use counter so cannot get stuck repeating convert
success, result, out_unit_table = process(parms, in_unit_table, out_unit_table)
if success and parms.do_convert_again then
parms.do_convert_again = false
else
break
end
end
end
-- If input=x gives a problem, the result should be just the user input
-- (if x is a property like P123 it has been replaced with '').
-- An unknown input unit would display the input and an error message
-- with success == true at this point.
-- Also, can have success == false with a message that outputs an empty string.
if parms.input_text then
if success and not parms.have_problem then
return result
end
local cat
if parms.tracking then
-- Add a tracking category using the given text as the category sort key.
-- There is currently only one type of tracking, but in principle multiple
-- items could be tracked, using different sort keys for convenience.
cat = wanted_category('tracking', parms.tracking)
end
return parms.input_text .. (cat or '')
end
return success and result or message(parms, result)
end
local function _unit(unitcode, options)
-- Helper function for Module:Val to look up a unit.
-- Parameter unitcode must be a string to identify the wanted unit.
-- Parameter options must be nil or a table with optional fields:
-- value = number (for sort key; default value is 1)
-- scaled_top = nil for a normal unit, or a number for a unit which is
-- the denominator of a per unit (for sort key)
-- si = { 'symbol', 'link' }
-- (a table with two strings) to make an SI unit
-- that will be used for the look up
-- link = true if result should be [[linked]]
-- sort = 'on' or 'debug' if result should include a sort key in a
-- span element ('debug' makes the key visible)
-- name = true for the name of the unit instead of the symbol
-- us = true for the US spelling of the unit, if any
-- Return nil if unitcode is not a non-empty string.
-- Otherwise return a table with fields:
-- text = requested symbol or name of unit, optionally linked
-- scaled_value = input value adjusted by unit scale; used for sort key
-- sortspan = span element with sort key like that provided by {{ntsh}},
-- calculated from the result of converting value
-- to a base unit with scale 1.
-- unknown = true if the unitcode was not known
unitcode = strip(unitcode)
if unitcode == nil or unitcode == '' then
return nil
end
set_config({})
linked_pages = {}
options = options or {}
local parms = {
abbr = options.name and 'off' or 'on',
lk = options.link and 'on' or nil,
opt_sp_us = options.us and true or nil,
opt_ignore_error = true, -- do not add pages using this function to 'what links here' for Module:Convert/extra
opt_sortable_on = options.sort == 'on' or options.sort == 'debug',
opt_sortable_debug = options.sort == 'debug',
}
if options.si then
-- Make a dummy table of units (just one unit) for lookup to use.
-- This makes lookup recognize any SI prefix in the unitcode.
local symbol = options.si[1] or '?'
parms.unittable = { [symbol] = {
_name1 = symbol,
_name2 = symbol,
_symbol = symbol,
utype = symbol,
scale = symbol == 'g' and 0.001 or 1,
prefixes = 1,
default = symbol,
link = options.si[2],
}}
end
local success, unit_table = lookup(parms, unitcode, 'no_combination')
if not success then
unit_table = setmetatable({
symbol = unitcode, name2 = unitcode, utype = unitcode,
scale = 1, default = '', defkey = '', linkey = '' }, unit_mt)
end
local value = tonumber(options.value) or 1
local clean = tostring(abs(value))
local info = {
value = value,
altvalue = value,
singular = (clean == '1'),
clean = clean,
show = clean,
}
unit_table.inout = 'in'
unit_table.valinfo = { info }
local sortspan, scaled_value
if options.sort then
sortspan, scaled_value = make_table_or_sort(parms, value, info, unit_table, options.scaled_top)
end
return {
text = make_id(parms, 1, unit_table),
sortspan = sortspan,
scaled_value = scaled_value,
unknown = not success and true or nil,
}
end
return { convert = main_convert, _unit = _unit }
3pypa0bmxjwgr4t9y04ld77yttvlyar
392702
392700
2026-09-02T00:54:16Z
MacTire02
219
prowal
392702
Scribunto
text/plain
-- Convert a value from one unit of measurement to another.
-- Example: {{convert|123|lb|kg}} --> 123 pounds (56 kg)
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
local MINUS = '−' -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92)
local abs = math.abs
local floor = math.floor
local format = string.format
local log10 = math.log10
local ustring = mw.ustring
local ulen = ustring.len
local usub = ustring.sub
-- Configuration options to keep magic values in one location.
-- Conversion data and message text are defined in separate modules.
local config, maxsigfig
local numdot -- must be '.' or ',' or a character which works in a regex
local numsep, numsep_remove, numsep_remove2
local data_code, all_units
local text_code
local varname -- can be a code to use variable names that depend on value
local from_en_table -- to translate an output string of en digits to local language
local to_en_table -- to translate an input string of digits in local language to en
-- Use translation_table in convert/text to change the following.
local en_default -- true uses lang=en unless convert has lang=local or local digits
local group_method = 3 -- code for how many digits are in a group
local per_word = 'per' -- for units like "liters per kilometer"
local plural_suffix = 'yn' -- only other useful value is probably '' to disable plural unit names
local omitsep -- true to omit separator before local symbol/name
-- All units should be defined in the data module. However, to cater for quick changes
-- and experiments, any unknown unit is looked up in an extra data module, if it exists.
-- That module would be transcluded in only a small number of pages, so there should be
-- little server overhead from making changes, and changes should propagate quickly.
local extra_module -- name of module with extra units
local extra_units -- nil or table of extra units from extra_module
-- Some options in the invoking template can set variables used later in the module.
local currency_text -- for a user-defined currency symbol: {{convert|12|$/ha|$=€}} (euro replaces dollar)
local function from_en(text)
-- Input is a string representing a number in en digits with '.' decimal mark,
-- without digit grouping (which is done just after calling this).
-- Return the translation of the string with numdot and digits in local language.
if numdot ~= '.' then
text = text:gsub('%.', numdot)
end
if from_en_table then
text = text:gsub('%d', from_en_table)
end
return text
end
local function to_en(text)
-- Input is a string representing a number in the local language with
-- an optional numdot decimal mark and numsep digit grouping.
-- Return the translation of the string with '.' mark and en digits,
-- and no separators (they have to be removed here to handle cases like
-- numsep = '.' and numdot = ',' with input "1.234.567,8").
if to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
return text
end
local function decimal_mark(text)
-- Return ',' if text probably is using comma for decimal mark, or has no decimal mark.
-- Return '.' if text probably is using dot for decimal mark.
-- Otherwise return nothing (decimal mark not known).
if not text:find('[.,]') then return ',' end
text = text:gsub('^%-', ''):gsub('%+%d+/%d+$', ''):gsub('[Ee]%-?%d+$', '')
local decimal =
text:match('^0?([.,])%d+$') or
text:match('%d([.,])%d?%d?$') or
text:match('%d([.,])%d%d%d%d+$')
if decimal then return decimal end
if text:match('%.%d+%.') then return ',' end
if text:match('%,%d+,') then return '.' end
end
local add_warning, with_separator -- forward declarations
local function to_en_with_check(text, parms)
-- Version of to_en() for a wiki using numdot = ',' and numsep = '.' to check
-- text (an input number as a string) which might have been copied from enwiki.
-- For example, in '1.234' the '.' could be a decimal mark or a group separator.
-- From viwiki.
if to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if decimal_mark(text) == '.' then
local original = text
text = text:gsub(',', '') -- for example, interpret "1,234.5" as an enwiki value
if parms then
add_warning(parms, 0, 'cvt_enwiki_num', original, with_separator({}, text))
end
else
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
end
return text
end
local function omit_separator(id)
-- Return true if there should be no separator before id (a unit symbol or name).
-- For zhwiki, there should be no separator if id uses local characters.
-- The following kludge should be a sufficient test.
if omitsep then
if id:sub(1, 2) == '-{' then -- for "-{...}-" content language variant
return true
end
if id:byte() > 127 then
local first = usub(id, 1, 1)
if first ~= 'Å' and first ~= '°' and first ~= 'µ' then
return true
end
end
end
return id:sub(1, 1) == '/' -- no separator before units like "/ha"
end
local spell_module -- name of module that can spell numbers
local speller -- function from that module to handle spelling (set if needed)
local wikidata_module, wikidata_data_module -- names of Wikidata modules
local wikidata_code, wikidata_data -- exported tables from those modules (set if needed)
local function set_config(args)
-- Set configuration options from template #invoke or defaults.
config = args
maxsigfig = config.maxsigfig or 14 -- maximum number of significant figures
local data_module, text_module
local sandbox = config.sandbox and ('/' .. config.sandbox) or ''
data_module = "Module:Convert/data" .. sandbox
text_module = "Module:Convert/text" .. sandbox
extra_module = "Module:Convert/extra" .. sandbox
wikidata_module = "Module:Convert/wikidata" .. sandbox
wikidata_data_module = "Module:Convert/wikidata/data" .. sandbox
spell_module = "Module:ConvertNumeric"
data_code = mw.loadData(data_module)
text_code = mw.loadData(text_module)
all_units = data_code.all_units
local translation = text_code.translation_table
if translation then
numdot = translation.numdot
numsep = translation.numsep
if numdot == ',' and numsep == '.' then
if text_code.all_messages.cvt_enwiki_num then
to_en = to_en_with_check
end
end
if translation.group then
group_method = translation.group
end
if translation.per_word then
per_word = translation.per_word
end
if translation.plural_suffix then
plural_suffix = translation.plural_suffix
end
varname = translation.varname
from_en_table = translation.from_en
local use_workaround = true
if use_workaround then
-- 2013-07-05 workaround bug by making a copy of the required table.
-- mw.ustring.gsub fails with a table (to_en_table) as the replacement,
-- if the table is accessed via mw.loadData.
local source = translation.to_en
if source then
to_en_table = {}
for k, v in pairs(source) do
to_en_table[k] = v
end
end
else
to_en_table = translation.to_en
end
if translation.lang == 'en default' then
en_default = true -- for hiwiki
end
omitsep = translation.omitsep -- for zhwiki
end
numdot = config.numdot or numdot or '.' -- decimal mark before fractional digits
numsep = config.numsep or numsep or ',' -- group separator for numbers
-- numsep should be ',' or '.' or '' or ' ' or a Unicode character.
-- numsep_remove must work in a regex to identify separators to be removed.
if numsep ~= '' then
numsep_remove = (numsep == '.') and '%.' or numsep
end
if numsep ~= ',' and numdot ~= ',' then
numsep_remove2 = ',' -- so numbers copied from enwiki will work
end
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,
}
end
local function divide(numerator, denominator)
-- Return integers quotient, remainder resulting from dividing the two
-- given numbers, which should be unsigned integers.
local quotient, remainder = floor(numerator / denominator), numerator % denominator
if not (0 <= remainder and remainder < denominator) then
-- Floating point limits may need this, as in {{convert|160.02|Ym|ydftin}}.
remainder = 0
end
return quotient, remainder
end
local function split(text, delimiter)
-- Return a numbered table with fields from splitting text.
-- The delimiter is used in a regex without escaping (for example, '.' would fail).
-- Each field has any leading/trailing whitespace removed.
local t = {}
text = text .. delimiter -- to get last item
for item in text:gmatch('%s*(.-)%s*' .. delimiter) do
table.insert(t, item)
end
return t
end
local function strip(text)
-- If text is a string, return its content with no leading/trailing
-- whitespace. Otherwise return nil (a nil argument gives a nil result).
if type(text) == 'string' then
return text:match("^%s*(.-)%s*$")
end
end
local function table_len(t)
-- Return length (<100) of a numbered table to replace #t which is
-- documented to not work if t is accessed via mw.loadData().
for i = 1, 100 do
if t[i] == nil then
return i - 1
end
end
end
local function wanted_category(catkey, catsort, want_warning)
-- Return message category if it is wanted in current namespace,
-- otherwise return ''.
local cat
local title = mw.title.getCurrentTitle()
if title then
local nsdefault = '0' -- default namespace: '0' = article; '0,10' = article and template
local namespace = title.namespace
for _, v in ipairs(split(config.nscat or nsdefault, ',')) do
if namespace == tonumber(v) then
cat = text_code.all_categories[want_warning and 'warning' or catkey]
if catsort and catsort ~= '' and cat:sub(-2) == ']]' then
cat = cat:sub(1, -3) .. '|' .. mw.text.nowiki(usub(catsort, 1, 20)) .. ']]'
end
break
end
end
end
return cat or ''
end
local function message(parms, mcode, is_warning)
-- Return wikitext for an error message, including category if specified
-- for the message type.
-- mcode = numbered table specifying the message:
-- mcode[1] = 'cvt_xxx' (string used as a key to get message info)
-- mcode[2] = 'parm1' (string to replace '$1' if any in message)
-- mcode[3] = 'parm2' (string to replace '$2' if any in message)
-- mcode[4] = 'parm3' (string to replace '$3' if any in message)
local msg
if type(mcode) == 'table' then
if mcode[1] == 'cvt_no_output' then
-- Some errors should cause convert to output an empty string,
-- for example, for an optional field in an infobox.
return ''
end
msg = text_code.all_messages[mcode[1]]
end
parms.have_problem = true
local function subparm(fmt, ...)
local rep = {}
for i, v in ipairs({...}) do
rep['$' .. i] = v
end
return (fmt:gsub('$%d+', rep))
end
if msg then
local parts = {}
local regex, replace = msg.regex, msg.replace
for i = 1, 3 do
local limit = 40
local s = mcode[i + 1]
if s then
if regex and replace then
s = s:gsub(regex, replace)
limit = nil -- allow long "should be" messages
end
-- Escape user input so it does not break the message.
-- To avoid tags (like {{convert|1<math>23</math>|m}}) breaking
-- the mouseover title, any strip marker starting with char(127) is
-- replaced with '...' (text not needing i18n).
local append
local pos = s:find(string.char(127), 1, true)
if pos then
append = '...'
s = s:sub(1, pos - 1)
end
if limit and ulen(s) > limit then
s = usub(s, 1, limit)
append = '...'
end
s = mw.text.nowiki(s) .. (append or '')
else
s = '?'
end
parts['$' .. i] = s
end
local function ispreview()
-- Return true if a prominent message should be shown.
if parms.test == 'preview' or parms.test == 'nopreview' then
-- For testing, can preview a real message or simulate a preview
-- when running automated tests.
return parms.test == 'preview'
end
local success, revid = pcall(function ()
return (parms.frame):preprocess('{{REVISIONID}}') end)
return success and (revid == '')
end
local want_warning = is_warning and
not config.warnings and -- show unobtrusive warnings if config.warnings not configured
not msg.nowarn -- but use msg settings, not standard warning, if specified
local title = string.gsub(msg[1] or 'Missing message', '$%d+', parts)
local text = want_warning and '*' or msg[2] or 'Missing message'
local cat = wanted_category(msg[3], mcode[2], want_warning)
local anchor = msg[4] or ''
local fmtkey = ispreview() and 'cvt_format_preview' or
(want_warning and 'cvt_format2' or msg.format or 'cvt_format')
local fmt = text_code.all_messages[fmtkey] or 'convert: bug'
return subparm(fmt, title:gsub('"', '"'), text, cat, anchor)
end
return 'Convert internal error: unknown message'
end
function add_warning(parms, level, key, text1, text2) -- for forward declaration above
-- If enabled, add a warning that will be displayed after the convert result.
-- A higher level is more verbose: more kinds of warnings are displayed.
-- To reduce output noise, only the first warning is displayed.
if level <= (tonumber(config.warnings) or 1) then
if parms.warnings == nil then
parms.warnings = message(parms, { key, text1, text2 }, true)
end
end
end
local function spell_number(parms, inout, number, numerator, denominator)
-- Return result of spelling (number, numerator, denominator), or
-- return nil if spelling is not available or not supported for given text.
-- Examples (each value must be a string or nil):
-- number numerator denominator output
-- ------ --------- ----------- -------------------
-- "1.23" nil nil one point two three
-- "1" "2" "3" one and two thirds
-- nil "2" "3" two thirds
if not speller then
local function get_speller(module)
return require(module).spell_number
end
local success
success, speller = pcall(get_speller, spell_module)
if not success or type(speller) ~= 'function' then
add_warning(parms, 1, 'cvt_no_spell', 'spell')
return nil
end
end
local case
if parms.spell_upper == inout then
case = true
parms.spell_upper = nil -- only uppercase first word in a multiple unit
end
local sp = not parms.opt_sp_us
local adj = parms.opt_adjectival
return speller(number, numerator, denominator, case, sp, adj)
end
------------------------------------------------------------------------
-- BEGIN: Code required only for built-in units.
-- LATER: If need much more code, move to another module to simplify this module.
local function speed_of_sound(altitude)
-- This is for the Mach built-in unit of speed.
-- Return speed of sound in metres per second at given altitude in feet.
-- If no altitude given, use default (zero altitude = sea level).
-- Table gives speed of sound in miles per hour at various altitudes:
-- altitude = -17,499 to 402,499 feet
-- mach_table[a + 4] = s where
-- a = (altitude / 5000) rounded to nearest integer (-3 to 80)
-- s = speed of sound (mph) at that altitude
-- LATER: Should calculate result from an interpolation between the next
-- lower and higher altitudes in table, rather than rounding to nearest.
-- From: http://www.aerospaceweb.org/question/atmosphere/q0112.shtml
local mach_table = { -- a =
799.5, 787.0, 774.2, 761.207051, -- -3 to 0
748.0, 734.6, 721.0, 707.0, 692.8, 678.3, 663.5, 660.1, 660.1, 660.1, -- 1 to 10
660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6, -- 11 to 20
677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6, -- 21 to 30
737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.0, -- 31 to 40
695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7, -- 41 to 50
639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5, -- 51 to 60
614.4, 615.3, 616.7, 619.8, 623.4, 629.7, 635.0, 641.1, 650.6, 660.0, -- 61 to 70
672.5, 674.3, 676.1, 677.9, 679.7, 681.5, 683.3, 685.1, 686.8, 688.6, -- 71 to 80
}
altitude = altitude or 0
local a = (altitude < 0) and -altitude or altitude
a = floor(a / 5000 + 0.5)
if altitude < 0 then
a = -a
end
if a < -3 then
a = -3
elseif a > 80 then
a = 80
end
return mach_table[a + 4] * 0.44704 -- mph converted to m/s
end
-- END: Code required only for built-in units.
------------------------------------------------------------------------
local function add_style(parms, class)
-- Add selected template style to parms if not already present.
parms.templatestyles = parms.templatestyles or {}
if not parms.templatestyles[class] then
parms.templatestyles[class] = parms.frame:extensionTag({
name = 'templatestyles', args = { src = text_code.titles[class] }
})
end
end
local function get_styles(parms)
-- Return string of required template styles, empty if none.
if parms.templatestyles then
local t = {}
for _, v in pairs(parms.templatestyles) do
table.insert(t, v)
end
return table.concat(t)
end
return ''
end
local function get_range(word)
if word == "as" then
word = "and"
end
local ranges = text_code.ranges
return ranges.types[word] or ranges.types[ranges.aliases[word]]
end
local function check_mismatch(unit1, unit2)
-- If unit1 cannot be converted to unit2, return an error message table.
-- This allows conversion between units of the same type, and between
-- Nm (normally torque) and ftlb (energy), as in gun-related articles.
-- This works because Nm is the base unit (scale = 1) for both the
-- primary type (torque), and the alternate type (energy, where Nm = J).
-- A match occurs if the primary types are the same, or if unit1 matches
-- the alternate type of unit2, and vice versa. That provides a whitelist
-- of which conversions are permitted between normally incompatible types.
if unit1.utype == unit2.utype or
(unit1.utype == unit2.alttype and unit1.alttype == unit2.utype) then
return nil
end
return { 'cvt_mismatch', unit1.utype, unit2.utype }
end
local function override_from(out_table, in_table, fields)
-- Copy the specified fields from in_table to out_table, but do not
-- copy nil fields (keep any corresponding field in out_table).
for _, field in ipairs(fields) do
if in_table[field] then
out_table[field] = in_table[field]
end
end
end
local function shallow_copy(t)
-- Return a shallow copy of table t.
-- Do not need the features and overhead of the Scribunto mw.clone().
local result = {}
for k, v in pairs(t) do
result[k] = v
end
return result
end
local unit_mt = {
-- Metatable to get missing values for a unit that does not accept SI prefixes.
-- Warning: The boolean value 'false' is returned for any missing field
-- so __index is not called twice for the same field in a given unit.
__index = function (self, key)
local value
if key == 'name1' or key == 'sym_us' then
value = self.symbol
elseif key == 'name2' then
value = self.name1 .. plural_suffix
elseif key == 'name1_us' then
value = self.name1
if not rawget(self, 'name2_us') then
-- If name1_us is 'foot', do not make name2_us by appending plural_suffix.
self.name2_us = self.name2
end
elseif key == 'name2_us' then
local raw1_us = rawget(self, 'name1_us')
if raw1_us then
value = raw1_us .. plural_suffix
else
value = self.name2
end
elseif key == 'link' then
value = self.name1
else
value = false
end
rawset(self, key, value)
return value
end
}
local function prefixed_name(unit, name, index)
-- Return unit name with SI prefix inserted at correct position.
-- index = 1 (name1), 2 (name2), 3 (name1_us), 4 (name2_us).
-- The position is a byte (not character) index, so use Lua's sub().
local pos = rawget(unit, 'prefix_position')
if type(pos) == 'string' then
pos = tonumber(split(pos, ',')[index])
end
if pos then
return name:sub(1, pos - 1) .. unit.si_name .. name:sub(pos)
end
return unit.si_name .. name
end
local unit_prefixed_mt = {
-- Metatable to get missing values for a unit that accepts SI prefixes.
-- Before use, fields si_name, si_prefix must be defined.
-- The unit must define _symbol, _name1 and
-- may define _sym_us, _name1_us, _name2_us
-- (_sym_us, _name2_us may be defined for a language using sp=us
-- to refer to a variant unrelated to U.S. units).
__index = function (self, key)
local value
if key == 'symbol' then
value = self.si_prefix .. self._symbol
elseif key == 'sym_us' then
value = rawget(self, '_sym_us')
if value then
value = self.si_prefix .. value
else
value = self.symbol
end
elseif key == 'name1' then
value = prefixed_name(self, self._name1, 1)
elseif key == 'name2' then
value = rawget(self, '_name2')
if value then
value = prefixed_name(self, value, 2)
else
value = self.name1 .. plural_suffix
end
elseif key == 'name1_us' then
value = rawget(self, '_name1_us')
if value then
value = prefixed_name(self, value, 3)
else
value = self.name1
end
elseif key == 'name2_us' then
value = rawget(self, '_name2_us')
if value then
value = prefixed_name(self, value, 4)
elseif rawget(self, '_name1_us') then
value = self.name1_us .. plural_suffix
else
value = self.name2
end
elseif key == 'link' then
value = self.name1
else
value = false
end
rawset(self, key, value)
return value
end
}
local unit_per_mt = {
-- Metatable to get values for a per unit of form "x/y".
-- This is never called to determine a unit name or link because per units
-- are handled as a special case.
-- Similarly, the default output is handled elsewhere, and for a symbol
-- this is only called from get_default() for default_exceptions.
__index = function (self, key)
local value
if key == 'symbol' then
local per = self.per
local unit1, unit2 = per[1], per[2]
if unit1 then
value = unit1[key] .. '/' .. unit2[key]
else
value = '/' .. unit2[key]
end
elseif key == 'sym_us' then
value = self.symbol
elseif key == 'scale' then
local per = self.per
local unit1, unit2 = per[1], per[2]
value = (unit1 and unit1.scale or 1) * self.scalemultiplier / unit2.scale
else
value = false
end
rawset(self, key, value)
return value
end
}
local function make_per(unitcode, unit_table, ulookup)
-- Return true, t where t is a per unit with unit codes expanded to unit tables,
-- or return false, t where t is an error message table.
local result = {
unitcode = unitcode,
utype = unit_table.utype,
per = {}
}
override_from(result, unit_table, { 'invert', 'iscomplex', 'default', 'link', 'symbol', 'symlink' })
result.symbol_raw = (result.symbol or false) -- to distinguish between a defined exception and a metatable calculation
local prefix
for i, v in ipairs(unit_table.per) do
if i == 1 and v == '' then
-- First unit symbol can be empty; that gives a nil first unit table.
elseif i == 1 and text_code.currency[v] then
prefix = currency_text or v
else
local success, t = ulookup(v)
if not success then return false, t end
result.per[i] = t
end
end
local multiplier = unit_table.multiplier
if not result.utype then
-- Creating an automatic per unit.
local unit1 = result.per[1]
local utype = (unit1 and unit1.utype or prefix or '') .. '/' .. result.per[2].utype
local t = data_code.per_unit_fixups[utype]
if t then
if type(t) == 'table' then
utype = t.utype or utype
result.link = result.link or t.link
multiplier = multiplier or t.multiplier
else
utype = t
end
end
result.utype = utype
end
result.scalemultiplier = multiplier or 1
result.vprefix = prefix or false -- set to non-nil to avoid calling __index
return true, setmetatable(result, unit_per_mt)
end
local function lookup(parms, unitcode, what, utable, fails, depth)
-- Return true, t where t is a copy of the unit's converter table,
-- or return false, t where t is an error message table.
-- Parameter 'what' determines whether combination units are accepted:
-- 'no_combination' : single unit only
-- 'any_combination' : single unit or combination or output multiple
-- 'only_multiple' : single unit or output multiple only
-- Parameter unitcode is a symbol (like 'g'), with an optional SI prefix (like 'kg').
-- If, for example, 'kg' is in this table, that entry is used;
-- otherwise the prefix ('k') is applied to the base unit ('g').
-- If unitcode is a known combination code (and if allowed by what),
-- a table of output multiple unit tables is included in the result.
-- For compatibility with the old template, an underscore in a unitcode is
-- replaced with a space so usage like {{convert|350|board_feet}} works.
-- Wikignomes may also put two spaces or " " in combinations, so
-- replace underscore, " ", and multiple spaces with a single space.
utable = utable or parms.unittable or all_units
fails = fails or {}
depth = depth and depth + 1 or 1
if depth > 9 then
-- There are ways to mistakenly define units which result in infinite
-- recursion when lookup() is called. That gives a long delay and very
-- confusing error messages, so the depth parameter is used as a guard.
return false, { 'cvt_lookup', unitcode }
end
if unitcode == nil or unitcode == '' then
return false, { 'cvt_no_unit' }
end
unitcode = unitcode:gsub('_', ' '):gsub(' ', ' '):gsub(' +', ' ')
local function call_make_per(t)
return make_per(unitcode, t,
function (ucode) return lookup(parms, ucode, 'no_combination', utable, fails, depth) end
)
end
local t = utable[unitcode]
if t then
if t.shouldbe then
return false, { 'cvt_should_be', t.shouldbe }
end
if t.sp_us then
parms.opt_sp_us = true
end
local target = t.target -- nil, or unitcode is an alias for this target
if target then
local success, result = lookup(parms, target, what, utable, fails, depth)
if not success then return false, result end
override_from(result, t, { 'customary', 'default', 'link', 'symbol', 'symlink' })
local multiplier = t.multiplier
if multiplier then
result.multiplier = tostring(multiplier)
result.scale = result.scale * multiplier
end
return true, result
end
if t.per then
return call_make_per(t)
end
local combo = t.combination -- nil or a table of unitcodes
if combo then
local multiple = t.multiple
if what == 'no_combination' or (what == 'only_multiple' and not multiple) then
return false, { 'cvt_bad_unit', unitcode }
end
-- Recursively create a combination table containing the
-- converter table of each unitcode.
local result = { utype = t.utype, multiple = multiple, combination = {} }
local cvt = result.combination
for i, v in ipairs(combo) do
local success, t = lookup(parms, v, multiple and 'no_combination' or 'only_multiple', utable, fails, depth)
if not success then return false, t end
cvt[i] = t
end
return true, result
end
local result = shallow_copy(t)
result.unitcode = unitcode
if result.prefixes then
result.si_name = ''
result.si_prefix = ''
return true, setmetatable(result, unit_prefixed_mt)
end
return true, setmetatable(result, unit_mt)
end
local SIprefixes = text_code.SIprefixes
for plen = SIprefixes[1] or 2, 1, -1 do
-- Look for an SI prefix; should never occur with an alias.
-- Check for longer prefix first ('dam' is decametre).
-- SIprefixes[1] = prefix maximum #characters (as seen by mw.ustring.sub).
local prefix = usub(unitcode, 1, plen)
local si = SIprefixes[prefix]
if si then
local t = utable[usub(unitcode, plen+1)]
if t and t.prefixes then
local result = shallow_copy(t)
result.unitcode = unitcode
result.si_name = parms.opt_sp_us and si.name_us or si.name
result.si_prefix = si.prefix or prefix
result.scale = t.scale * 10 ^ (si.exponent * t.prefixes)
return true, setmetatable(result, unit_prefixed_mt)
end
end
end
-- Accept user-defined combinations like "acre+m2+ha" or "acre m2 ha" for output.
-- If '+' is used, each unit code can include a space, and any error is fatal.
-- If ' ' is used and if each space-separated word is a unit code, it is a combo,
-- but errors are not fatal so the unit code can be looked up as an extra unit.
local err_is_fatal
local combo = collection()
if unitcode:find('+', 1, true) then
err_is_fatal = true
for item in (unitcode .. '+'):gmatch('%s*(.-)%s*%+') do
if item ~= '' then
combo:add(item)
end
end
elseif unitcode:find('%s') then
for item in unitcode:gmatch('%S+') do
combo:add(item)
end
end
if combo.n > 1 then
local function lookup_combo()
if what == 'no_combination' or what == 'only_multiple' then
return false, { 'cvt_bad_unit', unitcode }
end
local result = { combination = {} }
local cvt = result.combination
for i, v in ipairs(combo) do
local success, t = lookup(parms, v, 'only_multiple', utable, fails, depth)
if not success then return false, t end
if i == 1 then
result.utype = t.utype
else
local mismatch = check_mismatch(result, t)
if mismatch then
return false, mismatch
end
end
cvt[i] = t
end
return true, result
end
local success, result = lookup_combo()
if success or err_is_fatal then
return success, result
end
end
-- Accept any unit with an engineering notation prefix like "e6cuft"
-- (million cubic feet), but not chained prefixes like "e3e6cuft",
-- and not if the unit is a combination or multiple,
-- and not if the unit has an offset or is a built-in.
-- Only en digits are accepted.
local exponent, baseunit = unitcode:match('^e(%d+)(.*)')
if exponent then
local engscale = text_code.eng_scales[exponent]
if engscale then
local success, result = lookup(parms, baseunit, 'no_combination', utable, fails, depth)
if success and not (result.offset or result.builtin or result.engscale) then
result.unitcode = unitcode -- 'e6cuft' not 'cuft'
result.defkey = unitcode -- key to lookup default exception
result.engscale = engscale
result.scale = result.scale * 10 ^ tonumber(exponent)
return true, result
end
end
end
-- Look for x/y; split on right-most slash to get scale correct (x/y/z is x/y per z).
local top, bottom = unitcode:match('^(.-)/([^/]+)$')
if top and not unitcode:find('e%d') then
-- If valid, create an automatic per unit for an "x/y" unit code.
-- The unitcode must not include extraneous spaces.
-- Engineering notation (apart from at start and which has been stripped before here),
-- is not supported so do not make a per unit if find text like 'e3' in unitcode.
local success, result = call_make_per({ per = {top, bottom} })
if success then
return true, result
end
end
if not parms.opt_ignore_error and not get_range(unitcode) then
-- Want the "what links here" list for the extra_module to show only cases
-- where an extra unit is used, so do not require it if invoked from {{val}}
-- or if looking up a range word which cannot be a unit.
if not extra_units then
local success, extra = pcall(function () return require(extra_module).extra_units end)
if success and type(extra) == 'table' then
extra_units = extra
end
end
if extra_units then
-- A unit in one data table might refer to a unit in the other table, so
-- switch between them, relying on fails or depth to terminate loops.
if not fails[unitcode] then
fails[unitcode] = true
local other = (utable == all_units) and extra_units or all_units
local success, result = lookup(parms, unitcode, what, other, fails, depth)
if success then
return true, result
end
end
end
end
if to_en_table then
-- At fawiki it is common to translate all digits so a unit like "km2" becomes "km۲".
local en_code = ustring.gsub(unitcode, '%d', to_en_table)
if en_code ~= unitcode then
return lookup(parms, en_code, what, utable, fails, depth)
end
end
return false, { 'cvt_unknown', unitcode }
end
local function valid_number(num)
-- Return true if num is a valid number.
-- In Scribunto (different from some standard Lua), when expressed as a string,
-- overflow or other problems are indicated with text like "inf" or "nan"
-- which are regarded as invalid here (each contains "n").
if type(num) == 'number' and tostring(num):find('n', 1, true) == nil then
return true
end
end
local function hyphenated(name, parts)
-- Return a hyphenated form of given name (for adjectival usage).
-- The name may be linked and the target of the link must not be changed.
-- Hypothetical examples:
-- [[long ton|ton]] → [[long ton|ton]] (no change)
-- [[tonne|long ton]] → [[tonne|long-ton]]
-- [[metric ton|long ton]] → [[metric ton|long-ton]]
-- [[long ton]] → [[long ton|long-ton]]
-- Input can also have multiple links in a single name like:
-- [[United States customary units|U.S.]] [[US gallon|gallon]]
-- [[mile]]s per [[United States customary units|U.S.]] [[quart]]
-- [[long ton]]s per [[short ton]]
-- Assume that links cannot be nested (never like "[[abc[[def]]ghi]]").
-- This uses a simple and efficient procedure that works for most cases.
-- Some units (if used) would require more, and can later think about
-- adding a method to handle exceptions.
-- The procedure is to replace each space with a hyphen, but
-- not a space after ')' [for "(pre-1954 US) nautical mile"], and
-- not spaces immediately before '(' or in '(...)' [for cases like
-- "British thermal unit (ISO)" and "Calorie (International Steam Table)"].
if name:find(' ', 1, true) then
if parts then
local pos
if name:sub(1, 1) == '(' then
pos = name:find(')', 1, true)
if pos then
return name:sub(1, pos+1) .. name:sub(pos+2):gsub(' ', '-')
end
elseif name:sub(-1) == ')' then
pos = name:find('(', 1, true)
if pos then
return name:sub(1, pos-2):gsub(' ', '-') .. name:sub(pos-1)
end
end
return name:gsub(' ', '-')
end
parts = collection()
for before, item, after in name:gmatch('([^[]*)(%[%[[^[]*%]%])([^[]*)') do
if item:find(' ', 1, true) then
local prefix
local plen = item:find('|', 1, true)
if plen then
prefix = item:sub(1, plen)
item = item:sub(plen + 1, -3)
else
prefix = item:sub(1, -3) .. '|'
item = item:sub(3, -3)
end
item = prefix .. hyphenated(item, parts) .. ']]'
end
parts:add(before:gsub(' ', '-') .. item .. after:gsub(' ', '-'))
end
if parts.n == 0 then
-- No link like "[[...]]" was found in the original name.
parts:add(hyphenated(name, parts))
end
return table.concat(parts)
end
return name
end
local function hyphenated_maybe(parms, want_name, sep, id, inout)
-- Return s, f where
-- s = id, possibly modified
-- f = true if hyphenated
-- Possible modifications: hyphenate; prepend '-'; append mid text.
if id == nil or id == '' then
return ''
end
local mid = (inout == (parms.opt_flip and 'out' or 'in')) and parms.mid or ''
if want_name then
if parms.opt_adjectival then
return '-' .. hyphenated(id) .. mid, true
end
if parms.opt_add_s and id:sub(-1) ~= 's' then
id = id .. 's' -- for nowiki
end
end
return sep .. id .. mid
end
local function use_minus(text)
-- Return text with Unicode minus instead of '-', if present.
if text:sub(1, 1) == '-' then
return MINUS .. text:sub(2)
end
return text
end
local function digit_groups(parms, text, method)
-- Return a numbered table of groups of digits (left-to-right, in local language).
-- Parameter method is a number or nil:
-- 3 for 3-digit grouping (default), or
-- 2 for 3-then-2 grouping (only for digits before decimal mark).
local len_right
local len_left = text:find('.', 1, true)
if len_left then
len_right = #text - len_left
len_left = len_left - 1
else
len_left = #text
end
local twos = method == 2 and len_left > 5
local groups = collection()
local run = len_left
local n
if run < 4 or (run == 4 and parms.opt_comma5) then
if parms.opt_gaps then
n = run
else
n = #text
end
elseif twos then
n = run % 2 == 0 and 1 or 2
else
n = run % 3 == 0 and 3 or run % 3
end
while run > 0 do
groups:add(n)
run = run - n
n = (twos and run > 3) and 2 or 3
end
if len_right then
if groups.n == 0 then
groups:add(0)
end
if parms.opt_gaps and len_right > 3 then
local want4 = not parms.opt_gaps3 -- true gives no gap before trailing single digit
local isfirst = true
run = len_right
while run > 0 do
n = (want4 and run == 4) and 4 or (run > 3 and 3 or run)
if isfirst then
isfirst = false
groups[groups.n] = groups[groups.n] + 1 + n
else
groups:add(n)
end
run = run - n
end
else
groups[groups.n] = groups[groups.n] + 1 + len_right
end
end
local pos = 1
for i, length in ipairs(groups) do
groups[i] = from_en(text:sub(pos, pos + length - 1))
pos = pos + length
end
return groups
end
function with_separator(parms, text) -- for forward declaration above
-- Input text is a number in en digits with optional '.' decimal mark.
-- Return an equivalent, formatted for display:
-- with a custom decimal mark instead of '.', if wanted
-- with thousand separators inserted, if wanted
-- digits in local language
-- The given text is like '123' or '123.' or '12345.6789'.
-- The text has no sign (caller inserts that later, if necessary).
-- When using gaps, they are inserted before and after the decimal mark.
-- Separators are inserted only before the decimal mark.
-- A trailing dot (as in '123.') is removed because their use appears to
-- be accidental, and such a number should be shown as '123' or '123.0'.
-- It is useful for convert to suppress the dot so, for example, '4000.'
-- is a simple way of indicating that all the digits are significant.
if text:sub(-1) == '.' then
text = text:sub(1, -2)
end
if #text < 4 or parms.opt_nocomma or numsep == '' then
return from_en(text)
end
local groups = digit_groups(parms, text, group_method)
if parms.opt_gaps then
if groups.n <= 1 then
return groups[1] or ''
end
local nowrap = '<span style="white-space: nowrap">'
local gap = '<span style="margin-left: 0.25em">'
local close = '</span>'
return nowrap .. groups[1] .. gap .. table.concat(groups, close .. gap, 2, groups.n) .. close .. close
end
return table.concat(groups, numsep)
end
-- An input value like 1.23e12 is displayed using scientific notation (1.23×10¹²).
-- That also makes the output use scientific notation, except for small values.
-- In addition, very small or very large output values use scientific notation.
-- Use format(fmtpower, significand, '10', exponent) where each argument is a string.
local fmtpower = '%s<span style="margin:0 .15em 0 .25em">×</span>%s<sup>%s</sup>'
local function with_exponent(parms, show, exponent)
-- Return wikitext to display the implied value in scientific notation.
-- Input uses en digits; output uses digits in local language.
return format(fmtpower, with_separator(parms, show), from_en('10'), use_minus(from_en(tostring(exponent))))
end
local function make_sigfig(value, sigfig)
-- Return show, exponent that are equivalent to the result of
-- converting the number 'value' (where value >= 0) to a string,
-- rounded to 'sigfig' significant figures.
-- The returned items are:
-- show: a string of digits; no sign and no dot;
-- there is an implied dot before show.
-- exponent: a number (an integer) to shift the implied dot.
-- Resulting value = tonumber('.' .. show) * 10^exponent.
-- Examples:
-- make_sigfig(23.456, 3) returns '235', 2 (.235 * 10^2).
-- make_sigfig(0.0023456, 3) returns '235', -2 (.235 * 10^-2).
-- make_sigfig(0, 3) returns '000', 1 (.000 * 10^1).
if sigfig <= 0 then
sigfig = 1
elseif sigfig > maxsigfig then
sigfig = maxsigfig
end
if value == 0 then
return string.rep('0', sigfig), 1
end
local exp, fracpart = math.modf(log10(value))
if fracpart >= 0 then
fracpart = fracpart - 1
exp = exp + 1
end
local digits = format('%.0f', 10^(fracpart + sigfig))
if #digits > sigfig then
-- Overflow (for sigfig=3: like 0.9999 rounding to "1000"; need "100").
digits = digits:sub(1, sigfig)
exp = exp + 1
end
assert(#digits == sigfig, 'Bug: rounded number has wrong length')
return digits, exp
end
-- Fraction output format.
local fracfmt = {
{ -- Like {{frac}} (fraction slash).
'<span class="frac" role="math">{SIGN}<span class="num">{NUM}</span>⁄<span class="den">{DEN}</span></span>', -- 1/2
'<span class="frac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="num">{NUM}</span>⁄<span class="den">{DEN}</span></span>', -- 1+2/3
style = 'frac',
},
{ -- Like {{sfrac}} (stacked fraction, that is, horizontal bar).
'<span class="sfrac tion" role="math">{SIGN}<span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span>', -- 1//2
'<span class="sfrac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="tion"><span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span></span>', -- 1+2//3
style = 'sfrac',
},
}
local function format_fraction(parms, inout, negative, wholestr, numstr, denstr, do_spell, style)
-- Return wikitext for a fraction, possibly spelled.
-- Inputs use en digits and have no sign; output uses digits in local language.
local wikitext
if not style then
style = parms.opt_fraction_horizontal and 2 or 1
end
if wholestr == '' then
wholestr = nil
end
local substitute = {
SIGN = negative and MINUS or '',
WHOLE = wholestr and with_separator(parms, wholestr),
NUM = from_en(numstr),
DEN = from_en(denstr),
}
wikitext = fracfmt[style][wholestr and 2 or 1]:gsub('{(%u+)}', substitute)
if do_spell then
if negative then
if wholestr then
wholestr = '-' .. wholestr
else
numstr = '-' .. numstr
end
end
local s = spell_number(parms, inout, wholestr, numstr, denstr)
if s then
return s
end
end
add_style(parms, fracfmt[style].style)
return wikitext
end
local function format_number(parms, show, exponent, isnegative)
-- Parameter show is a string or a table containing strings.
-- Each string is a formatted number in en digits and optional '.' decimal mark.
-- A table represents a fraction: integer, numerator, denominator;
-- if a table is given, exponent must be nil.
-- Return t where t is a table with fields:
-- show = wikitext formatted to display implied value
-- (digits in local language)
-- is_scientific = true if show uses scientific notation
-- clean = unformatted show (possibly adjusted and with inserted '.')
-- (en digits)
-- sign = '' or MINUS
-- exponent = exponent (possibly adjusted)
-- The clean and exponent fields can be used to calculate the
-- rounded absolute value, if needed.
--
-- The value implied by the arguments is found from:
-- exponent is nil; and
-- show is a string of digits (no sign), with an optional dot;
-- show = '123.4' is value 123.4, '1234' is value 1234.0;
-- or:
-- exponent is an integer indicating where dot should be;
-- show is a string of digits (no sign and no dot);
-- there is an implied dot before show;
-- show does not start with '0';
-- show = '1234', exponent = 3 is value 0.1234*10^3 = 123.4.
--
-- The formatted result:
-- * Is for an output value and is spelled if wanted and possible.
-- * Includes a Unicode minus if isnegative and not spelled.
-- * Uses a custom decimal mark, if wanted.
-- * Has digits grouped where necessary, if wanted.
-- * Uses scientific notation if requested, or for very small or large values
-- (which forces result to not be spelled).
-- * Has no more than maxsigfig significant digits
-- (same as old template and {{#expr}}).
local xhi, xlo -- these control when scientific notation (exponent) is used
if parms.opt_scientific then
xhi, xlo = 4, 2 -- default for output if input uses e-notation
elseif parms.opt_scientific_always then
xhi, xlo = 0, 0 -- always use scientific notation (experimental)
else
xhi, xlo = 10, 4 -- default
end
local sign = isnegative and MINUS or ''
local maxlen = maxsigfig
local tfrac
if type(show) == 'table' then
tfrac = show
show = tfrac.wholestr
assert(exponent == nil, 'Bug: exponent given with fraction')
end
if not tfrac and not exponent then
local integer, dot, decimals = show:match('^(%d*)(%.?)(.*)')
if integer == '0' or integer == '' then
local zeros, figs = decimals:match('^(0*)([^0]?.*)')
if #figs == 0 then
if #zeros > maxlen then
show = '0.' .. zeros:sub(1, maxlen)
end
elseif #zeros >= xlo then
show = figs
exponent = -#zeros
elseif #figs > maxlen then
show = '0.' .. zeros .. figs:sub(1, maxlen)
end
elseif #integer >= xhi then
show = integer .. decimals
exponent = #integer
else
maxlen = maxlen + #dot
if #show > maxlen then
show = show:sub(1, maxlen)
end
end
end
if exponent then
local function zeros(n)
return string.rep('0', n)
end
if #show > maxlen then
show = show:sub(1, maxlen)
end
if exponent > xhi or exponent <= -xlo or (exponent == xhi and show ~= '1' .. zeros(xhi - 1)) then
-- When xhi, xlo = 10, 4 (the default), scientific notation is used if the
-- rounded value satisfies: value >= 1e9 or value < 1e-4 (1e9 = 0.1e10),
-- except if show is '1000000000' (1e9), for example:
-- {{convert|1000000000|m|m|sigfig=10}} → 1,000,000,000 metres (1,000,000,000 m)
local significand
if #show > 1 then
significand = show:sub(1, 1) .. '.' .. show:sub(2)
else
significand = show
end
return {
clean = '.' .. show,
exponent = exponent,
sign = sign,
show = sign .. with_exponent(parms, significand, exponent-1),
is_scientific = true,
}
end
if exponent >= #show then
show = show .. zeros(exponent - #show) -- result has no dot
elseif exponent <= 0 then
show = '0.' .. zeros(-exponent) .. show
else
show = show:sub(1, exponent) .. '.' .. show:sub(exponent+1)
end
end
local formatted_show
if tfrac then
show = tostring(tfrac.value) -- to set clean in returned table
formatted_show = format_fraction(parms, 'out', isnegative, tfrac.wholestr, tfrac.numstr, tfrac.denstr, parms.opt_spell_out)
else
if isnegative and show:match('^0.?0*$') then
sign = '' -- don't show minus if result is negative but rounds to zero
end
formatted_show = sign .. with_separator(parms, show)
if parms.opt_spell_out then
formatted_show = spell_number(parms, 'out', sign .. show) or formatted_show
end
end
return {
clean = show,
sign = sign,
show = formatted_show,
is_scientific = false, -- to avoid calling __index
}
end
local function extract_fraction(parms, text, negative)
-- If text represents a fraction, return
-- value, altvalue, show, denominator
-- where
-- value is a number (value of the fraction in argument text)
-- altvalue is an alternate interpretation of any fraction for the hands
-- unit where "12.1+3/4" means 12 hands 1.75 inches
-- show is a string (formatted text for display of an input value,
-- and is spelled if wanted and possible)
-- denominator is value of the denominator in the fraction
-- Otherwise, return nil.
-- Input uses en digits and '.' decimal mark (input has been translated).
-- Output uses digits in local language and local decimal mark, if any.
------------------------------------------------------------------------
-- Originally this function accepted x+y/z where x, y, z were any valid
-- numbers, possibly with a sign. For example '1.23e+2+1.2/2.4' = 123.5,
-- and '2-3/8' = 1.625. However, such usages were found to be errors or
-- misunderstandings, so since August 2014 the following restrictions apply:
-- x (if present) is an integer or has a single digit after decimal mark
-- y and z are unsigned integers
-- e-notation is not accepted
-- The overall number can start with '+' or '-' (so '12+3/4' and '+12+3/4'
-- and '-12-3/4' are valid).
-- Any leading negative sign is removed by the caller, so only inputs
-- like the following are accepted here (may have whitespace):
-- negative = false false true (there was a leading '-')
-- text = '2/3' '+2/3' '2/3'
-- text = '1+2/3' '+1+2/3' '1-2/3'
-- text = '12.3+1/2' '+12.3+1/2' '12.3-1/2'
-- Values like '12.3+1/2' are accepted, but are intended only for use
-- with the hands unit (not worth adding code to enforce that).
------------------------------------------------------------------------
local leading_plus, prefix, numstr, slashes, denstr =
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*(/+)%s*(%d+)%s*$')
if not leading_plus then
-- Accept a single U+2044 fraction slash because that may be pasted.
leading_plus, prefix, numstr, denstr =
text:match('^%s*(%+?)%s*(.-)%s*(%d+)%s*⁄%s*(%d+)%s*$')
slashes = '/'
end
local numerator = tonumber(numstr)
local denominator = tonumber(denstr)
if numerator == nil or denominator == nil or (negative and leading_plus ~= '') then
return nil
end
local whole, wholestr
if prefix == '' then
wholestr = ''
whole = 0
else
-- Any prefix must be like '12+' or '12-' (whole number and fraction sign);
-- '12.3+' and '12.3-' are also accepted (single digit after decimal point)
-- because '12.3+1/2 hands' is valid (12 hands 3½ inches).
local num1, num2, frac_sign = prefix:match('^(%d+)(%.?%d?)%s*([+%-])$')
if num1 == nil then return nil end
if num2 == '' then -- num2 must be '' or like '.1' but not '.' or '.12'
wholestr = num1
else
if #num2 ~= 2 then return nil end
wholestr = num1 .. num2
end
if frac_sign ~= (negative and '-' or '+') then return nil end
whole = tonumber(wholestr)
if whole == nil then return nil end
end
local value = whole + numerator / denominator
if not valid_number(value) then return nil end
local altvalue = whole + numerator / (denominator * 10)
local style = #slashes -- kludge: 1 or 2 slashes can be used to select style
if style > 2 then style = 2 end
local wikitext = format_fraction(parms, 'in', negative, leading_plus .. wholestr, numstr, denstr, parms.opt_spell_in, style)
return value, altvalue, wikitext, denominator
end
local function extract_number(parms, text, another, no_fraction)
-- Return true, info if can extract a number from text,
-- where info is a table with the result,
-- or return false, t where t is an error message table.
-- Input can use en digits or digits in local language and can
-- have references at the end. Accepting references is intended
-- for use in infoboxes with a field for a value passed to convert.
-- Parameter another = true if the expected value is not the first.
-- Before processing, the input text is cleaned:
-- * Any thousand separators (valid or not) are removed.
-- * Any sign is replaced with '-' (if negative) or '' (otherwise).
-- That replaces Unicode minus with '-'.
-- If successful, the returned info table contains named fields:
-- value = a valid number
-- altvalue = a valid number, usually same as value but different
-- if fraction used (for hands unit)
-- singular = true if value is 1 or -1 (to use singular form of units)
-- clean = cleaned text with any separators and sign removed
-- (en digits and '.' decimal mark)
-- show = text formatted for output, possibly with ref strip markers
-- (digits in local language and custom decimal mark)
-- The resulting show:
-- * Is for an input value and is spelled if wanted and possible.
-- * Has a rounded value, if wanted.
-- * Has digits grouped where necessary, if wanted.
-- * If negative, a Unicode minus is used; otherwise the sign is
-- '+' (if the input text used '+'), or is '' (if no sign in input).
text = strip(text or '')
local reference
local pos = text:find('\127', 1, true)
if pos then
local before = text:sub(1, pos - 1)
local remainder = text:sub(pos)
local refs = {}
while #remainder > 0 do
local ref, spaces
ref, spaces, remainder = remainder:match('^(\127[^\127]*UNIQ[^\127]*%-ref[^\127]*\127)(%s*)(.*)')
if ref then
table.insert(refs, ref)
else
refs = {}
break
end
end
if #refs > 0 then
text = strip(before)
reference = table.concat(refs)
end
end
local clean = to_en(text, parms)
if clean == '' then
return false, { another and 'cvt_no_num2' or 'cvt_no_num' }
end
local isnegative, propersign = false, '' -- most common case
local singular, show, denominator
local value = tonumber(clean)
local altvalue
if value then
local sign = clean:sub(1, 1)
if sign == '+' or sign == '-' then
propersign = (sign == '+') and '+' or MINUS
clean = clean:sub(2)
end
if value < 0 then
isnegative = true
value = -value
end
else
local valstr
for _, prefix in ipairs({ '-', MINUS, '−' }) do
-- Including '-' sets isnegative in case input is a fraction like '-2-3/4'.
local plen = #prefix
if clean:sub(1, plen) == prefix then
valstr = clean:sub(plen + 1)
if valstr:match('^%s') then -- "- 1" is invalid but "-1 - 1/2" is ok
return false, { 'cvt_bad_num', text }
end
break
end
end
if valstr then
isnegative = true
propersign = MINUS
clean = valstr
value = tonumber(clean)
end
if value == nil then
if not no_fraction then
value, altvalue, show, denominator = extract_fraction(parms, clean, isnegative)
end
if value == nil then
return false, { 'cvt_bad_num', text }
end
if value <= 1 then
singular = true -- for example, "½ mile" or "one half mile" (singular unit)
end
end
end
if not valid_number(value) then -- for example, "1e310" may overflow
return false, { 'cvt_invalid_num' }
end
if show == nil then
-- clean is a non-empty string with no spaces, and does not represent a fraction,
-- and value = tonumber(clean) is a number >= 0.
-- If the input uses e-notation, show will be displayed using a power of ten, but
-- we use the number as given so it might not be normalized scientific notation.
-- The input value is spelled if specified so any e-notation is ignored;
-- that allows input like 2e6 to be spelled as "two million" which works
-- because the spell module converts '2e6' to '2000000' before spelling.
local function rounded(value, default, exponent)
local precision = parms.opt_ri
if precision then
local fmt = '%.' .. format('%d', precision) .. 'f'
local result = fmt:format(tonumber(value) + 2e-14) -- fudge for some common cases of bad rounding
if not exponent then
singular = (tonumber(result) == 1)
end
return result
end
return default
end
singular = (value == 1)
local scientific
local significand, exponent = clean:match('^([%d.]+)[Ee]([+%-]?%d+)')
if significand then
show = with_exponent(parms, rounded(significand, significand, exponent), exponent)
scientific = true
else
show = with_separator(parms, rounded(value, clean))
end
show = propersign .. show
if parms.opt_spell_in then
show = spell_number(parms, 'in', propersign .. rounded(value, clean)) or show
scientific = false
end
if scientific then
parms.opt_scientific = true
end
end
if isnegative and (value ~= 0) then
value = -value
altvalue = -(altvalue or value)
end
return true, {
value = value,
altvalue = altvalue or value,
singular = singular,
clean = clean,
show = show .. (reference or ''),
denominator = denominator,
}
end
local function get_number(text)
-- Return v, f where:
-- v = nil (text is not a number)
-- or
-- v = value of text (text is a number)
-- f = true if value is an integer
-- Input can use en digits or digits in local language or separators,
-- but no Unicode minus, and no fraction.
if text then
local number = tonumber(to_en(text))
if number then
local _, fracpart = math.modf(number)
return number, (fracpart == 0)
end
end
end
local function gcd(a, b)
-- Return the greatest common denominator for the given values,
-- which are known to be positive integers.
if a > b then
a, b = b, a
end
if a <= 0 then
return b
end
local r = b % a
if r <= 0 then
return a
end
if r == 1 then
return 1
end
return gcd(r, a)
end
local function fraction_table(value, denominator)
-- Return value as a string or a table:
-- * If result is a string, there is no fraction, and the result
-- is value formatted as a string of en digits.
-- * If result is a table, it represents a fraction with named fields:
-- wholestr, numstr, denstr (strings of en digits for integer, numerator, denominator).
-- The result is rounded to the nearest multiple of (1/denominator).
-- If the multiple is zero, no fraction is included.
-- No fraction is included if value is very large as the fraction would
-- be unhelpful, particularly if scientific notation is required.
-- Input value is a non-negative number.
-- Input denominator is a positive integer for the desired fraction.
if value <= 0 then
return '0'
end
if denominator <= 0 or value > 1e8 then
return format('%.2f', value)
end
local integer, decimals = math.modf(value)
local numerator = floor((decimals * denominator) +
0.5 + 2e-14) -- add fudge for some common cases of bad rounding
if numerator >= denominator then
integer = integer + 1
numerator = 0
end
local wholestr = tostring(integer)
if numerator > 0 then
local div = gcd(numerator, denominator)
if div > 1 then
numerator = numerator / div
denominator = denominator / div
end
return {
wholestr = (integer > 0) and wholestr or '',
numstr = tostring(numerator),
denstr = tostring(denominator),
value = value,
}
end
return wholestr
end
local function preunits(count, preunit1, preunit2)
-- If count is 1:
-- ignore preunit2
-- return p1
-- else:
-- preunit1 is used for preunit2 if the latter is empty
-- return p1, p2
-- where:
-- p1 is text to insert before the input unit
-- p2 is text to insert before the output unit
-- p1 or p2 may be nil to mean "no preunit"
-- Using '+' gives output like "5+ feet" (no space before, but space after).
local function withspace(text, wantboth)
-- Return text with space before and, if wantboth, after.
-- However, no space is added if there is a space or ' ' or '-'
-- at that position ('-' is for adjectival text).
-- There is also no space if text starts with '&'
-- (e.g. '°' would display a degree symbol with no preceding space).
local char = text:sub(1, 1)
if char == '&' then
return text -- an html entity can be used to specify the exact display
end
if not (char == ' ' or char == '-' or char == '+') then
text = ' ' .. text
end
if wantboth then
char = text:sub(-1, -1)
if not (char == ' ' or char == '-' or text:sub(-6, -1) == ' ') then
text = text .. ' '
end
end
return text
end
local PLUS = '+ '
preunit1 = preunit1 or ''
local trim1 = strip(preunit1)
if count == 1 then
if trim1 == '' then
return nil
end
if trim1 == '+' then
return PLUS
end
return withspace(preunit1, true)
end
preunit1 = withspace(preunit1)
preunit2 = preunit2 or ''
local trim2 = strip(preunit2)
if trim1 == '+' then
if trim2 == '' or trim2 == '+' then
return PLUS, PLUS
end
preunit1 = PLUS
end
if trim2 == '' then
if trim1 == '' then
return nil, nil
end
preunit2 = preunit1
elseif trim2 == '+' then
preunit2 = PLUS
elseif trim2 == ' ' then -- trick to make preunit2 empty
preunit2 = nil
else
preunit2 = withspace(preunit2)
end
return preunit1, preunit2
end
local function range_text(range, want_name, parms, before, after, inout, options)
-- Return before .. rtext .. after
-- where rtext is the text that separates two values in a range.
local rtext, adj_text, exception
options = options or {}
if type(range) == 'table' then
-- Table must specify range text for ('off' and 'on') or ('input' and 'output'),
-- and may specify range text for 'adj=on',
-- and may specify exception = true.
rtext = range[want_name and 'off' or 'on'] or
range[((inout == 'in') == (parms.opt_flip == true)) and 'output' or 'input']
adj_text = range['adj']
exception = range['exception']
else
rtext = range
end
if parms.opt_adjectival then
if want_name or (exception and parms.abbr_org == 'on') then
rtext = adj_text or rtext:gsub(' ', '-'):gsub(' ', '-')
end
end
if rtext == '–' and (options.spaced or after:sub(1, #MINUS) == MINUS) then
rtext = ' – '
end
return before .. rtext .. after
end
local function get_composite(parms, iparm, in_unit_table)
-- Look for a composite input unit. For example, {{convert|1|yd|2|ft|3|in}}
-- would result in a call to this function with
-- iparm = 3 (parms[iparm] = "2", just after the first unit)
-- in_unit_table = (unit table for "yd"; contains value 1 for number of yards)
-- Return true, iparm, unit where
-- iparm = index just after the composite units (7 in above example)
-- unit = composite unit table holding all input units,
-- or return true if no composite unit is present in parms,
-- or return false, t where t is an error message table.
local default, subinfo
local composite_units, count = { in_unit_table }, 1
local fixups = {}
local total = in_unit_table.valinfo[1].value
local subunit = in_unit_table
while subunit.subdivs do -- subdivs is nil or a table of allowed subdivisions
local subcode = strip(parms[iparm+1])
local subdiv = subunit.subdivs[subcode] or subunit.subdivs[(all_units[subcode] or {}).target]
if not subdiv then
break
end
local success
success, subunit = lookup(parms, subcode, 'no_combination')
if not success then return false, subunit end -- should never occur
success, subinfo = extract_number(parms, parms[iparm])
if not success then return false, subinfo end
iparm = iparm + 2
subunit.inout = 'in'
subunit.valinfo = { subinfo }
-- Recalculate total as a number of subdivisions.
-- subdiv[1] = number of subdivisions per previous unit (integer > 1).
total = total * subdiv[1] + subinfo.value
if not default then -- set by the first subdiv with a default defined
default = subdiv.default
end
count = count + 1
composite_units[count] = subunit
if subdiv.unit or subdiv.name then
fixups[count] = { unit = subdiv.unit, name = subdiv.name, valinfo = subunit.valinfo }
end
end
if count == 1 then
return true -- no error and no composite unit
end
for i, fixup in pairs(fixups) do
local unit = fixup.unit
local name = fixup.name
if not unit or (count > 2 and name) then
composite_units[i].fixed_name = name
else
local success, alternate = lookup(parms, unit, 'no_combination')
if not success then return false, alternate end -- should never occur
alternate.inout = 'in'
alternate.valinfo = fixup.valinfo
composite_units[i] = alternate
end
end
return true, iparm, {
utype = in_unit_table.utype,
scale = subunit.scale, -- scale of last (least significant) unit
valinfo = { { value = total, clean = subinfo.clean, denominator = subinfo.denominator } },
composite = composite_units,
default = default or in_unit_table.default
}
end
local function translate_parms(parms, kv_pairs)
-- Update fields in parms by translating each key:value in kv_pairs to terms
-- used by this module (may involve translating from local language to English).
-- Also, checks are performed which may display warnings, if enabled.
-- Return true if successful or return false, t where t is an error message table.
currency_text = nil -- local testing can hold module in memory; must clear globals
if kv_pairs.adj and kv_pairs.sing then
-- For enwiki (before translation), warn if attempt to use adj and sing
-- as the latter is a deprecated alias for the former.
if kv_pairs.adj ~= kv_pairs.sing and kv_pairs.sing ~= '' then
add_warning(parms, 1, 'cvt_unknown_option', 'sing=' .. kv_pairs.sing)
end
kv_pairs.sing = nil
end
kv_pairs.comma = kv_pairs.comma or config.comma -- for plwiki who want default comma=5
for loc_name, loc_value in pairs(kv_pairs) do
local en_name = text_code.en_option_name[loc_name]
if en_name then
local en_value = text_code.en_option_value[en_name]
if en_value == 'INTEGER' then -- altitude_ft, altitude_m, frac, sigfig
en_value = nil
if loc_value == '' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
else
local minimum
local number, is_integer = get_number(loc_value)
if en_name == 'sigfig' then
minimum = 1
elseif en_name == 'frac' then
minimum = 2
if number and number < 0 then
parms.opt_fraction_horizontal = true
number = -number
end
else
minimum = -1e6
end
if number and is_integer and number >= minimum then
en_value = number
else
local m
if en_name == 'frac' then
m = 'cvt_bad_frac'
elseif en_name == 'sigfig' then
m = 'cvt_bad_sigfig'
else
m = 'cvt_bad_altitude'
end
add_warning(parms, 1, m, loc_name .. '=' .. loc_value)
end
end
elseif en_value == 'TEXT' then -- $, input, qid, qual, stylein, styleout, tracking
en_value = loc_value ~= '' and loc_value or nil -- accept non-empty user text with no validation
if not en_value and (en_name == '$' or en_name == 'qid' or en_name == 'qual') then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
elseif en_name == '$' then
-- Value should be a single character like "€" for the euro currency symbol, but anything is accepted.
currency_text = (loc_value == 'euro') and '€' or loc_value
elseif en_name == 'input' then
-- May have something like {{convert|input=}} (empty input) if source is an infobox
-- with optional fields. In that case, want to output nothing rather than an error.
parms.input_text = loc_value -- keep input because parms.input is nil if loc_value == ''
end
else
en_value = en_value[loc_value]
if en_value and en_value:sub(-1) == '?' then
en_value = en_value:sub(1, -2)
add_warning(parms, -1, 'cvt_deprecated', loc_name .. '=' .. loc_value)
end
if en_value == nil then
if loc_value == '' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
end
elseif en_value == '' then
en_value = nil -- an ignored option like adj=off
elseif type(en_value) == 'string' and en_value:sub(1, 4) == 'opt_' then
for _, v in ipairs(split(en_value, ',')) do
local lhs, rhs = v:match('^(.-)=(.+)$')
if rhs then
parms[lhs] = tonumber(rhs) or rhs
else
parms[v] = true
end
end
en_value = nil
end
end
parms[en_name] = en_value
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
end
end
local abbr_entered = parms.abbr
local cfg_abbr = config.abbr
if cfg_abbr then
-- Don't warn if invalid because every convert would show that warning.
if cfg_abbr == 'on always' then
parms.abbr = 'on'
elseif cfg_abbr == 'off always' then
parms.abbr = 'off'
elseif parms.abbr == nil then
if cfg_abbr == 'on default' then
parms.abbr = 'on'
elseif cfg_abbr == 'off default' then
parms.abbr = 'off'
end
end
end
if parms.abbr then
if parms.abbr == 'unit' then
parms.abbr = 'on'
parms.number_word = true
end
parms.abbr_org = parms.abbr -- original abbr, before any flip
elseif parms.opt_hand_hh then
parms.abbr_org = 'on'
parms.abbr = 'on'
else
parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name)
end
if parms.opt_order_out then
-- Disable options that do not work in a useful way with order=out.
parms.opt_flip = nil -- override adj=flip
parms.opt_spell_in = nil
parms.opt_spell_out = nil
parms.opt_spell_upper = nil
end
if parms.opt_spell_out and not abbr_entered then
parms.abbr = 'off' -- should show unit name when spelling the output value
end
if parms.opt_flip then
local function swap_in_out(option)
local value = parms[option]
if value == 'in' then
parms[option] = 'out'
elseif value == 'out' then
parms[option] = 'in'
end
end
swap_in_out('abbr')
swap_in_out('lk')
if parms.opt_spell_in and not parms.opt_spell_out then
-- For simplicity, and because it does not appear to be needed,
-- user cannot set an option to spell the output only.
parms.opt_spell_in = nil
parms.opt_spell_out = true
end
end
if parms.opt_spell_upper then
parms.spell_upper = parms.opt_flip and 'out' or 'in'
end
if parms.opt_table or parms.opt_tablecen then
if abbr_entered == nil and parms.lk == nil then
parms.opt_values = true
end
parms.table_align = parms.opt_table and 'right' or 'center'
end
if parms.table_align or parms.opt_sortable_on then
parms.need_table_or_sort = true
end
local disp_joins = text_code.disp_joins
local default_joins = disp_joins['b']
parms.join_between = default_joins[3] or '; '
local disp = parms.disp
if disp == nil then -- special case for the most common setting
parms.joins = default_joins
elseif disp == 'x' then
-- Later, parms.joins is set from the input parameters.
else
-- Old template does this.
local abbr = parms.abbr
if disp == 'slash' then
if abbr_entered == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
disp = 'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
parms.joins = disp_joins[disp] or default_joins
parms.join_between = parms.joins[3] or parms.join_between
parms.wantname = parms.joins.wantname
end
if (en_default and not parms.opt_lang_local and (parms[1] or ''):find('%d')) or parms.opt_lang_en then
from_en_table = nil
end
if en_default and from_en_table then
-- For hiwiki: localized symbol/name is defined with the US symbol/name field,
-- and is used if output uses localized numbers.
parms.opt_sp_us = true
end
return true
end
local function get_values(parms)
-- If successful, update parms and return true, v, i where
-- v = table of input values
-- i = index to next entry in parms after those processed here
-- or return false, t where t is an error message table.
local valinfo = collection() -- numbered table of input values
local range = collection() -- numbered table of range items (having, for example, 2 range items requires 3 input values)
local had_nocomma -- true if removed "nocomma" kludge from second parameter (like "tonocomma")
local parm2 = strip(parms[2])
if parm2 and parm2:sub(-7, -1) == 'nocomma' then
parms[2] = strip(parm2:sub(1, -8))
parms.opt_nocomma = true
had_nocomma = true
end
local function extractor(i)
-- If the parameter is not a value, try unpacking it as a range ("1-23" for "1 to 23").
-- However, "-1-2/3" is a negative fraction (-1⅔), so it must be extracted first.
-- Do not unpack a parameter if it is like "3-1/2" which is sometimes incorrectly
-- used instead of "3+1/2" (and which should not be interpreted as "3 to ½").
-- Unpacked items are inserted into the parms table.
-- The tail recursion allows combinations like "1x2 to 3x4".
local valstr = strip(parms[i]) -- trim so any '-' as a negative sign will be at start
local success, result = extract_number(parms, valstr, i > 1)
if not success and valstr and i < 20 then -- check i to limit abuse
local lhs, sep, rhs = valstr:match('^(%S+)%s+(%S+)%s+(%S.*)')
if lhs and not (sep == '-' and rhs:match('/')) then
if sep:find('%d') then
return success, result -- to reject {{convert|1 234 567|m}} with a decent message (en only)
end
parms[i] = rhs
table.insert(parms, i, sep)
table.insert(parms, i, lhs)
return extractor(i)
end
if not valstr:match('%-.*/') then
for _, sep in ipairs(text_code.ranges.words) do
local start, stop = valstr:find(sep, 2, true) -- start at 2 to skip any negative sign for range '-'
if start then
parms[i] = valstr:sub(stop + 1)
table.insert(parms, i, sep)
table.insert(parms, i, valstr:sub(1, start - 1))
return extractor(i)
end
end
end
end
return success, result
end
local i = 1
local is_change
while true do
local success, info = extractor(i) -- need to set parms.opt_nocomma before calling this
if not success then return false, info end
i = i + 1
if is_change then
info.is_change = true -- value is after "±" and so is a change (significant for range like {{convert|5|±|5|°C}})
is_change = nil
end
valinfo:add(info)
local range_item = get_range(strip(parms[i]))
if not range_item then
break
end
i = i + 1
range:add(range_item)
if type(range_item) == 'table' then
-- For range "x", if append unit to some values, append it to all.
parms.in_range_x = parms.in_range_x or range_item.in_range_x
parms.out_range_x = parms.out_range_x or range_item.out_range_x
parms.abbr_range_x = parms.abbr_range_x or range_item.abbr_range_x
is_change = range_item.is_range_change
end
end
if range.n > 0 then
if range.n > 30 then -- limit abuse, although 4 is a more likely upper limit
return false, { 'cvt_invalid_num' } -- misleading message but it will do
end
parms.range = range
elseif had_nocomma then
return false, { 'cvt_unknown', parm2 }
end
return true, valinfo, i
end
local function simple_get_values(parms)
-- If input is like "{{convert|valid_value|valid_unit|...}}",
-- return true, i, in_unit, in_unit_table
-- i = index in parms of what follows valid_unit, if anything.
-- The valid_value is not negative and does not use a fraction, and
-- no options requiring further processing of the input are used.
-- Otherwise, return nothing or return false, parm1 for caller to interpret.
-- Testing shows this function is successful for 96% of converts in articles,
-- and that on average it speeds up converts by 8%.
local clean = to_en(strip(parms[1] or ''), parms)
if parms.opt_ri or parms.opt_spell_in or #clean > 10 or not clean:match('^[0-9.]+$') then
return false, clean
end
local value = tonumber(clean)
if not value then return end
local info = {
value = value,
altvalue = value,
singular = (value == 1),
clean = clean,
show = with_separator(parms, clean),
}
local in_unit = strip(parms[2])
-- A range word may also be a valid unit code (e.g. Manx "as" / attosecond).
-- Let the full parser handle ranges before trying the fast unit lookup.
if get_range(in_unit) then
return
end
local success, in_unit_table = lookup(parms, in_unit, 'no_combination')
if not success then return end
in_unit_table.valinfo = { info }
return true, 3, in_unit, in_unit_table
end
local function wikidata_call(parms, operation, ...)
-- Return true, s where s is the result of a Wikidata operation,
-- or return false, t where t is an error message table.
local function worker(...)
wikidata_code = wikidata_code or require(wikidata_module)
wikidata_data = wikidata_data or mw.loadData(wikidata_data_module)
return wikidata_code[operation](wikidata_data, ...)
end
local success, status, result = pcall(worker, ...)
if success then
return status, result
end
if parms.opt_sortable_debug then
-- Use debug=yes to crash if an error while accessing Wikidata.
error('Error accessing Wikidata: ' .. status, 0)
end
return false, { 'cvt_wd_fail' }
end
local function get_parms(parms, args)
-- If successful, update parms and return true, unit where
-- parms is a table of all arguments passed to the template
-- converted to named arguments, and
-- unit is the input unit table;
-- or return false, t where t is an error message table.
-- For special processing (not a convert), can also return
-- true, wikitext where wikitext is the final result.
-- The returned input unit table may be for a fake unit using the specified
-- unit code as the symbol and name, and with bad_mcode = message code table.
-- MediaWiki removes leading and trailing whitespace from the values of
-- named arguments. However, the values of numbered arguments include any
-- whitespace entered in the template, and whitespace is used by some
-- parameters (example: the numbered parameters associated with "disp=x").
local kv_pairs = {} -- table of input key:value pairs where key is a name; needed because cannot iterate parms and add new fields to it
for k, v in pairs(args) do
if type(k) == 'number' or k == 'test' then -- parameter "test" is reserved for testing and is not translated
parms[k] = v
else
kv_pairs[k] = v
end
end
if parms.test == 'wikidata' then
local ulookup = function (ucode)
-- Use empty table for parms so it does not accumulate results when used repeatedly.
return lookup({}, ucode, 'no_combination')
end
return wikidata_call(parms, '_listunits', ulookup)
end
local success, msg = translate_parms(parms, kv_pairs)
if not success then return false, msg end
if parms.input then
success, msg = wikidata_call(parms, '_adjustparameters', parms, 1)
if not success then return false, msg end
end
local success, i, in_unit, in_unit_table = simple_get_values(parms)
if not success then
if type(i) == 'string' and i:match('^NNN+$') then
-- Some infoboxes have examples like {{convert|NNN|m}} (3 or more "N").
-- Output an empty string for these.
return false, { 'cvt_no_output' }
end
local valinfo
success, valinfo, i = get_values(parms)
if not success then return false, valinfo end
in_unit = strip(parms[i])
i = i + 1
success, in_unit_table = lookup(parms, in_unit, 'no_combination')
if not success then
in_unit = in_unit or ''
if parms.opt_ignore_error then -- display given unit code with no error (for use with {{val}})
in_unit_table = '' -- suppress error message and prevent processing of output unit
end
in_unit_table = setmetatable({
symbol = in_unit, name2 = in_unit, utype = in_unit,
scale = 1, default = '', defkey = '', linkey = '',
bad_mcode = in_unit_table }, unit_mt)
end
in_unit_table.valinfo = valinfo
end
if parms.test == 'msg' then
-- Am testing the messages produced when no output unit is specified, and
-- the input unit has a missing or invalid default.
-- Set two units for testing that.
-- LATER: Remove this code.
if in_unit == 'chain' then
in_unit_table.default = nil -- no default
elseif in_unit == 'rd' then
in_unit_table.default = "ft!X!m" -- an invalid expression
end
end
in_unit_table.inout = 'in' -- this is an input unit
if not parms.range then
local success, inext, composite_unit = get_composite(parms, i, in_unit_table)
if not success then return false, inext end
if composite_unit then
in_unit_table = composite_unit
i = inext
end
end
if in_unit_table.builtin == 'mach' then
-- As with old template, a number following Mach as the input unit is the altitude.
-- That is deprecated: should use altitude_ft=NUMBER or altitude_m=NUMBER.
local success, info
success = tonumber(parms[i]) -- this will often work and will give correct result for values like 2e4 without forcing output scientific notation
if success then
info = { value = success }
else
success, info = extract_number(parms, parms[i], false, true)
end
if success then
i = i + 1
in_unit_table.altitude = info.value
end
end
local word = strip(parms[i])
i = i + 1
local precision, is_bad_precision
local function set_precision(text)
local number, is_integer = get_number(text)
if number then
if is_integer then
precision = number
else
precision = text
is_bad_precision = true
end
return true -- text was used for precision, good or bad
end
end
if word and not set_precision(word) then
parms.out_unit = parms.out_unit or word
if set_precision(strip(parms[i])) then
i = i + 1
end
end
if parms.opt_adj_mid then
word = parms[i]
i = i + 1
if word then -- mid-text words
if word:sub(1, 1) == '-' then
parms.mid = word
else
parms.mid = ' ' .. word
end
end
end
if parms.opt_one_preunit then
parms[parms.opt_flip and 'preunit2' or 'preunit1'] = preunits(1, parms[i])
i = i + 1
end
if parms.disp == 'x' then
-- Following is reasonably compatible with the old template.
local first = parms[i] or ''
local second = parms[i+1] or ''
i = i + 2
if strip(first) == '' then -- user can enter ' ' rather than ' ' to avoid the default
first = ' [ ' .. first
second = ' ]' .. second
end
parms.joins = { first, second }
elseif parms.opt_two_preunits then
local p1, p2 = preunits(2, parms[i], parms[i+1])
i = i + 2
if parms.preunit1 then
-- To simplify documentation, allow unlikely use of adj=pre with disp=preunit
-- (however, an output unit must be specified with adj=pre and with disp=preunit).
parms.preunit1 = parms.preunit1 .. p1
parms.preunit2 = p2
else
parms.preunit1, parms.preunit2 = p1, p2
end
end
if precision == nil then
if set_precision(strip(parms[i])) then
i = i + 1
end
end
if is_bad_precision then
add_warning(parms, 1, 'cvt_bad_prec', precision)
else
parms.precision = precision
end
for j = i, i + 3 do
local parm = parms[j] -- warn if find a non-empty extraneous parameter
if parm and parm:match('%S') then
add_warning(parms, 1, 'cvt_unknown_option', parm)
break
end
end
return true, in_unit_table
end
local function record_default_precision(parms, out_current, precision)
-- If necessary, adjust parameters and return a possibly adjusted precision.
-- When converting a range of values where a default precision is required,
-- that default is calculated for each value because the result sometimes
-- depends on the precise input and output values. This function may cause
-- the entire convert process to be repeated in order to ensure that the
-- same default precision is used for each individual convert.
-- If that were not done, a range like 1000 to 1000.4 may give poor results
-- because the first output could be heavily rounded, while the second is not.
-- For range 1000.4 to 1000, this function can give the second convert the
-- same default precision that was used for the first.
if not parms.opt_round_each then
local maxdef = out_current.max_default_precision
if maxdef then
if maxdef < precision then
parms.do_convert_again = true
out_current.max_default_precision = precision
else
precision = out_current.max_default_precision
end
else
out_current.max_default_precision = precision
end
end
return precision
end
local function default_precision(parms, invalue, inclean, denominator, outvalue, in_current, out_current, extra)
-- Return a default value for precision (an integer like 2, 0, -2).
-- If denominator is not nil, it is the value of the denominator in inclean.
-- Code follows procedures used in old template.
local fudge = 1e-14 -- {{Order of magnitude}} adds this, so we do too
local prec, minprec, adjust
local subunit_ignore_trailing_zero
local subunit_more_precision -- kludge for "in" used in input like "|2|ft|6|in"
local composite = in_current.composite
if composite then
subunit_ignore_trailing_zero = true -- input "|2|st|10|lb" has precision 0, not -1
if composite[#composite].exception == 'subunit_more_precision' then
subunit_more_precision = true -- do not use standard precision with input like "|2|ft|6|in"
end
end
if denominator and denominator > 0 then
prec = math.max(log10(denominator), 1)
else
-- Count digits after decimal mark, handling cases like '12.345e6'.
local exponent
local integer, dot, decimals, expstr = inclean:match('^(%d*)(%.?)(%d*)(.*)')
local e = expstr:sub(1, 1)
if e == 'e' or e == 'E' then
exponent = tonumber(expstr:sub(2))
end
if dot == '' then
prec = subunit_ignore_trailing_zero and 0 or -integer:match('0*$'):len()
else
prec = #decimals
end
if exponent then
-- So '1230' and '1.23e3' both give prec = -1, and '0.00123' and '1.23e-3' give 5.
prec = prec - exponent
end
end
if in_current.istemperature and out_current.istemperature then
-- Converting between common temperatures (°C, °F, °R, K); not keVT.
-- Kelvin value can be almost zero, or small but negative due to precision problems.
-- Also, an input value like -300 C (below absolute zero) gives negative kelvins.
-- Calculate minimum precision from absolute value.
adjust = 0
local kelvin = abs((invalue - in_current.offset) * in_current.scale)
if kelvin < 1e-8 then -- assume nonzero due to input or calculation precision problem
minprec = 2
else
minprec = 2 - floor(log10(kelvin) + fudge) -- 3 sigfigs in kelvin
end
else
if invalue == 0 or outvalue <= 0 then
-- We are never called with a negative outvalue, but it might be zero.
-- This is special-cased to avoid calculation exceptions.
return record_default_precision(parms, out_current, 0)
end
if out_current.exception == 'integer_more_precision' and floor(invalue) == invalue then
-- With certain output units that sometimes give poor results
-- with default rounding, use more precision when the input
-- value is equal to an integer. An example of a poor result
-- is when input 50 gives a smaller output than input 49.5.
-- Experiment shows this helps, but it does not eliminate all
-- surprises because it is not clear whether "50" should be
-- interpreted as "from 45 to 55" or "from 49.5 to 50.5".
adjust = -log10(in_current.scale)
elseif subunit_more_precision then
-- Conversion like "{{convert|6|ft|1|in|cm}}" (where subunit is "in")
-- has a non-standard adjust value, to give more output precision.
adjust = log10(out_current.scale) + 2
else
adjust = log10(abs(invalue / outvalue))
end
adjust = adjust + log10(2)
-- Ensure that the output has at least two significant figures.
minprec = 1 - floor(log10(outvalue) + fudge)
end
if extra then
adjust = extra.adjust or adjust
minprec = extra.minprec or minprec
end
return record_default_precision(parms, out_current, math.max(floor(prec + adjust), minprec))
end
local function convert(parms, invalue, info, in_current, out_current)
-- Convert given input value from one unit to another.
-- Return output_value (a number) if a simple convert, or
-- return f, t where
-- f = true, t = table of information with results, or
-- f = false, t = error message table.
local inscale = in_current.scale
local outscale = out_current.scale
if not in_current.iscomplex and not out_current.iscomplex then
return invalue * (inscale / outscale) -- minimize overhead for most common case
end
if in_current.invert or out_current.invert then
-- Inverted units, such as inverse length, inverse time, or
-- fuel efficiency. Built-in units do not have invert set.
if (in_current.invert or 1) * (out_current.invert or 1) < 0 then
return 1 / (invalue * inscale * outscale)
end
return invalue * (inscale / outscale)
elseif in_current.offset then
-- Temperature (there are no built-ins for this type of unit).
if info.is_change then
return invalue * (inscale / outscale)
end
return (invalue - in_current.offset) * (inscale / outscale) + out_current.offset
else
-- Built-in unit.
local in_builtin = in_current.builtin
local out_builtin = out_current.builtin
if in_builtin and out_builtin then
if in_builtin == out_builtin then
return invalue
end
-- There are no cases (yet) where need to convert from one
-- built-in unit to another, so this should never occur.
return false, { 'cvt_bug_convert' }
end
if in_builtin == 'mach' or out_builtin == 'mach' then
-- Should check that only one altitude is given but am planning to remove
-- in_current.altitude (which can only occur when Mach is the input unit),
-- and out_current.altitude cannot occur.
local alt = parms.altitude_ft or in_current.altitude
if not alt and parms.altitude_m then
alt = parms.altitude_m / 0.3048 -- 1 ft = 0.3048 m
end
local spd = speed_of_sound(alt)
if in_builtin == 'mach' then
inscale = spd
return invalue * (inscale / outscale)
end
outscale = spd
local adjust = 0.1 / inscale
return true, {
outvalue = invalue * (inscale / outscale),
adjust = log10(adjust) + log10(2),
}
elseif in_builtin == 'hand' then
-- 1 hand = 4 inches; 1.2 hands = 6 inches.
-- Decimals of a hand are only defined for the first digit, and
-- the first fractional digit should be a number of inches (1, 2 or 3).
-- However, this code interprets the entire fractional part as the number
-- of inches / 10 (so 1.75 inches would be 0.175 hands).
-- A value like 12.3 hands is exactly 12*4 + 3 inches; base default precision on that.
local integer, fracpart = math.modf(invalue)
local inch_value = 4 * integer + 10 * fracpart -- equivalent number of inches
local factor = inscale / outscale
if factor == 4 then
-- Am converting to inches: show exact result, and use "inches" not "in" by default.
if parms.abbr_org == nil then
out_current.usename = true
end
local show = format('%g', abs(inch_value)) -- show and clean are unsigned
if not show:find('e', 1, true) then
return true, {
invalue = inch_value,
outvalue = inch_value,
clean = show,
show = show,
}
end
end
local outvalue = (integer + 2.5 * fracpart) * factor
local fracstr = info.clean:match('%.(.*)') or ''
local fmt
if fracstr == '' then
fmt = '%.0f'
else
fmt = '%.' .. format('%d', #fracstr - 1) .. 'f'
end
return true, {
invalue = inch_value,
clean = format(fmt, inch_value),
outvalue = outvalue,
minprec = 0,
}
end
end
return false, { 'cvt_bug_convert' } -- should never occur
end
local function user_style(parms, i)
-- Return text for a user-specified style for a table cell, or '' if none,
-- given i = 1 (input style) or 2 (output style).
local style = parms[(i == 1) and 'stylein' or 'styleout']
if style then
style = style:gsub('"', '')
if style ~= '' then
if style:sub(-1) ~= ';' then
style = style .. ';'
end
return style
end
end
return ''
end
local function make_table_or_sort(parms, invalue, info, in_current, scaled_top)
-- Set options to handle output for a table or a sort key, or both.
-- The text sort key is based on the value resulting from converting
-- the input to a fake base unit with scale = 1, and other properties
-- required for a conversion derived from the input unit.
-- For other modules, return the sort key in a hidden span element, and
-- the scaled value used to generate the sort key.
-- If scaled_top is set, it is the scaled value of the numerator of a per unit
-- to be combined with this unit (the denominator) to make the sort key.
-- Scaling only works with units that convert with a factor (not temperature).
local sortkey, scaled_value
if parms.opt_sortable_on then
local base = { -- a fake unit with enough fields for a valid convert
scale = 1,
invert = in_current.invert and 1,
iscomplex = in_current.iscomplex,
offset = in_current.offset and 0,
}
local outvalue, extra = convert(parms, invalue, info, in_current, base)
if extra then
outvalue = extra.outvalue
end
if in_current.istemperature then
-- Have converted to kelvin; assume numbers close to zero have a
-- rounding error and should be zero.
if abs(outvalue) < 1e-12 then
outvalue = 0
end
end
if scaled_top and outvalue ~= 0 then
outvalue = scaled_top / outvalue
end
scaled_value = outvalue
if not valid_number(outvalue) then
if outvalue < 0 then
sortkey = '1000000000000000000'
else
sortkey = '9000000000000000000'
end
elseif outvalue == 0 then
sortkey = '5000000000000000000'
else
local mag = floor(log10(abs(outvalue)) + 1e-14)
local prefix
if outvalue > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
outvalue = outvalue + 10^(mag+1)
end
sortkey = format('%d', prefix) .. format('%015.0f', floor(outvalue * 10^(14-mag)))
end
end
local sortspan
if sortkey and not parms.table_align then
sortspan = parms.opt_sortable_debug and
'<span data-sort-value="' .. sortkey .. '♠"><span style="border:1px solid">' .. sortkey .. '♠</span></span>' or
'<span data-sort-value="' .. sortkey .. '♠"></span>'
parms.join_before = sortspan
end
if parms.table_align then
local sort
if sortkey then
sort = ' data-sort-value="' .. sortkey .. '"'
if parms.opt_sortable_debug then
parms.join_before = '<span style="border:1px solid">' .. sortkey .. '</span>'
end
else
sort = ''
end
local style = 'style="text-align:' .. parms.table_align .. ';'
local joins = {}
for i = 1, 2 do
joins[i] = (i == 1 and '' or '\n|') .. style .. user_style(parms, i) .. '"' .. sort .. '|'
end
parms.table_joins = joins
end
return sortspan, scaled_value
end
local cvt_to_hand
local function cvtround(parms, info, in_current, out_current)
-- Return true, t where t is a table with the conversion results; fields:
-- show = rounded, formatted string with the result of converting value in info,
-- using the rounding specified in parms.
-- singular = true if result (after rounding and ignoring any negative sign)
-- is "1", or like "1.00", or is a fraction with value < 1;
-- (and more fields shown below, and a calculated 'absvalue' field).
-- or return false, t where t is an error message table.
-- Input info.clean uses en digits (it has been translated, if necessary).
-- Output show uses en or non-en digits as appropriate, or can be spelled.
if out_current.builtin == 'hand' then
return cvt_to_hand(parms, info, in_current, out_current)
end
local invalue = in_current.builtin == 'hand' and info.altvalue or info.value
local outvalue, extra = convert(parms, invalue, info, in_current, out_current)
if parms.need_table_or_sort then
parms.need_table_or_sort = nil -- process using first input value only
make_table_or_sort(parms, invalue, info, in_current)
end
if extra then
if not outvalue then return false, extra end
invalue = extra.invalue or invalue
outvalue = extra.outvalue
end
if not valid_number(outvalue) then
return false, { 'cvt_invalid_num' }
end
local isnegative
if outvalue < 0 then
isnegative = true
outvalue = -outvalue
end
local precision, show, exponent
local denominator = out_current.frac
if denominator then
show = fraction_table(outvalue, denominator)
else
precision = parms.precision
if not precision then
if parms.sigfig then
show, exponent = make_sigfig(outvalue, parms.sigfig)
elseif parms.opt_round then
local n = parms.opt_round
if n == 0.5 then
local integer, fracpart = math.modf(floor(2 * outvalue + 0.5) / 2)
if fracpart == 0 then
show = format('%.0f', integer)
else
show = format('%.1f', integer + fracpart)
end
else
show = format('%.0f', floor((outvalue / n) + 0.5) * n)
end
elseif in_current.builtin == 'mach' then
local sigfig = info.clean:gsub('^[0.]+', ''):gsub('%.', ''):len() + 1
show, exponent = make_sigfig(outvalue, sigfig)
else
local inclean = info.clean
if extra then
inclean = extra.clean or inclean
show = extra.show
end
if not show then
precision = default_precision(parms, invalue, inclean, info.denominator, outvalue, in_current, out_current, extra)
end
end
end
end
if precision then
if precision >= 0 then
local fudge
if precision <= 8 then
-- Add a fudge to handle common cases of bad rounding due to inability
-- to precisely represent some values. This makes the following work:
-- {{convert|-100.1|C|K}} and {{convert|5555000|um|m|2}}.
-- Old template uses #expr round, which invokes PHP round().
-- LATER: Investigate how PHP round() works.
fudge = 2e-14
else
fudge = 0
end
local fmt = '%.' .. format('%d', precision) .. 'f'
local success
success, show = pcall(format, fmt, outvalue + fudge)
if not success then
return false, { 'cvt_big_prec', tostring(precision) }
end
else
precision = -precision -- #digits to zero (in addition to any digits after dot)
local shift = 10 ^ precision
show = format('%.0f', outvalue/shift)
if show ~= '0' then
exponent = #show + precision
end
end
end
local t = format_number(parms, show, exponent, isnegative)
if type(show) == 'string' then
-- Set singular using match because on some systems 0.99999999999999999 is 1.0.
if exponent then
t.singular = (exponent == 1 and show:match('^10*$'))
else
t.singular = (show == '1' or show:match('^1%.0*$'))
end
else
t.fraction_table = show
t.singular = (outvalue <= 1) -- cannot have 'fraction == 1', but if it were possible it would be singular
end
t.raw_absvalue = outvalue -- absolute value before rounding
return true, setmetatable(t, {
__index = function (self, key)
if key == 'absvalue' then
-- Calculate absolute value after rounding, if needed.
local clean, exponent = rawget(self, 'clean'), rawget(self, 'exponent')
local value = tonumber(clean) -- absolute value (any negative sign has been ignored)
if exponent then
value = value * 10^exponent
end
rawset(self, key, value)
return value
end
end })
end
function cvt_to_hand(parms, info, in_current, out_current)
-- Convert input to hands, inches.
-- Return true, t where t is a table with the conversion results;
-- or return false, t where t is an error message table.
if parms.abbr_org == nil then
out_current.usename = true -- default is to show name not symbol
end
local precision = parms.precision
local frac = out_current.frac
if not frac and precision and precision > 1 then
frac = (precision == 2) and 2 or 4
end
local out_next = out_current.out_next
if out_next then
-- Use magic knowledge to determine whether the next unit is inches without requiring i18n.
-- The following ensures that when the output combination "hand in" is used, the inches
-- value is rounded to match the hands value. Also, displaying say "61½" instead of 61.5
-- is better as 61.5 implies the value is not 61.4.
if out_next.exception == 'subunit_more_precision' then
out_next.frac = frac
end
end
-- Convert to inches; calculate hands from that.
local dummy_unit_table = { scale = out_current.scale / 4, frac = frac }
local success, outinfo = cvtround(parms, info, in_current, dummy_unit_table)
if not success then return false, outinfo end
local tfrac = outinfo.fraction_table
local inches = outinfo.raw_absvalue
if tfrac then
inches = floor(inches) -- integer part only; fraction added later
else
inches = floor(inches + 0.5) -- a hands measurement never shows decimals of an inch
end
local hands, inches = divide(inches, 4)
outinfo.absvalue = hands + inches/4 -- supposed to be the absolute rounded value, but this is close enough
local inchstr = tostring(inches) -- '0', '1', '2' or '3'
if precision and precision <= 0 then -- using negative or 0 for precision rounds to nearest hand
hands = floor(outinfo.raw_absvalue/4 + 0.5)
inchstr = ''
elseif tfrac then
-- Always show an integer before fraction (like "15.0½") because "15½" means 15-and-a-half hands.
inchstr = numdot .. format_fraction(parms, 'out', false, inchstr, tfrac.numstr, tfrac.denstr)
else
inchstr = numdot .. from_en(inchstr)
end
outinfo.show = outinfo.sign .. with_separator(parms, format('%.0f', hands)) .. inchstr
return true, outinfo
end
local function evaluate_condition(value, condition)
-- Return true or false from applying a conditional expression to value,
-- or throw an error if invalid.
-- A very limited set of expressions is supported:
-- v < 9
-- v * 9 < 9
-- where
-- 'v' is replaced with value
-- 9 is any number (as defined by Lua tonumber)
-- only en digits are accepted
-- '<' can also be '<=' or '>' or '>='
-- In addition, the following form is supported:
-- LHS and RHS
-- where
-- LHS, RHS = any of above expressions.
local function compare(value, text)
local arithop, factor, compop, limit = text:match('^%s*v%s*([*]?)(.-)([<>]=?)(.*)$')
if arithop == nil then
error('Invalid default expression', 0)
elseif arithop == '*' then
factor = tonumber(factor)
if factor == nil then
error('Invalid default expression', 0)
end
value = value * factor
end
limit = tonumber(limit)
if limit == nil then
error('Invalid default expression', 0)
end
if compop == '<' then
return value < limit
elseif compop == '<=' then
return value <= limit
elseif compop == '>' then
return value > limit
elseif compop == '>=' then
return value >= limit
end
error('Invalid default expression', 0) -- should not occur
end
local lhs, rhs = condition:match('^(.-%W)and(%W.*)')
if lhs == nil then
return compare(value, condition)
end
return compare(value, lhs) and compare(value, rhs)
end
local function get_default(value, unit_table)
-- Return true, s where s = name of unit's default output unit,
-- or return false, t where t is an error message table.
-- Some units have a default that depends on the input value
-- (the first value if a range of values is used).
-- If '!' is in the default, the first bang-delimited field is an
-- expression that uses 'v' to represent the input value.
-- Example: 'v < 120 ! small ! big ! suffix' (suffix is optional)
-- evaluates 'v < 120' as a boolean with result
-- 'smallsuffix' if (value < 120), or 'bigsuffix' otherwise.
-- Input must use en digits and '.' decimal mark.
local default = data_code.default_exceptions[unit_table.defkey or unit_table.symbol] or unit_table.default
if not default then
local per = unit_table.per
if per then
local function a_default(v, u)
local success, ucode = get_default(v, u)
if not success then
return '?' -- an unlikely error has occurred; will cause lookup of default to fail
end
-- Attempt to use only the first unit if a combination or output multiple.
-- This is not bulletproof but should work for most cases.
-- Where it does not work, the convert will need to specify the wanted output unit.
local t = all_units[ucode]
if t then
local combo = t.combination
if combo then
-- For a multiple like ftin, the "first" unit (ft) is last in the combination.
local i = t.multiple and table_len(combo) or 1
ucode = combo[i]
end
else
-- Try for an automatically generated combination.
local item = ucode:match('^(.-)%+') or ucode:match('^(%S+)%s')
if all_units[item] then
return item
end
end
return ucode
end
local unit1, unit2 = per[1], per[2]
local def1 = (unit1 and a_default(value, unit1) or unit_table.vprefix or '')
local def2 = a_default(1, unit2) -- 1 because per unit of denominator
return true, def1 .. '/' .. def2
end
return false, { 'cvt_no_default', unit_table.symbol }
end
if default:find('!', 1, true) == nil then
return true, default
end
local t = split(default, '!')
if #t == 3 or #t == 4 then
local success, result = pcall(evaluate_condition, value, t[1])
if success then
default = result and t[2] or t[3]
if #t == 4 then
default = default .. t[4]
end
return true, default
end
end
return false, { 'cvt_bad_default', unit_table.symbol }
end
local linked_pages -- to record linked pages so will not link to the same page more than once
local function unlink(unit_table)
-- Forget that the given unit has previously been linked (if it has).
-- That is needed when processing a range of inputs or outputs when an id
-- for the first range value may have been evaluated, but only an id for
-- the last value is displayed, and that id may need to be linked.
linked_pages[unit_table.unitcode or unit_table] = nil
end
local function make_link(link, id, unit_table)
-- Return wikilink "[[link|id]]", possibly abbreviated as in examples:
-- [[Mile|mile]] --> [[mile]]
-- [[Mile|miles]] --> [[mile]]s
-- However, just id is returned if:
-- * no link given (so caller does not need to check if a link was defined); or
-- * link has previously been used during the current convert (to avoid overlinking).
local link_key
if unit_table then
link_key = unit_table.unitcode or unit_table
else
link_key = link
end
if not link or link == '' or linked_pages[link_key] then
return id
end
linked_pages[link_key] = true
-- Following only works for language en, but it should be safe on other wikis,
-- and overhead of doing it generally does not seem worthwhile.
local l = link:sub(1, 1):lower() .. link:sub(2)
if link == id or l == id then
return '[[' .. id .. ']]'
elseif link .. 's' == id or l .. 's' == id then
return '[[' .. id:sub(1, -2) .. ']]s'
else
return '[[' .. link .. '|' .. id .. ']]'
end
end
local function variable_name(clean, unit_table)
-- For slwiki, a unit name depends on the value.
-- Parameter clean is the unsigned rounded value in en digits, as a string.
-- Value Source Example for "m"
-- integer 1: name1 meter (also is the name of the unit)
-- integer 2: var{1} metra
-- integer 3 and 4: var{2} metri
-- integer else: var{3} metrov (0 and 5 or more)
-- real/fraction: var{4} metra
-- var{i} means the i'th field in unit_table.varname if it exists and has
-- an i'th field, otherwise name2.
-- Fields are separated with "!" and are not empty.
-- A field for a unit using an SI prefix has the prefix name inserted,
-- replacing '#' if found, or before the field otherwise.
local vname
if clean == '1' then
vname = unit_table.name1
elseif unit_table.varname then
local i
if clean == '2' then
i = 1
elseif clean == '3' or clean == '4' then
i = 2
elseif clean:find('.', 1, true) then
i = 4
else
i = 3
end
if i > 1 and varname == 'pl' then
i = i - 1
end
vname = split(unit_table.varname, '!')[i]
end
if vname then
local si_name = rawget(unit_table, 'si_name') or ''
local pos = vname:find('#', 1, true)
if pos then
vname = vname:sub(1, pos - 1) .. si_name .. vname:sub(pos + 1)
else
vname = si_name .. vname
end
return vname
end
return unit_table.name2
end
local function linked_id(parms, unit_table, key_id, want_link, clean)
-- Return final unit id (symbol or name), optionally with a wikilink,
-- and update unit_table.sep if required.
-- key_id is one of: 'symbol', 'sym_us', 'name1', 'name1_us', 'name2', 'name2_us'.
local abbr_on = (key_id == 'symbol' or key_id == 'sym_us')
if abbr_on and want_link then
local symlink = rawget(unit_table, 'symlink')
if symlink then
return symlink -- for exceptions that have the linked symbol built-in
end
end
local multiplier = rawget(unit_table, 'multiplier')
local per = unit_table.per
if per then
local paren1, paren2 = '', '' -- possible parentheses around bottom unit
local unit1 = per[1] -- top unit_table, or nil
local unit2 = per[2] -- bottom unit_table
if abbr_on then
if not unit1 then
unit_table.sep = '' -- no separator in "$2/acre"
end
if not want_link then
local symbol = unit_table.symbol_raw
if symbol then
return symbol -- for exceptions that have the symbol built-in
end
end
if (unit2.symbol):find('⋅', 1, true) then
paren1, paren2 = '(', ')'
end
end
local key_id2 -- unit2 is always singular
if key_id == 'name2' then
key_id2 = 'name1'
elseif key_id == 'name2_us' then
key_id2 = 'name1_us'
else
key_id2 = key_id
end
local result
if abbr_on then
result = '/'
elseif omitsep then
result = per_word
elseif unit1 then
result = ' ' .. per_word .. ' '
else
result = per_word .. ' '
end
if want_link and unit_table.link then
if abbr_on or not varname then
result = (unit1 and linked_id(parms, unit1, key_id, false, clean) or '') .. result .. linked_id(parms, unit2, key_id2, false, '1')
else
result = (unit1 and variable_name(clean, unit1) or '') .. result .. variable_name('1', unit2)
end
if omit_separator(result) then
unit_table.sep = ''
end
return make_link(unit_table.link, result, unit_table)
end
if unit1 then
result = linked_id(parms, unit1, key_id, want_link, clean) .. result
if unit1.sep then
unit_table.sep = unit1.sep
end
elseif omitsep then
unit_table.sep = ''
end
return result .. paren1 .. linked_id(parms, unit2, key_id2, want_link, '1') .. paren2
end
if multiplier then
-- A multiplier (like "100" in "100km") forces the unit to be plural.
multiplier = from_en(multiplier)
if not omitsep then
multiplier = multiplier .. (abbr_on and ' ' or ' ')
end
if not abbr_on then
if key_id == 'name1' then
key_id = 'name2'
elseif key_id == 'name1_us' then
key_id = 'name2_us'
end
end
else
multiplier = ''
end
local id = unit_table.fixed_name or ((varname and not abbr_on) and variable_name(clean, unit_table) or unit_table[key_id])
if omit_separator(id) then
unit_table.sep = ''
end
if want_link then
local link = data_code.link_exceptions[unit_table.linkey or unit_table.symbol] or unit_table.link
if link then
local before = ''
local i = unit_table.customary
if i == 1 and parms.opt_sp_us then
i = 2 -- show "U.S." not "US"
end
if i == 3 and abbr_on then
i = 4 -- abbreviate "imperial" to "imp"
end
local customary = text_code.customary_units[i]
if customary then
-- LATER: This works for language en only, but it's esoteric so ignore for now.
local pertext
if id:sub(1, 1) == '/' then
-- Want unit "/USgal" to display as "/U.S. gal", not "U.S. /gal".
pertext = '/'
id = id:sub(2)
elseif id:sub(1, 4) == 'per ' then
-- Similarly want "per U.S. gallon", not "U.S. per gallon" (but in practice this is unlikely to be used).
pertext = 'per '
id = id:sub(5)
else
pertext = ''
end
-- Omit any "US"/"U.S."/"imp"/"imperial" from start of id since that will be inserted.
local removes = (i < 3) and { 'US ', 'US ', 'U.S. ', 'U.S. ' } or { 'imp ', 'imp ', 'imperial ' }
for _, prefix in ipairs(removes) do
local plen = #prefix
if id:sub(1, plen) == prefix then
id = id:sub(plen + 1)
break
end
end
before = pertext .. make_link(customary.link, customary[1]) .. ' '
end
id = before .. make_link(link, id, unit_table)
end
end
return multiplier .. id
end
local function make_id(parms, which, unit_table)
-- Return id, f where
-- id = unit name or symbol, possibly modified
-- f = true if id is a name, or false if id is a symbol
-- using the value for index 'which', and for 'in' or 'out' (unit_table.inout).
-- Result is '' if no symbol/name is to be used.
-- In addition, set unit_table.sep = ' ' or ' ' or ''
-- (the separator that caller will normally insert before the id).
if parms.opt_values then
unit_table.sep = ''
return ''
end
local inout = unit_table.inout
local info = unit_table.valinfo[which]
local abbr_org = parms.abbr_org
local adjectival = parms.opt_adjectival
local lk = parms.lk
local want_link = (lk == 'on' or lk == inout)
local usename = unit_table.usename
local singular = info.singular
local want_name
if usename then
want_name = true
else
if abbr_org == nil then
if parms.wantname then
want_name = true
end
if unit_table.usesymbol then
want_name = false
end
end
if want_name == nil then
local abbr = parms.abbr
if abbr == 'on' or abbr == inout or (abbr == 'mos' and inout == 'out') then
want_name = false
else
want_name = true
end
end
end
local key
if want_name then
if lk == nil and unit_table.builtin == 'hand' then
want_link = true
end
if parms.opt_use_nbsp then
unit_table.sep = ' '
else
unit_table.sep = ' '
end
if parms.opt_singular then
local value
if inout == 'in' then
value = info.value
else
value = info.absvalue
end
if value then -- some unusual units do not always set value field
value = abs(value)
singular = (0 < value and value < 1.0001)
end
end
if unit_table.engscale then
-- engscale: so "|1|e3kg" gives "1 thousand kilograms" (plural)
singular = false
end
key = (adjectival or singular) and 'name1' or 'name2'
if parms.opt_sp_us then
key = key .. '_us'
end
else
if unit_table.builtin == 'hand' then
if parms.opt_hand_hh then
unit_table.symbol = 'hh' -- LATER: might want i18n applied to this
end
end
unit_table.sep = ' '
key = parms.opt_sp_us and 'sym_us' or 'symbol'
end
return linked_id(parms, unit_table, key, want_link, info.clean), want_name
end
local function decorate_value(parms, unit_table, which, number_word)
-- If needed, update unit_table so values will be shown with extra information.
-- For consistency with the old template (but different from fmtpower),
-- the style to display powers of 10 includes "display:none" to allow some
-- browsers to copy, for example, "10³" as "10^3", rather than as "103".
local info
local engscale = unit_table.engscale
local prefix = unit_table.vprefix
if engscale or prefix then
info = unit_table.valinfo[which]
if info.decorated then
return -- do not redecorate if repeating convert
end
info.decorated = true
if engscale then
local inout = unit_table.inout
local abbr = parms.abbr
if (abbr == 'on' or abbr == inout) and not parms.number_word then
info.show = info.show ..
'<span style="margin-left:0.2em">×<span style="margin-left:0.1em">' ..
from_en('10') ..
'</span></span><s style="display:none">^</s><sup>' ..
from_en(tostring(engscale.exponent)) .. '</sup>'
elseif number_word then
local number_id
local lk = parms.lk
if lk == 'on' or lk == inout then
number_id = make_link(engscale.link, engscale[1])
else
number_id = engscale[1]
end
-- WP:NUMERAL recommends " " in values like "12 million".
info.show = info.show .. (parms.opt_adjectival and '-' or ' ') .. number_id
end
end
if prefix then
info.show = prefix .. info.show
end
end
end
local function process_input(parms, in_current)
-- Processing required once per conversion.
-- Return block of text to represent input (value/unit).
if parms.opt_output_only or parms.opt_output_number_only or parms.opt_output_unit_only then
parms.joins = { '', '' }
return ''
end
local first_unit
local composite = in_current.composite -- nil or table of units
if composite then
first_unit = composite[1]
else
first_unit = in_current
end
local id1, want_name = make_id(parms, 1, first_unit)
local sep = first_unit.sep -- separator between value and unit, set by make_id
local preunit = parms.preunit1
if preunit then
sep = '' -- any separator is included in preunit
else
preunit = ''
end
if parms.opt_input_unit_only then
parms.joins = { '', '' }
if composite then
local parts = { id1 }
for i, unit in ipairs(composite) do
if i > 1 then
table.insert(parts, (make_id(parms, 1, unit)))
end
end
id1 = table.concat(parts, ' ')
end
if want_name and parms.opt_adjectival then
return preunit .. hyphenated(id1)
end
return preunit .. id1
end
if parms.opt_also_symbol and not composite and not parms.opt_flip then
local join1 = parms.joins[1]
if join1 == ' (' or join1 == ' [' then
parms.joins = { ' [' .. first_unit[parms.opt_sp_us and 'sym_us' or 'symbol'] .. ']' .. join1 , parms.joins[2] }
end
end
if in_current.builtin == 'mach' and first_unit.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. ' '
local range = parms.range
local valinfo = first_unit.valinfo
local result = prefix .. valinfo[1].show
if range then
-- For simplicity and because more not needed, handle one range item only.
local prefix2 = make_id(parms, 2, first_unit) .. ' '
result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in', {spaced=true})
end
return preunit .. result
end
if composite then
-- Simplify: assume there is no range, and no decoration.
local mid = (not parms.opt_flip) and parms.mid or ''
local sep1 = ' '
local sep2 = ' '
if parms.opt_adjectival and want_name then
sep1 = '-'
sep2 = '-'
end
if omitsep and sep == '' then
-- Testing the id of the most significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
local parts = { first_unit.valinfo[1].show .. sep1 .. id1 }
for i, unit in ipairs(composite) do
if i > 1 then
table.insert(parts, unit.valinfo[1].show .. sep1 .. (make_id(parms, 1, unit)))
end
end
return table.concat(parts, sep2) .. mid
end
local add_unit = (parms.abbr == 'mos') or
parms[parms.opt_flip and 'out_range_x' or 'in_range_x'] or
(not want_name and parms.abbr_range_x)
local range = parms.range
if range and not add_unit then
unlink(first_unit)
end
local id = range and make_id(parms, range.n + 1, first_unit) or id1
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, 'in')
if was_hyphenated then
add_unit = false
end
local result
local valinfo = first_unit.valinfo
if range then
for i = 0, range.n do
local number_word
if i == range.n then
add_unit = false
number_word = true
end
decorate_value(parms, first_unit, i+1, number_word)
local show = valinfo[i+1].show
if add_unit then
show = show .. first_unit.sep .. (i == 0 and id1 or make_id(parms, i+1, first_unit))
end
if i == 0 then
result = show
else
result = range_text(range[i], want_name, parms, result, show, 'in')
end
end
else
decorate_value(parms, first_unit, 1, true)
result = valinfo[1].show
end
return result .. preunit .. extra
end
local function process_one_output(parms, out_current)
-- Processing required for each output unit.
-- Return block of text to represent output (value/unit).
local inout = out_current.inout -- normally 'out' but can be 'in' for order=out
local id1, want_name = make_id(parms, 1, out_current)
local sep = out_current.sep -- set by make_id
local preunit = parms.preunit2
if preunit then
sep = '' -- any separator is included in preunit
else
preunit = ''
end
if parms.opt_output_unit_only then
if want_name and parms.opt_adjectival then
return preunit .. hyphenated(id1)
end
return preunit .. id1
end
if out_current.builtin == 'mach' and out_current.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. ' '
local range = parms.range
local valinfo = out_current.valinfo
local result = prefix .. valinfo[1].show
if range then
-- For simplicity and because more not needed, handle one range item only.
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout, {spaced=true})
end
return preunit .. result
end
local add_unit = (parms[parms.opt_flip and 'in_range_x' or 'out_range_x'] or
(not want_name and parms.abbr_range_x)) and
not parms.opt_output_number_only
local range = parms.range
if range and not add_unit then
unlink(out_current)
end
local id = range and make_id(parms, range.n + 1, out_current) or id1
local extra, was_hyphenated = hyphenated_maybe(parms, want_name, sep, id, inout)
if was_hyphenated then
add_unit = false
end
local result
local valinfo = out_current.valinfo
if range then
for i = 0, range.n do
local number_word
if i == range.n then
add_unit = false
number_word = true
end
decorate_value(parms, out_current, i+1, number_word)
local show = valinfo[i+1].show
if add_unit then
show = show .. out_current.sep .. (i == 0 and id1 or make_id(parms, i+1, out_current))
end
if i == 0 then
result = show
else
result = range_text(range[i], want_name, parms, result, show, inout)
end
end
else
decorate_value(parms, out_current, 1, true)
result = valinfo[1].show
end
if parms.opt_output_number_only then
return result
end
return result .. preunit .. extra
end
local function make_output_single(parms, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for a single output (which is not a combination or a multiple);
-- or return false, t where t is an error message table.
if parms.opt_order_out and in_unit_table.unitcode == out_unit_table.unitcode then
out_unit_table.valinfo = in_unit_table.valinfo
else
out_unit_table.valinfo = collection()
for _, v in ipairs(in_unit_table.valinfo) do
local success, info = cvtround(parms, v, in_unit_table, out_unit_table)
if not success then return false, info end
out_unit_table.valinfo:add(info)
end
end
return true, process_one_output(parms, out_unit_table)
end
local function make_output_multiple(parms, in_unit_table, out_unit_table)
-- Return true, item where item = wikitext of the conversion result
-- for an output which is a multiple (like 'ftin');
-- or return false, t where t is an error message table.
local inout = out_unit_table.inout -- normally 'out' but can be 'in' for order=out
local multiple = out_unit_table.multiple -- table of scaling factors (will not be nil)
local combos = out_unit_table.combination -- table of unit tables (will not be nil)
local abbr = parms.abbr
local abbr_org = parms.abbr_org
local disp = parms.disp
local want_name = (abbr_org == nil and (disp == 'or' or disp == 'slash')) or
not (abbr == 'on' or abbr == inout or abbr == 'mos')
local want_link = (parms.lk == 'on' or parms.lk == inout)
local mid = parms.opt_flip and parms.mid or ''
local sep1 = ' '
local sep2 = ' '
if parms.opt_adjectival and want_name then
sep1 = '-'
sep2 = '-'
end
local do_spell = parms.opt_spell_out
parms.opt_spell_out = nil -- so the call to cvtround does not spell the value
local function make_result(info, isfirst)
local fmt, outvalue, sign
local results = {}
for i = 1, #combos do
local tfrac, thisvalue, strforce
local out_current = combos[i]
out_current.inout = inout
local scale = multiple[i]
if i == 1 then -- least significant unit ('in' from 'ftin')
local decimals
out_current.frac = out_unit_table.frac
local success, outinfo = cvtround(parms, info, in_unit_table, out_current)
if not success then return false, outinfo end
if isfirst then
out_unit_table.valinfo = { outinfo } -- in case output value of first least significant unit is needed
end
sign = outinfo.sign
tfrac = outinfo.fraction_table
if outinfo.is_scientific then
strforce = outinfo.show
decimals = ''
elseif tfrac then
decimals = ''
else
local show = outinfo.show -- number as a string in local language
local p1, p2 = show:find(numdot, 1, true)
decimals = p1 and show:sub(p2 + 1) or '' -- text after numdot, if any
end
fmt = '%.' .. ulen(decimals) .. 'f' -- to reproduce precision
if decimals == '' then
if tfrac then
outvalue = floor(outinfo.raw_absvalue) -- integer part only; fraction added later
else
outvalue = floor(outinfo.raw_absvalue + 0.5) -- keep all integer digits of least significant unit
end
else
outvalue = outinfo.absvalue
end
end
if scale then
outvalue, thisvalue = divide(outvalue, scale)
else
thisvalue = outvalue
end
local id
if want_name then
if varname then
local clean
if strforce or tfrac then
clean = '.1' -- dummy value to force name for floating point
else
clean = format(fmt, thisvalue)
end
id = variable_name(clean, out_current)
else
local key = 'name2'
if parms.opt_adjectival then
key = 'name1'
elseif tfrac then
if thisvalue == 0 then
key = 'name1'
end
elseif parms.opt_singular then
if 0 < thisvalue and thisvalue < 1.0001 then
key = 'name1'
end
else
if thisvalue == 1 then
key = 'name1'
end
end
id = out_current[key]
end
else
id = out_current['symbol']
end
if i == 1 and omit_separator(id) then
-- Testing the id of the least significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
if want_link then
local link = out_current.link
if link then
id = make_link(link, id, out_current)
end
end
local strval
local spell_inout = (i == #combos or outvalue == 0) and inout or '' -- trick so the last value processed (first displayed) has uppercase, if requested
if strforce and outvalue == 0 then
sign = '' -- any sign is in strforce
strval = strforce -- show small values in scientific notation; will only use least significant unit
elseif tfrac then
local wholestr = (thisvalue > 0) and tostring(thisvalue) or nil
strval = format_fraction(parms, spell_inout, false, wholestr, tfrac.numstr, tfrac.denstr, do_spell)
else
strval = (thisvalue == 0) and from_en('0') or with_separator(parms, format(fmt, thisvalue))
if do_spell then
strval = spell_number(parms, spell_inout, strval) or strval
end
end
table.insert(results, strval .. sep1 .. id)
if outvalue == 0 then
break
end
fmt = '%.0f' -- only least significant unit can have a non-integral value
end
local reversed, count = {}, #results
for i = 1, count do
reversed[i] = results[count + 1 - i]
end
return true, sign .. table.concat(reversed, sep2)
end
local valinfo = in_unit_table.valinfo
local success, result = make_result(valinfo[1], true)
if not success then return false, result end
local range = parms.range
if range then
for i = 1, range.n do
local success, result2 = make_result(valinfo[i+1])
if not success then return false, result2 end
result = range_text(range[i], want_name, parms, result, result2, inout, {spaced=true})
end
end
return true, result .. mid
end
local function process(parms, in_unit_table, out_unit_table)
-- Return true, s, outunit where s = final wikitext result,
-- or return false, t where t is an error message table.
linked_pages = {}
local success, bad_output
local bad_input_mcode = in_unit_table.bad_mcode -- nil if input unit is a valid convert unit
local out_unit = parms.out_unit
if out_unit == nil or out_unit == '' or type(out_unit) == 'function' then
if bad_input_mcode or parms.opt_input_unit_only then
bad_output = ''
else
local getdef = type(out_unit) == 'function' and out_unit or get_default
success, out_unit = getdef(in_unit_table.valinfo[1].value, in_unit_table)
parms.out_unit = out_unit
if not success then
bad_output = out_unit
end
end
end
if not bad_output and not out_unit_table then
success, out_unit_table = lookup(parms, out_unit, 'any_combination')
if success then
local mismatch = check_mismatch(in_unit_table, out_unit_table)
if mismatch then
bad_output = mismatch
end
else
bad_output = out_unit_table
end
end
local lhs, rhs
local flipped = parms.opt_flip and not bad_input_mcode
if bad_output then
rhs = (bad_output == '') and '' or message(parms, bad_output)
elseif parms.opt_input_unit_only then
rhs = ''
else
local combos -- nil (for 'ft' or 'ftin'), or table of unit tables (for 'm ft')
if not out_unit_table.multiple then -- nil/false ('ft' or 'm ft'), or table of factors ('ftin')
combos = out_unit_table.combination
end
local frac = parms.frac -- nil or denominator of fraction for output values
if frac then
-- Apply fraction to the unit (if only one), or to non-SI units (if a combination),
-- except that if a precision is also specified, the fraction only applies to
-- the hand unit; that allows the following result:
-- {{convert|156|cm|in hand|1|frac=2}} → 156 centimetres (61.4 in; 15.1½ hands)
-- However, the following is handled elsewhere as a special case:
-- {{convert|156|cm|hand in|1|frac=2}} → 156 centimetres (15.1½ hands; 61½ in)
if combos then
local precision = parms.precision
for _, unit in ipairs(combos) do
if unit.builtin == 'hand' or (not precision and not unit.prefixes) then
unit.frac = frac
end
end
else
out_unit_table.frac = frac
end
end
local outputs = {}
local imax = combos and #combos or 1 -- 1 (single unit) or number of unit tables
if imax == 1 then
parms.opt_order_out = nil -- only useful with an output combination
end
if not flipped and not parms.opt_order_out then
-- Process left side first so any duplicate links (from lk=on) are suppressed
-- on right. Example: {{convert|28|e9pc|e9ly|abbr=off|lk=on}}
lhs = process_input(parms, in_unit_table)
end
for i = 1, imax do
local success, item
local out_current = combos and combos[i] or out_unit_table
out_current.inout = 'out'
if i == 1 then
if imax > 1 and out_current.builtin == 'hand' then
out_current.out_next = combos[2] -- built-in hand can influence next unit in a combination
end
if parms.opt_order_out then
out_current.inout = 'in'
end
end
if out_current.multiple then
success, item = make_output_multiple(parms, in_unit_table, out_current)
else
success, item = make_output_single(parms, in_unit_table, out_current)
end
if not success then return false, item end
outputs[i] = item
end
if parms.opt_order_out then
lhs = outputs[1]
table.remove(outputs, 1)
end
local sep = parms.table_joins and parms.table_joins[2] or parms.join_between
rhs = table.concat(outputs, sep)
end
if flipped or not lhs then
local input = process_input(parms, in_unit_table)
if flipped then
lhs = rhs
rhs = input
else
lhs = input
end
end
if parms.join_before then
lhs = parms.join_before .. lhs
end
local wikitext
if bad_input_mcode then
if bad_input_mcode == '' then
wikitext = lhs
else
wikitext = lhs .. message(parms, bad_input_mcode)
end
elseif parms.table_joins then
wikitext = parms.table_joins[1] .. lhs .. parms.table_joins[2] .. rhs
else
wikitext = lhs .. parms.joins[1] .. rhs .. parms.joins[2]
end
if parms.warnings and not bad_input_mcode then
wikitext = wikitext .. parms.warnings
end
return true, get_styles(parms) .. wikitext, out_unit_table
end
local function main_convert(frame)
-- Do convert, and if needed, do it again with higher default precision.
local parms = { frame = frame } -- will hold template arguments, after translation
set_config(frame.args)
local success, result = get_parms(parms, frame:getParent().args)
if success then
if type(result) ~= 'table' then
return tostring(result)
end
local in_unit_table = result
local out_unit_table
for _ = 1, 2 do -- use counter so cannot get stuck repeating convert
success, result, out_unit_table = process(parms, in_unit_table, out_unit_table)
if success and parms.do_convert_again then
parms.do_convert_again = false
else
break
end
end
end
-- If input=x gives a problem, the result should be just the user input
-- (if x is a property like P123 it has been replaced with '').
-- An unknown input unit would display the input and an error message
-- with success == true at this point.
-- Also, can have success == false with a message that outputs an empty string.
if parms.input_text then
if success and not parms.have_problem then
return result
end
local cat
if parms.tracking then
-- Add a tracking category using the given text as the category sort key.
-- There is currently only one type of tracking, but in principle multiple
-- items could be tracked, using different sort keys for convenience.
cat = wanted_category('tracking', parms.tracking)
end
return parms.input_text .. (cat or '')
end
return success and result or message(parms, result)
end
local function _unit(unitcode, options)
-- Helper function for Module:Val to look up a unit.
-- Parameter unitcode must be a string to identify the wanted unit.
-- Parameter options must be nil or a table with optional fields:
-- value = number (for sort key; default value is 1)
-- scaled_top = nil for a normal unit, or a number for a unit which is
-- the denominator of a per unit (for sort key)
-- si = { 'symbol', 'link' }
-- (a table with two strings) to make an SI unit
-- that will be used for the look up
-- link = true if result should be [[linked]]
-- sort = 'on' or 'debug' if result should include a sort key in a
-- span element ('debug' makes the key visible)
-- name = true for the name of the unit instead of the symbol
-- us = true for the US spelling of the unit, if any
-- Return nil if unitcode is not a non-empty string.
-- Otherwise return a table with fields:
-- text = requested symbol or name of unit, optionally linked
-- scaled_value = input value adjusted by unit scale; used for sort key
-- sortspan = span element with sort key like that provided by {{ntsh}},
-- calculated from the result of converting value
-- to a base unit with scale 1.
-- unknown = true if the unitcode was not known
unitcode = strip(unitcode)
if unitcode == nil or unitcode == '' then
return nil
end
set_config({})
linked_pages = {}
options = options or {}
local parms = {
abbr = options.name and 'off' or 'on',
lk = options.link and 'on' or nil,
opt_sp_us = options.us and true or nil,
opt_ignore_error = true, -- do not add pages using this function to 'what links here' for Module:Convert/extra
opt_sortable_on = options.sort == 'on' or options.sort == 'debug',
opt_sortable_debug = options.sort == 'debug',
}
if options.si then
-- Make a dummy table of units (just one unit) for lookup to use.
-- This makes lookup recognize any SI prefix in the unitcode.
local symbol = options.si[1] or '?'
parms.unittable = { [symbol] = {
_name1 = symbol,
_name2 = symbol,
_symbol = symbol,
utype = symbol,
scale = symbol == 'g' and 0.001 or 1,
prefixes = 1,
default = symbol,
link = options.si[2],
}}
end
local success, unit_table = lookup(parms, unitcode, 'no_combination')
if not success then
unit_table = setmetatable({
symbol = unitcode, name2 = unitcode, utype = unitcode,
scale = 1, default = '', defkey = '', linkey = '' }, unit_mt)
end
local value = tonumber(options.value) or 1
local clean = tostring(abs(value))
local info = {
value = value,
altvalue = value,
singular = (clean == '1'),
clean = clean,
show = clean,
}
unit_table.inout = 'in'
unit_table.valinfo = { info }
local sortspan, scaled_value
if options.sort then
sortspan, scaled_value = make_table_or_sort(parms, value, info, unit_table, options.scaled_top)
end
return {
text = make_id(parms, 1, unit_table),
sortspan = sortspan,
scaled_value = scaled_value,
unknown = not success and true or nil,
}
end
return { convert = main_convert, _unit = _unit }
6ooopjzljpyf28mdyhkl2nyaalgy7v6
Module:Convert/text
828
23834
392696
307794
2026-09-02T00:29:22Z
MacTire02
219
++
392696
Scribunto
text/plain
-- Text used by Module:Convert for enwiki.
-- This is a separate module to simplify translation for use on another wiki.
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
-- Some units accept an SI prefix before the unit code, such as "kg" for kilogram.
local SIprefixes = {
-- The prefix field is what the prefix should be, if different from the prefix used.
['Y'] = { exponent = 24, name = 'yotta', },
['Z'] = { exponent = 21, name = 'zetta', },
['E'] = { exponent = 18, name = 'exa' , },
['P'] = { exponent = 15, name = 'peta' , },
['T'] = { exponent = 12, name = 'tera' , },
['G'] = { exponent = 9, name = 'giga' , },
['M'] = { exponent = 6, name = 'mega' , },
['k'] = { exponent = 3, name = 'kilo' , },
['h'] = { exponent = 2, name = 'hecto', },
['da']= { exponent = 1, name = 'deca' , name_us = 'deka' },
['d'] = { exponent = -1, name = 'deci' , },
['c'] = { exponent = -2, name = 'centi', },
['m'] = { exponent = -3, name = 'milli', },
['μ'] = { exponent = -6, name = 'micro', }, -- key = 'GREEK SMALL LETTER MU' (U+03BC) utf-8 CE BC
['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- key = 'MICRO SIGN' (U+00B5) utf-8 C2 B5
['u'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- not an SI prefix, but allow for people typing this
['n'] = { exponent = -9, name = 'nano' , },
['p'] = { exponent =-12, name = 'pico' , },
['f'] = { exponent =-15, name = 'femto', },
['a'] = { exponent =-18, name = 'atto' , },
['z'] = { exponent =-21, name = 'zepto', },
['y'] = { exponent =-24, name = 'yocto', },
}
-- Some units can be qualified with one of the following prefixes, when linked.
local customary_units = {
{ "US", link = "United States customary units" },
{ "U.S.", link = "United States customary units" },
{ "imperial", link = "Imperial units" },
{ "imp", link = "Imperial units" },
}
-- Names when using engineering notation (a prefix of "eN" where N is a number; example "e6km").
-- key = { "name", link = "article title", exponent = numeric_key_value }
-- If lk=on and link is defined, the name of the number will appear as a link.
local eng_scales = {
["3"] = { "thousand", exponent = 3 },
["6"] = { "million", exponent = 6 },
["9"] = { "billion", link = "1000000000 (number)", exponent = 9 },
["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 },
["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 },
}
local all_categories = {
unit = "[[Category:Convert errors]]",
option = "[[Category:Convert errors]]",
warning = '[[Category:Convert invalid options]]',
tracking = '[[Category:Convert tracking]]',
}
-- For some error messages, the following puts the wanted style around
-- each unit code marked like '...%{ft%}...'.
local unitcode_regex = '%%([{}])'
local unitcode_replace = { ['{'] = '"', ['}'] = '"' } -- no longer need the more elaborate substitute used before 2013-09-28
-- All messages that may be displayed if a problem occurs.
local all_messages = {
-- Message format string: $1=title, $2=text, $3=category, $4=anchor.
-- Each displayed message starts with "Convert:" so can easily locate by searching article.
cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>',
cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>',
cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3',
-- Each of following messages is a table:
-- { [1] = 'title', -- mouseover title text
-- [2] = 'text', -- link text displayed in article
-- [3] = 'category key', -- key to lookup category in all_categories
-- [4] = 'anchor', -- anchor for link to relevant section on help page
-- regex = gsub_regex,
-- replace = gsub_table,
-- } Mouseover title text Link text CatKey Anchor
cvt_bad_input = { 'input "$1" must be a number and unit' , 'invalid input' , 'option', 'invalid_input' },
cvt_bad_num = { 'Value "$1" must be a number' , 'invalid number' , 'option', 'invalid_number' },
cvt_big_prec = { 'Precision "$1" is too large' , 'precision too large' , 'option', 'precision_too_large' },
cvt_invalid_num = { 'Number has overflowed' , 'number overflow' , 'option', 'number_overflow' },
cvt_no_num = { 'Needs the number to be converted' , 'needs a number' , 'option', 'needs_number' },
cvt_no_num2 = { 'Needs another number for a range' , 'needs another number', 'option', 'needs_another_number' },
cvt_bad_altitude = { '"$1" needs an integer' , 'invalid altitude' , 'option', 'invalid_altitude' },
cvt_bad_frac = { '"$1" needs an integer above 1' , 'invalid fraction' , 'option', 'invalid_fraction' },
cvt_bad_prec = { 'Precision "$1" must be an integer' , 'invalid precision' , 'option', 'invalid_precision' },
cvt_bad_sigfig = { '"$1" needs a positive integer' , 'invalid sigfig' , 'option', 'invalid_sigfig' },
cvt_empty_option = { 'Ignored empty option "$1"' , 'empty option' , 'option', 'empty_option' },
cvt_deprecated = { 'Option "$1" is deprecated' , '*' , 'option', 'deprecated_option', format = 'cvt_format2', nowarn = true },
cvt_no_spell = { 'Spelling is not available' , 'bug, ask for help' , 'option', 'ask_for_help' },
cvt_unknown_option = { 'Ignored invalid option "$1"' , 'invalid option' , 'option', 'invalid_option' },
cvt_wd_fail = { 'Unable to access Wikidata' , 'wikidata problem' , 'option', 'wikidata_problem' },
cvt_bad_default = { 'Unit "$1" has an invalid default' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_bad_unit = { 'Unit "$1" is invalid here' , 'unit invalid here' , 'unit' , 'unit_invalid_here' },
cvt_no_default = { 'Unit "$1" has no default output unit' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_no_unit = { 'Needs name of unit' , 'needs unit name' , 'unit' , 'needs_unit_name' },
cvt_unknown = { 'Unit name "$1" is not known' , 'unknown unit' , 'unit' , 'unknown_unit' },
cvt_should_be = { '$1' , 'ambiguous unit' , 'unit' , 'ambiguous_unit', regex = unitcode_regex, replace = unitcode_replace },
cvt_mismatch = { 'Cannot convert "$1" to "$2"' , 'unit mismatch' , 'unit' , 'unit_mismatch' },
cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_lookup = { 'Unit "$1" is incorrectly defined' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
}
-- Text to join input value/unit with output value/unit.
local disp_joins = {
-- [1]=before output, [2]=after output, [3]=between outputs in a combination; default "; "
-- [wantname] gives default abbr=off
["or"] = { " or " , "" , " or ", wantname = true },
["sqbr-sp"] = { " [" , "]" },
["sqbr-nbsp"] = { " [" , "]" },
["comma"] = { ", " , "" , ", " },
["slash-sp"] = { " / " , "" , wantname = true },
["slash-nbsp"] = { " / ", "" , wantname = true },
["slash-nosp"] = { "/" , "" , wantname = true },
["b"] = { " (" , ")" },
["(or)"] = { " (" , ")", " or " },
["br"] = { "<br />" , "" , wantname = true },
["br()"] = { "<br />(" , ")", wantname = true },
}
-- Text to separate values in a range.
local range_types = {
-- Specifying a table requires either:
-- * "off" and "on" values (for "abbr=off" and "abbr=on"), or
-- * "input" and "output" values (for LHS and RHS);
-- other fields are optional.
-- When "adj=on|abbr=off" applies, spaces in range text are replaced with hyphens.
-- With "exception = true", that also occurs with "adj=on|abbr=on".
-- If "adj" is defined here, that text (unchanged) is used with "adj=on".
["+"] = " + ",
[","] = ", ",
[", and"] = ", and ",
[", or"] = ", or ",
["by"] = " by ",
["-"] = "–",
["to about"] = " to about ",
["and"] = { off = " and ", on = " and ", exception = true },
["and(-)"] = { input = " and ", output = "–" },
["or"] = { off = " or " , on = " or " , exception = true },
["to"] = { off = " to " , on = " to " , exception = true },
["to(-)"] = { input = " to ", output = "–" },
["+/-"] = { off = " ± ", on = " ± ", adj = " ± ", is_range_change = true },
["by(x)"] = { input = " by ", output = " × ", out_range_x = true },
["x"] = { off = " by ", on = " × ", abbr_range_x = true },
["xx"] = " × ",
["*"] = "×",
["/"] = " / ", -- for a table of high/low temperatures with {{convert|83|/|63|F|disp=br()|abbr=values}}
}
local range_aliases = {
-- ["alternative name for a range"] = "standard range name"
["–"] = "-",
["–"] = "-",
["×"] = "x",
["×"] = "x",
["±"] = "+/-",
["±"] = "+/-",
["as"] = "and", -- Manx: accept "as" as the range separator
}
-- Convert accepts range text delimited with whitespace, for example, {{convert|1 to 2|ft}}.
-- In addition, the following "words" are accepted without spaces, for example, {{convert|1-2|ft}}.
-- Words must be in correct order for searching, for example, 'x' after 'xx'.
local range_words = { '-', '–', 'xx', 'x', '*' }
local ranges = {
types = range_types,
aliases = range_aliases,
words = range_words,
}
-- Valid option names.
local en_option_name = {
-- ["local text for option name"] = "en name used in this module"
["$"] = "$",
["abbr"] = "abbr",
["adj"] = "adj",
["altitude_ft"] = "altitude_ft",
["altitude_m"] = "altitude_m",
["comma"] = "comma",
["debug"] = "debug",
["disp"] = "disp",
["frac"] = "frac",
["input"] = "input",
["lang"] = "lang",
["lk"] = "lk",
["order"] = "order",
["qid"] = "qid",
["qual"] = "qual",
["qualifier"] = "qual",
["round"] = "round",
["sigfig"] = "sigfig",
["sing"] = "adj", -- "sing" is an old alias for "adj"
["sortable"] = "sortable",
["sp"] = "sp",
["spell"] = "spell",
["stylein"] = "stylein",
["styleout"] = "styleout",
["tracking"] = "tracking",
}
-- Valid option values.
-- Convention: parms.opt_xxx refers to an option that is set here
-- (not intended to be set by the template which invokes this module).
-- Example: At enwiki, "abbr" includes:
-- ["values"] = "opt_values"
-- As a result, if the template uses abbr=values, Module:Convert sets:
-- parms["opt_values"] = true
-- parms["abbr"] = nil
-- Therefore parms.abbr will be nil, or will have one of the listed values
-- that do not start with "opt_".
-- An option value of form "xxx?" is the same as "xxx" but shows the input as deprecated.
local en_option_value = {
["$"] = 'TEXT', -- TEXT should be a currency symbol that will be used instead of "$"
["abbr"] = {
-- ["local text for option value"] = "en value used in this module"
["def"] = "", -- ignored (some wrapper templates call convert with "abbr=def" to mean "default abbreviation")
["h"] = "on", -- abbr=on + use "h" for hand unit (default)
["hh"] = "opt_hand_hh", -- abbr=on + use "hh" for hand unit
["in"] = "in", -- use symbol for LHS unit
["none"] = "off", -- old name for "off"
["off"] = "off", -- use name for all units
["on"] = "on", -- use symbol for all units
["out"] = "out", -- use symbol for RHS unit (default)
["unit"] = "unit", -- abbr=on but abbreviate units only: e6km → million km (not ×10⁶ km)
["values"] = "opt_values", -- show only input and output numbers, not units
["~"] = "opt_also_symbol", -- show input unit symbol as well as name
},
["adj"] = {
["mid"] = "opt_adjectival, opt_adj_mid", -- adj=on with user-specified text after input unit (between input and output)
["off"] = "", -- ignored (off is the default)
["on"] = "opt_adjectival", -- unit name is singular and hyphenated
["pre"] = "opt_one_preunit", -- user-specified text before input unit
["ri0"] = "opt_ri=0", -- round input with precision = 0
["ri1"] = "opt_ri=1", -- round input with precision = 1
["ri2"] = "opt_ri=2", -- round input with precision = 2
["ri3"] = "opt_ri=3", -- round input with precision = 3
},
["altitude_ft"] = 'INTEGER',
["altitude_m"] = 'INTEGER',
["comma"] = {
["5"] = "opt_comma5", -- only use numsep grouping if 5 or more digits
["gaps"] = "opt_gaps", -- use gaps, not numsep, to separate groups of digits
["gaps3"] = "opt_gaps, opt_gaps3", -- group only in threes rather than default of no gap before a single digit after decimal mark
["off"] = "opt_nocomma", -- no numsep in input or output numbers
},
["debug"] = {
["yes"] = "opt_sortable_debug", -- make the normally hidden sort key visible
},
["disp"] = {
["5"] = "opt_round=5?", -- round output value to nearest 5
["b"] = "b", -- join: '(...)'
["(or)"] = "(or)", -- join: '(...)' with 'or' between outputs in a combination
["br"] = "br", -- join: '<br />'
["br()"] = "br()", -- join: '<br />(...)'
["comma"] = "comma", -- join: ','
["flip"] = "opt_flip", -- reverse order of input/output
["number"] = "opt_output_number_only", -- display output value (not input, and not output symbol/name)
["or"] = "or", -- join: 'or'
["out"] = "opt_output_only",
["output number only"] = "opt_output_number_only",
["output only"] = "opt_output_only",
["preunit"] = "opt_two_preunits", -- user-specified text before input and output units
["sqbr"] = "sqbr", -- join: '[...]'
["table"] = "opt_table", -- output is suitable for a table cell with align="right"
["tablecen"] = "opt_tablecen", -- output is suitable for a table cell with align="center"
["unit"] = "opt_input_unit_only", -- display input symbol/name (not output, and not input value)
["unit or text"] = "opt_input_unit_only, opt_ignore_error", -- display input symbol/name, or given unit code if not known
["unit2"] = "opt_output_unit_only",
["x"] = "x", -- join: <first>...<second> (user-specified text)
},
["frac"] = 'INTEGER',
["input"] = 'TEXT', -- TEXT should be value><space><unitcode> or <wikidata-property-id>
["lang"] = { -- language for output digits (both en and local digits are always accepted for input)
["en"] = "opt_lang_en", -- use en digits for numbers, regardless of local language
["local"] = "opt_lang_local", -- use local digits for numbers (default, although config can change default to en)
},
["lk"] = {
["in"] = "in", -- link LHS unit name or symbol
["off"] = "off", -- do not link: same as default except for hand unit
["on"] = "on", -- link all unit names or symbols (but not twice for the same unit)
["out"] = "out", -- link RHS unit name or symbol
},
["order"] = {
["flip"] = "opt_flip", -- reverse order of input/output
["out"] = "opt_order_out", -- do not show input; instead, use order in output combination, with the first output shown as the input
},
["qid"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["qual"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["round"] = {
["0.5"] = "opt_round=0.5", -- round output value to nearest 0.5
["5"] = "opt_round=5", -- round output value to nearest 5
["10"] = "opt_round=10", -- round output value to nearest 10 (same as but clearer than "|-1")
["25"] = "opt_round=25", -- round output value to nearest 25
["50"] = "opt_round=50", -- round output value to nearest 50
["each"] = "opt_round_each", -- using default precision in a range, round each output separately (default uses highest precision of each item in range)
},
["sigfig"] = 'INTEGER',
["sortable"] = {
["off"] = "", -- ignored (off is the default)
["on"] = "opt_sortable_on", -- output sort key for use in a sortable table, based on value from converting to a standard base unit
["debug"] = "opt_sortable_on, opt_sortable_debug", -- |sortable=debug is the same as |sortable=on|debug=yes
},
["sp"] = {
["us"] = "opt_sp_us", -- use U.S. spelling (like "meter" instead of default "metre")
},
["spell"] = { -- only English spelling is supported; not scientific notation; only some fractions
["in"] = "opt_spell_in", -- spell input value in words
["In"] = "opt_spell_in, opt_spell_upper", -- spell input value in words with first letter uppercase
["on"] = "opt_spell_in, opt_spell_out", -- spell input and output values in words
["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper", -- same, with first letter of first word in result uppercase
},
["stylein"] = 'TEXT',
["styleout"] = 'TEXT',
["tracking"] = 'TEXT',
}
local titles = {
["frac"] = "Fraction/styles.css",
["sfrac"] = "Sfrac/styles.css",
}
return {
SIprefixes = SIprefixes,
all_categories = all_categories,
all_messages = all_messages,
currency = { ['$'] = true, ['£'] = true, ['€'] = true, ['₱'] = true, ['₽'] = true, ['¥'] = true },
customary_units = customary_units,
disp_joins = disp_joins,
en_option_name = en_option_name,
en_option_value = en_option_value,
eng_scales = eng_scales,
ranges = ranges,
titles = titles,
}
9rrc5ui28kg98t6nx9bae9kz5cymnvp
392697
392696
2026-09-02T00:32:42Z
MacTire02
219
++
392697
Scribunto
text/plain
-- Text used by Module:Convert for enwiki.
-- This is a separate module to simplify translation for use on another wiki.
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
-- Some units accept an SI prefix before the unit code, such as "kg" for kilogram.
local SIprefixes = {
-- The prefix field is what the prefix should be, if different from the prefix used.
['Y'] = { exponent = 24, name = 'yotta', },
['Z'] = { exponent = 21, name = 'zetta', },
['E'] = { exponent = 18, name = 'exa' , },
['P'] = { exponent = 15, name = 'peta' , },
['T'] = { exponent = 12, name = 'tera' , },
['G'] = { exponent = 9, name = 'giga' , },
['M'] = { exponent = 6, name = 'mega' , },
['k'] = { exponent = 3, name = 'kilo' , },
['h'] = { exponent = 2, name = 'hecto', },
['da']= { exponent = 1, name = 'deca' , name_us = 'deka' },
['d'] = { exponent = -1, name = 'deci' , },
['c'] = { exponent = -2, name = 'centi', },
['m'] = { exponent = -3, name = 'milli', },
['μ'] = { exponent = -6, name = 'micro', }, -- key = 'GREEK SMALL LETTER MU' (U+03BC) utf-8 CE BC
['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- key = 'MICRO SIGN' (U+00B5) utf-8 C2 B5
['u'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- not an SI prefix, but allow for people typing this
['n'] = { exponent = -9, name = 'nano' , },
['p'] = { exponent =-12, name = 'pico' , },
['f'] = { exponent =-15, name = 'femto', },
['a'] = { exponent =-18, name = 'atto' , },
['z'] = { exponent =-21, name = 'zepto', },
['y'] = { exponent =-24, name = 'yocto', },
}
-- Some units can be qualified with one of the following prefixes, when linked.
local customary_units = {
{ "US", link = "United States customary units" },
{ "U.S.", link = "United States customary units" },
{ "imperial", link = "Imperial units" },
{ "imp", link = "Imperial units" },
}
-- Names when using engineering notation (a prefix of "eN" where N is a number; example "e6km").
-- key = { "name", link = "article title", exponent = numeric_key_value }
-- If lk=on and link is defined, the name of the number will appear as a link.
local eng_scales = {
["3"] = { "thousand", exponent = 3 },
["6"] = { "million", exponent = 6 },
["9"] = { "billion", link = "1000000000 (number)", exponent = 9 },
["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 },
["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 },
}
local all_categories = {
unit = "[[Category:Convert errors]]",
option = "[[Category:Convert errors]]",
warning = '[[Category:Convert invalid options]]',
tracking = '[[Category:Convert tracking]]',
}
-- For some error messages, the following puts the wanted style around
-- each unit code marked like '...%{ft%}...'.
local unitcode_regex = '%%([{}])'
local unitcode_replace = { ['{'] = '"', ['}'] = '"' } -- no longer need the more elaborate substitute used before 2013-09-28
-- All messages that may be displayed if a problem occurs.
local all_messages = {
-- Message format string: $1=title, $2=text, $3=category, $4=anchor.
-- Each displayed message starts with "Convert:" so can easily locate by searching article.
cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>',
cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>',
cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3',
-- Each of following messages is a table:
-- { [1] = 'title', -- mouseover title text
-- [2] = 'text', -- link text displayed in article
-- [3] = 'category key', -- key to lookup category in all_categories
-- [4] = 'anchor', -- anchor for link to relevant section on help page
-- regex = gsub_regex,
-- replace = gsub_table,
-- } Mouseover title text Link text CatKey Anchor
cvt_bad_input = { 'input "$1" must be a number and unit' , 'invalid input' , 'option', 'invalid_input' },
cvt_bad_num = { 'Value "$1" must be a number' , 'invalid number' , 'option', 'invalid_number' },
cvt_big_prec = { 'Precision "$1" is too large' , 'precision too large' , 'option', 'precision_too_large' },
cvt_invalid_num = { 'Number has overflowed' , 'number overflow' , 'option', 'number_overflow' },
cvt_no_num = { 'Needs the number to be converted' , 'needs a number' , 'option', 'needs_number' },
cvt_no_num2 = { 'Needs another number for a range' , 'needs another number', 'option', 'needs_another_number' },
cvt_bad_altitude = { '"$1" needs an integer' , 'invalid altitude' , 'option', 'invalid_altitude' },
cvt_bad_frac = { '"$1" needs an integer above 1' , 'invalid fraction' , 'option', 'invalid_fraction' },
cvt_bad_prec = { 'Precision "$1" must be an integer' , 'invalid precision' , 'option', 'invalid_precision' },
cvt_bad_sigfig = { '"$1" needs a positive integer' , 'invalid sigfig' , 'option', 'invalid_sigfig' },
cvt_empty_option = { 'Ignored empty option "$1"' , 'empty option' , 'option', 'empty_option' },
cvt_deprecated = { 'Option "$1" is deprecated' , '*' , 'option', 'deprecated_option', format = 'cvt_format2', nowarn = true },
cvt_no_spell = { 'Spelling is not available' , 'bug, ask for help' , 'option', 'ask_for_help' },
cvt_unknown_option = { 'Ignored invalid option "$1"' , 'invalid option' , 'option', 'invalid_option' },
cvt_wd_fail = { 'Unable to access Wikidata' , 'wikidata problem' , 'option', 'wikidata_problem' },
cvt_bad_default = { 'Unit "$1" has an invalid default' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_bad_unit = { 'Unit "$1" is invalid here' , 'unit invalid here' , 'unit' , 'unit_invalid_here' },
cvt_no_default = { 'Unit "$1" has no default output unit' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_no_unit = { 'Needs name of unit' , 'needs unit name' , 'unit' , 'needs_unit_name' },
cvt_unknown = { 'Unit name "$1" is not known' , 'unknown unit' , 'unit' , 'unknown_unit' },
cvt_should_be = { '$1' , 'ambiguous unit' , 'unit' , 'ambiguous_unit', regex = unitcode_regex, replace = unitcode_replace },
cvt_mismatch = { 'Cannot convert "$1" to "$2"' , 'unit mismatch' , 'unit' , 'unit_mismatch' },
cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_lookup = { 'Unit "$1" is incorrectly defined' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
}
-- Text to join input value/unit with output value/unit.
local disp_joins = {
-- [1]=before output, [2]=after output, [3]=between outputs in a combination; default "; "
-- [wantname] gives default abbr=off
["or"] = { " or " , "" , " or ", wantname = true },
["sqbr-sp"] = { " [" , "]" },
["sqbr-nbsp"] = { " [" , "]" },
["comma"] = { ", " , "" , ", " },
["slash-sp"] = { " / " , "" , wantname = true },
["slash-nbsp"] = { " / ", "" , wantname = true },
["slash-nosp"] = { "/" , "" , wantname = true },
["b"] = { " (" , ")" },
["(or)"] = { " (" , ")", " or " },
["br"] = { "<br />" , "" , wantname = true },
["br()"] = { "<br />(" , ")", wantname = true },
}
-- Text to separate values in a range.
local range_types = {
-- Specifying a table requires either:
-- * "off" and "on" values (for "abbr=off" and "abbr=on"), or
-- * "input" and "output" values (for LHS and RHS);
-- other fields are optional.
-- When "adj=on|abbr=off" applies, spaces in range text are replaced with hyphens.
-- With "exception = true", that also occurs with "adj=on|abbr=on".
-- If "adj" is defined here, that text (unchanged) is used with "adj=on".
["+"] = " + ",
[","] = ", ",
[", and"] = ", and ",
[", or"] = ", or ",
["by"] = " by ",
["-"] = "–",
["to about"] = " to about ",
["and"] = { off = " and ", on = " and ", exception = true },
["as"] = { off = " as ", on = " as ", exception = true }, -- Manx range separator
["and(-)"] = { input = " and ", output = "–" },
["or"] = { off = " or " , on = " or " , exception = true },
["to"] = { off = " to " , on = " to " , exception = true },
["to(-)"] = { input = " to ", output = "–" },
["+/-"] = { off = " ± ", on = " ± ", adj = " ± ", is_range_change = true },
["by(x)"] = { input = " by ", output = " × ", out_range_x = true },
["x"] = { off = " by ", on = " × ", abbr_range_x = true },
["xx"] = " × ",
["*"] = "×",
["/"] = " / ", -- for a table of high/low temperatures with {{convert|83|/|63|F|disp=br()|abbr=values}}
}
local range_aliases = {
-- ["alternative name for a range"] = "standard range name"
["–"] = "-",
["–"] = "-",
["×"] = "x",
["×"] = "x",
["±"] = "+/-",
["±"] = "+/-",
}
-- Convert accepts range text delimited with whitespace, for example, {{convert|1 to 2|ft}}.
-- In addition, the following "words" are accepted without spaces, for example, {{convert|1-2|ft}}.
-- Words must be in correct order for searching, for example, 'x' after 'xx'.
local range_words = { '-', '–', 'xx', 'x', '*' }
local ranges = {
types = range_types,
aliases = range_aliases,
words = range_words,
}
-- Valid option names.
local en_option_name = {
-- ["local text for option name"] = "en name used in this module"
["$"] = "$",
["abbr"] = "abbr",
["adj"] = "adj",
["altitude_ft"] = "altitude_ft",
["altitude_m"] = "altitude_m",
["comma"] = "comma",
["debug"] = "debug",
["disp"] = "disp",
["frac"] = "frac",
["input"] = "input",
["lang"] = "lang",
["lk"] = "lk",
["order"] = "order",
["qid"] = "qid",
["qual"] = "qual",
["qualifier"] = "qual",
["round"] = "round",
["sigfig"] = "sigfig",
["sing"] = "adj", -- "sing" is an old alias for "adj"
["sortable"] = "sortable",
["sp"] = "sp",
["spell"] = "spell",
["stylein"] = "stylein",
["styleout"] = "styleout",
["tracking"] = "tracking",
}
-- Valid option values.
-- Convention: parms.opt_xxx refers to an option that is set here
-- (not intended to be set by the template which invokes this module).
-- Example: At enwiki, "abbr" includes:
-- ["values"] = "opt_values"
-- As a result, if the template uses abbr=values, Module:Convert sets:
-- parms["opt_values"] = true
-- parms["abbr"] = nil
-- Therefore parms.abbr will be nil, or will have one of the listed values
-- that do not start with "opt_".
-- An option value of form "xxx?" is the same as "xxx" but shows the input as deprecated.
local en_option_value = {
["$"] = 'TEXT', -- TEXT should be a currency symbol that will be used instead of "$"
["abbr"] = {
-- ["local text for option value"] = "en value used in this module"
["def"] = "", -- ignored (some wrapper templates call convert with "abbr=def" to mean "default abbreviation")
["h"] = "on", -- abbr=on + use "h" for hand unit (default)
["hh"] = "opt_hand_hh", -- abbr=on + use "hh" for hand unit
["in"] = "in", -- use symbol for LHS unit
["none"] = "off", -- old name for "off"
["off"] = "off", -- use name for all units
["on"] = "on", -- use symbol for all units
["out"] = "out", -- use symbol for RHS unit (default)
["unit"] = "unit", -- abbr=on but abbreviate units only: e6km → million km (not ×10⁶ km)
["values"] = "opt_values", -- show only input and output numbers, not units
["~"] = "opt_also_symbol", -- show input unit symbol as well as name
},
["adj"] = {
["mid"] = "opt_adjectival, opt_adj_mid", -- adj=on with user-specified text after input unit (between input and output)
["off"] = "", -- ignored (off is the default)
["on"] = "opt_adjectival", -- unit name is singular and hyphenated
["pre"] = "opt_one_preunit", -- user-specified text before input unit
["ri0"] = "opt_ri=0", -- round input with precision = 0
["ri1"] = "opt_ri=1", -- round input with precision = 1
["ri2"] = "opt_ri=2", -- round input with precision = 2
["ri3"] = "opt_ri=3", -- round input with precision = 3
},
["altitude_ft"] = 'INTEGER',
["altitude_m"] = 'INTEGER',
["comma"] = {
["5"] = "opt_comma5", -- only use numsep grouping if 5 or more digits
["gaps"] = "opt_gaps", -- use gaps, not numsep, to separate groups of digits
["gaps3"] = "opt_gaps, opt_gaps3", -- group only in threes rather than default of no gap before a single digit after decimal mark
["off"] = "opt_nocomma", -- no numsep in input or output numbers
},
["debug"] = {
["yes"] = "opt_sortable_debug", -- make the normally hidden sort key visible
},
["disp"] = {
["5"] = "opt_round=5?", -- round output value to nearest 5
["b"] = "b", -- join: '(...)'
["(or)"] = "(or)", -- join: '(...)' with 'or' between outputs in a combination
["br"] = "br", -- join: '<br />'
["br()"] = "br()", -- join: '<br />(...)'
["comma"] = "comma", -- join: ','
["flip"] = "opt_flip", -- reverse order of input/output
["number"] = "opt_output_number_only", -- display output value (not input, and not output symbol/name)
["or"] = "or", -- join: 'or'
["out"] = "opt_output_only",
["output number only"] = "opt_output_number_only",
["output only"] = "opt_output_only",
["preunit"] = "opt_two_preunits", -- user-specified text before input and output units
["sqbr"] = "sqbr", -- join: '[...]'
["table"] = "opt_table", -- output is suitable for a table cell with align="right"
["tablecen"] = "opt_tablecen", -- output is suitable for a table cell with align="center"
["unit"] = "opt_input_unit_only", -- display input symbol/name (not output, and not input value)
["unit or text"] = "opt_input_unit_only, opt_ignore_error", -- display input symbol/name, or given unit code if not known
["unit2"] = "opt_output_unit_only",
["x"] = "x", -- join: <first>...<second> (user-specified text)
},
["frac"] = 'INTEGER',
["input"] = 'TEXT', -- TEXT should be value><space><unitcode> or <wikidata-property-id>
["lang"] = { -- language for output digits (both en and local digits are always accepted for input)
["en"] = "opt_lang_en", -- use en digits for numbers, regardless of local language
["local"] = "opt_lang_local", -- use local digits for numbers (default, although config can change default to en)
},
["lk"] = {
["in"] = "in", -- link LHS unit name or symbol
["off"] = "off", -- do not link: same as default except for hand unit
["on"] = "on", -- link all unit names or symbols (but not twice for the same unit)
["out"] = "out", -- link RHS unit name or symbol
},
["order"] = {
["flip"] = "opt_flip", -- reverse order of input/output
["out"] = "opt_order_out", -- do not show input; instead, use order in output combination, with the first output shown as the input
},
["qid"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["qual"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["round"] = {
["0.5"] = "opt_round=0.5", -- round output value to nearest 0.5
["5"] = "opt_round=5", -- round output value to nearest 5
["10"] = "opt_round=10", -- round output value to nearest 10 (same as but clearer than "|-1")
["25"] = "opt_round=25", -- round output value to nearest 25
["50"] = "opt_round=50", -- round output value to nearest 50
["each"] = "opt_round_each", -- using default precision in a range, round each output separately (default uses highest precision of each item in range)
},
["sigfig"] = 'INTEGER',
["sortable"] = {
["off"] = "", -- ignored (off is the default)
["on"] = "opt_sortable_on", -- output sort key for use in a sortable table, based on value from converting to a standard base unit
["debug"] = "opt_sortable_on, opt_sortable_debug", -- |sortable=debug is the same as |sortable=on|debug=yes
},
["sp"] = {
["us"] = "opt_sp_us", -- use U.S. spelling (like "meter" instead of default "metre")
},
["spell"] = { -- only English spelling is supported; not scientific notation; only some fractions
["in"] = "opt_spell_in", -- spell input value in words
["In"] = "opt_spell_in, opt_spell_upper", -- spell input value in words with first letter uppercase
["on"] = "opt_spell_in, opt_spell_out", -- spell input and output values in words
["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper", -- same, with first letter of first word in result uppercase
},
["stylein"] = 'TEXT',
["styleout"] = 'TEXT',
["tracking"] = 'TEXT',
}
local titles = {
["frac"] = "Fraction/styles.css",
["sfrac"] = "Sfrac/styles.css",
}
return {
SIprefixes = SIprefixes,
all_categories = all_categories,
all_messages = all_messages,
currency = { ['$'] = true, ['£'] = true, ['€'] = true, ['₱'] = true, ['₽'] = true, ['¥'] = true },
customary_units = customary_units,
disp_joins = disp_joins,
en_option_name = en_option_name,
en_option_value = en_option_value,
eng_scales = eng_scales,
ranges = ranges,
titles = titles,
}
5smf6jj5wrl5f2gru3633xj5cdvz33u
392698
392697
2026-09-02T00:39:14Z
MacTire02
219
++
392698
Scribunto
text/plain
-- Text used by Module:Convert for enwiki.
-- This is a separate module to simplify translation for use on another wiki.
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
local SIprefixes = {
['Y'] = { exponent = 24, name = 'yotta' },
['Z'] = { exponent = 21, name = 'zetta' },
['E'] = { exponent = 18, name = 'exa' },
['P'] = { exponent = 15, name = 'peta' },
['T'] = { exponent = 12, name = 'tera' },
['G'] = { exponent = 9, name = 'giga' },
['M'] = { exponent = 6, name = 'mega' },
['k'] = { exponent = 3, name = 'kilo' },
['h'] = { exponent = 2, name = 'hecto' },
['da'] = { exponent = 1, name = 'deca', name_us = 'deka' },
['d'] = { exponent = -1, name = 'deci' },
['c'] = { exponent = -2, name = 'centi' },
['m'] = { exponent = -3, name = 'milli' },
['μ'] = { exponent = -6, name = 'micro' },
['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' },
['u'] = { exponent = -6, name = 'micro', prefix = 'μ' },
['n'] = { exponent = -9, name = 'nano' },
['p'] = { exponent = -12, name = 'pico' },
['f'] = { exponent = -15, name = 'femto' },
['a'] = { exponent = -18, name = 'atto' },
['z'] = { exponent = -21, name = 'zepto' },
['y'] = { exponent = -24, name = 'yocto' },
}
local customary_units = {
{ "US", link = "United States customary units" },
{ "U.S.", link = "United States customary units" },
{ "imperial", link = "Imperial units" },
{ "imp", link = "Imperial units" },
}
local eng_scales = {
["3"] = { "thousand", exponent = 3 },
["6"] = { "million", exponent = 6 },
["9"] = { "billion", link = "1000000000 (number)", exponent = 9 },
["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 },
["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 },
}
local all_categories = {
unit = "[[Category:Convert errors]]",
option = "[[Category:Convert errors]]",
warning = "[[Category:Convert invalid options]]",
tracking = "[[Category:Convert tracking]]",
}
local unitcode_regex = "%%([{}])"
local unitcode_replace = { ["{"] = '"', ["}"] = '"' }
local all_messages = {
cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>',
cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>',
cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3',
cvt_bad_input = { 'input "$1" must be a number and unit', "invalid input", "option", "invalid_input" },
cvt_bad_num = { 'Value "$1" must be a number', "invalid number", "option", "invalid_number" },
cvt_big_prec = { 'Precision "$1" is too large', "precision too large", "option", "precision_too_large" },
cvt_invalid_num = { "Number has overflowed", "number overflow", "option", "number_overflow" },
cvt_no_num = { "Needs the number to be converted", "needs a number", "option", "needs_number" },
cvt_no_num2 = { "Needs another number for a range", "needs another number", "option", "needs_another_number" },
cvt_bad_altitude = { '"$1" needs an integer', "invalid altitude", "option", "invalid_altitude" },
cvt_bad_frac = { '"$1" needs an integer above 1', "invalid fraction", "option", "invalid_fraction" },
cvt_bad_prec = { 'Precision "$1" must be an integer', "invalid precision", "option", "invalid_precision" },
cvt_bad_sigfig = { '"$1" needs a positive integer', "invalid sigfig", "option", "invalid_sigfig" },
cvt_empty_option = { 'Ignored empty option "$1"', "empty option", "option", "empty_option" },
cvt_deprecated = { 'Option "$1" is deprecated', "*", "option", "deprecated_option", format = "cvt_format2", nowarn = true },
cvt_no_spell = { "Spelling is not available", "bug, ask for help", "option", "ask_for_help" },
cvt_unknown_option = { 'Ignored invalid option "$1"', "invalid option", "option", "invalid_option" },
cvt_wd_fail = { "Unable to access Wikidata", "wikidata problem", "option", "wikidata_problem" },
cvt_bad_default = { 'Unit "$1" has an invalid default', "bug, ask for help", "unit", "ask_for_help" },
cvt_bad_unit = { 'Unit "$1" is invalid here', "unit invalid here", "unit", "unit_invalid_here" },
cvt_no_default = { 'Unit "$1" has no default output unit', "bug, ask for help", "unit", "ask_for_help" },
cvt_no_unit = { "Needs name of unit", "needs unit name", "unit", "needs_unit_name" },
cvt_unknown = { 'Unit name "$1" is not known', "unknown unit", "unit", "unknown_unit" },
cvt_should_be = { "$1", "ambiguous unit", "unit", "ambiguous_unit", regex = unitcode_regex, replace = unitcode_replace },
cvt_mismatch = { 'Cannot convert "$1" to "$2"', "unit mismatch", "unit", "unit_mismatch" },
cvt_bug_convert = { "Bug: Cannot convert between specified units", "bug, ask for help", "unit", "ask_for_help" },
cvt_lookup = { 'Unit "$1" is incorrectly defined', "bug, ask for help", "unit", "ask_for_help" },
}
local disp_joins = {
["or"] = { " or ", "", " or ", wantname = true },
["sqbr-sp"] = { " [", "]" },
["sqbr-nbsp"] = { " [", "]" },
["comma"] = { ", ", "", ", " },
["slash-sp"] = { " / ", "", wantname = true },
["slash-nbsp"] = { " / ", "", wantname = true },
["slash-nosp"] = { "/", "" },
["b"] = { " (", ")" },
["(or)"] = { " (", ")", " or " },
["br"] = { "<br />", "", wantname = true },
["br()"] = { "<br />(", ")", wantname = true },
}
local range_types = {
["+"] = " + ",
[","] = ", ",
[", and"] = ", and ",
[", or"] = ", or ",
["by"] = " by ",
["-"] = "–",
["to about"] = " to about ",
["and"] = { off = " as ", on = " as ", exception = true },
["as"] = { off = " as ", on = " as ", exception = true },
["and(-)"] = { input = " and ", output = "–" },
["or"] = { off = " or ", on = " or ", exception = true },
["to"] = { off = " to ", on = " to ", exception = true },
["to(-)"] = { input = " to ", output = "–" },
["+/-"] = {
off = " ± ",
on = " ± ",
adj = " ± ",
is_range_change = true,
},
["by(x)"] = { input = " by ", output = " × ", out_range_x = true },
["x"] = { off = " by ", on = " × ", abbr_range_x = true },
["xx"] = " × ",
["*"] = "×",
["/"] = " / ",
}
local range_aliases = {
["–"] = "-",
["–"] = "-",
["×"] = "x",
["×"] = "x",
["±"] = "+/-",
["±"] = "+/-",
}
local range_words = { "-", "–", "xx", "x", "*" }
local ranges = {
types = range_types,
aliases = range_aliases,
words = range_words,
}
local en_option_name = {
["$"] = "$",
["abbr"] = "abbr",
["adj"] = "adj",
["altitude_ft"] = "altitude_ft",
["altitude_m"] = "altitude_m",
["comma"] = "comma",
["debug"] = "debug",
["disp"] = "disp",
["frac"] = "frac",
["input"] = "input",
["lang"] = "lang",
["lk"] = "lk",
["order"] = "order",
["qid"] = "qid",
["qual"] = "qual",
["qualifier"] = "qual",
["round"] = "round",
["sigfig"] = "sigfig",
["sing"] = "adj",
["sortable"] = "sortable",
["sp"] = "sp",
["spell"] = "spell",
["stylein"] = "stylein",
["styleout"] = "styleout",
["tracking"] = "tracking",
}
local en_option_value = {
["$"] = "TEXT",
["abbr"] = {
["def"] = "",
["h"] = "on",
["hh"] = "opt_hand_hh",
["in"] = "in",
["none"] = "off",
["off"] = "off",
["on"] = "on",
["out"] = "out",
["unit"] = "unit",
["values"] = "opt_values",
["~"] = "opt_also_symbol",
},
["adj"] = {
["mid"] = "opt_adjectival, opt_adj_mid",
["off"] = "",
["on"] = "opt_adjectival",
["pre"] = "opt_one_preunit",
["ri0"] = "opt_ri=0",
["ri1"] = "opt_ri=1",
["ri2"] = "opt_ri=2",
["ri3"] = "opt_ri=3",
},
["altitude_ft"] = "INTEGER",
["altitude_m"] = "INTEGER",
["comma"] = {
["5"] = "opt_comma5",
["gaps"] = "opt_gaps",
["gaps3"] = "opt_gaps, opt_gaps3",
["off"] = "opt_nocomma",
},
["debug"] = {
["yes"] = "opt_sortable_debug",
},
["disp"] = {
["5"] = "opt_round=5?",
["b"] = "b",
["(or)"] = "(or)",
["br"] = "br",
["br()"] = "br()",
["comma"] = "comma",
["flip"] = "opt_flip",
["number"] = "opt_output_number_only",
["or"] = "or",
["out"] = "opt_output_only",
["output number only"] = "opt_output_number_only",
["output only"] = "opt_output_only",
["preunit"] = "opt_two_preunits",
["sqbr"] = "sqbr",
["table"] = "opt_table",
["tablecen"] = "opt_tablecen",
["unit"] = "opt_input_unit_only",
["unit or text"] = "opt_input_unit_only, opt_ignore_error",
["unit2"] = "opt_output_unit_only",
["x"] = "x",
},
["frac"] = "INTEGER",
["input"] = "TEXT",
["lang"] = {
["en"] = "opt_lang_en",
["local"] = "opt_lang_local",
},
["lk"] = {
["in"] = "in",
["off"] = "off",
["on"] = "on",
["out"] = "out",
},
["order"] = {
["flip"] = "opt_flip",
["out"] = "opt_order_out",
},
["qid"] = "TEXT",
["qual"] = "TEXT",
["round"] = {
["0.5"] = "opt_round=0.5",
["5"] = "opt_round=5",
["10"] = "opt_round=10",
["25"] = "opt_round=25",
["50"] = "opt_round=50",
["each"] = "opt_round_each",
},
["sigfig"] = "INTEGER",
["sortable"] = {
["off"] = "",
["on"] = "opt_sortable_on",
["debug"] = "opt_sortable_on, opt_sortable_debug",
},
["sp"] = {
["us"] = "opt_sp_us",
},
["spell"] = {
["in"] = "opt_spell_in",
["In"] = "opt_spell_in, opt_spell_upper",
["on"] = "opt_spell_in, opt_spell_out",
["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper",
},
["stylein"] = "TEXT",
["styleout"] = "TEXT",
["tracking"] = "TEXT",
}
local titles = {
["frac"] = "Fraction/styles.css",
["sfrac"] = "Sfrac/styles.css",
}
return {
SIprefixes = SIprefixes,
all_categories = all_categories,
all_messages = all_messages,
currency = { ["$"] = true, ["£"] = true, ["€"] = true, ["₱"] = true, ["₽"] = true, ["¥"] = true },
customary_units = customary_units,
disp_joins = disp_joins,
en_option_name = en_option_name,
en_option_value = en_option_value,
eng_scales = eng_scales,
ranges = ranges,
titles = titles,
}
1l0fb3ngznykcjyarmr4gq6j76igrl0
392701
392698
2026-09-02T00:47:03Z
MacTire02
219
prowal
392701
Scribunto
text/plain
-- Text used by Module:Convert for enwiki.
-- This is a separate module to simplify translation for use on another wiki.
-- See [[:en:Template:Convert/Transwiki guide]] if copying to another wiki.
-- Some units accept an SI prefix before the unit code, such as "kg" for kilogram.
local SIprefixes = {
-- The prefix field is what the prefix should be, if different from the prefix used.
['Y'] = { exponent = 24, name = 'yotta', },
['Z'] = { exponent = 21, name = 'zetta', },
['E'] = { exponent = 18, name = 'exa' , },
['P'] = { exponent = 15, name = 'peta' , },
['T'] = { exponent = 12, name = 'tera' , },
['G'] = { exponent = 9, name = 'giga' , },
['M'] = { exponent = 6, name = 'mega' , },
['k'] = { exponent = 3, name = 'kilo' , },
['h'] = { exponent = 2, name = 'hecto', },
['da']= { exponent = 1, name = 'deca' , name_us = 'deka' },
['d'] = { exponent = -1, name = 'deci' , },
['c'] = { exponent = -2, name = 'centi', },
['m'] = { exponent = -3, name = 'milli', },
['μ'] = { exponent = -6, name = 'micro', }, -- key = 'GREEK SMALL LETTER MU' (U+03BC) utf-8 CE BC
['µ'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- key = 'MICRO SIGN' (U+00B5) utf-8 C2 B5
['u'] = { exponent = -6, name = 'micro', prefix = 'μ' }, -- not an SI prefix, but allow for people typing this
['n'] = { exponent = -9, name = 'nano' , },
['p'] = { exponent =-12, name = 'pico' , },
['f'] = { exponent =-15, name = 'femto', },
['a'] = { exponent =-18, name = 'atto' , },
['z'] = { exponent =-21, name = 'zepto', },
['y'] = { exponent =-24, name = 'yocto', },
}
-- Some units can be qualified with one of the following prefixes, when linked.
local customary_units = {
{ "US", link = "United States customary units" },
{ "U.S.", link = "United States customary units" },
{ "imperial", link = "Imperial units" },
{ "imp", link = "Imperial units" },
}
-- Names when using engineering notation (a prefix of "eN" where N is a number; example "e6km").
-- key = { "name", link = "article title", exponent = numeric_key_value }
-- If lk=on and link is defined, the name of the number will appear as a link.
local eng_scales = {
["3"] = { "thousand", exponent = 3 },
["6"] = { "million", exponent = 6 },
["9"] = { "billion", link = "1000000000 (number)", exponent = 9 },
["12"] = { "trillion", link = "1000000000000 (number)", exponent = 12 },
["15"] = { "quadrillion", link = "1000000000000000 (number)", exponent = 15 },
}
local all_categories = {
unit = "[[Category:Convert errors]]",
option = "[[Category:Convert errors]]",
warning = '[[Category:Convert invalid options]]',
tracking = '[[Category:Convert tracking]]',
}
-- For some error messages, the following puts the wanted style around
-- each unit code marked like '...%{ft%}...'.
local unitcode_regex = '%%([{}])'
local unitcode_replace = { ['{'] = '"', ['}'] = '"' } -- no longer need the more elaborate substitute used before 2013-09-28
-- All messages that may be displayed if a problem occurs.
local all_messages = {
-- Message format string: $1=title, $2=text, $3=category, $4=anchor.
-- Each displayed message starts with "Convert:" so can easily locate by searching article.
cvt_format = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[<i>[[Help:Convert messages#$4|<span title="Convert: $1">convert: $2</span>]]</i>]</sup>$3<span class="error"></span>',
cvt_format2 = '<sup class="noprint Inline-Template" style="white-space:nowrap;">[[Help:Convert messages#$4|<span title="Convert: $1">$2</span>]]</sup>$3<span class="error"></span>',
cvt_format_preview = '<strong class="error">Error in convert: $1 [[Help:Convert messages#$4|(help)]]</strong>$3',
-- Each of following messages is a table:
-- { [1] = 'title', -- mouseover title text
-- [2] = 'text', -- link text displayed in article
-- [3] = 'category key', -- key to lookup category in all_categories
-- [4] = 'anchor', -- anchor for link to relevant section on help page
-- regex = gsub_regex,
-- replace = gsub_table,
-- } Mouseover title text Link text CatKey Anchor
cvt_bad_input = { 'input "$1" must be a number and unit' , 'invalid input' , 'option', 'invalid_input' },
cvt_bad_num = { 'Value "$1" must be a number' , 'invalid number' , 'option', 'invalid_number' },
cvt_big_prec = { 'Precision "$1" is too large' , 'precision too large' , 'option', 'precision_too_large' },
cvt_invalid_num = { 'Number has overflowed' , 'number overflow' , 'option', 'number_overflow' },
cvt_no_num = { 'Needs the number to be converted' , 'needs a number' , 'option', 'needs_number' },
cvt_no_num2 = { 'Needs another number for a range' , 'needs another number', 'option', 'needs_another_number' },
cvt_bad_altitude = { '"$1" needs an integer' , 'invalid altitude' , 'option', 'invalid_altitude' },
cvt_bad_frac = { '"$1" needs an integer above 1' , 'invalid fraction' , 'option', 'invalid_fraction' },
cvt_bad_prec = { 'Precision "$1" must be an integer' , 'invalid precision' , 'option', 'invalid_precision' },
cvt_bad_sigfig = { '"$1" needs a positive integer' , 'invalid sigfig' , 'option', 'invalid_sigfig' },
cvt_empty_option = { 'Ignored empty option "$1"' , 'empty option' , 'option', 'empty_option' },
cvt_deprecated = { 'Option "$1" is deprecated' , '*' , 'option', 'deprecated_option', format = 'cvt_format2', nowarn = true },
cvt_no_spell = { 'Spelling is not available' , 'bug, ask for help' , 'option', 'ask_for_help' },
cvt_unknown_option = { 'Ignored invalid option "$1"' , 'invalid option' , 'option', 'invalid_option' },
cvt_wd_fail = { 'Unable to access Wikidata' , 'wikidata problem' , 'option', 'wikidata_problem' },
cvt_bad_default = { 'Unit "$1" has an invalid default' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_bad_unit = { 'Unit "$1" is invalid here' , 'unit invalid here' , 'unit' , 'unit_invalid_here' },
cvt_no_default = { 'Unit "$1" has no default output unit' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_no_unit = { 'Needs name of unit' , 'needs unit name' , 'unit' , 'needs_unit_name' },
cvt_unknown = { 'Unit name "$1" is not known' , 'unknown unit' , 'unit' , 'unknown_unit' },
cvt_should_be = { '$1' , 'ambiguous unit' , 'unit' , 'ambiguous_unit', regex = unitcode_regex, replace = unitcode_replace },
cvt_mismatch = { 'Cannot convert "$1" to "$2"' , 'unit mismatch' , 'unit' , 'unit_mismatch' },
cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'bug, ask for help' , 'unit' , 'ask_for_help' },
cvt_lookup = { 'Unit "$1" is incorrectly defined' , 'bug, ask for help' , 'unit' , 'ask_for_help' },
}
-- Text to join input value/unit with output value/unit.
local disp_joins = {
-- [1]=before output, [2]=after output, [3]=between outputs in a combination; default "; "
-- [wantname] gives default abbr=off
["or"] = { " or " , "" , " or ", wantname = true },
["sqbr-sp"] = { " [" , "]" },
["sqbr-nbsp"] = { " [" , "]" },
["comma"] = { ", " , "" , ", " },
["slash-sp"] = { " / " , "" , wantname = true },
["slash-nbsp"] = { " / ", "" , wantname = true },
["slash-nosp"] = { "/" , "" , wantname = true },
["b"] = { " (" , ")" },
["(or)"] = { " (" , ")", " or " },
["br"] = { "<br />" , "" , wantname = true },
["br()"] = { "<br />(" , ")", wantname = true },
}
-- Text to separate values in a range.
local range_types = {
-- Specifying a table requires either:
-- * "off" and "on" values (for "abbr=off" and "abbr=on"), or
-- * "input" and "output" values (for LHS and RHS);
-- other fields are optional.
-- When "adj=on|abbr=off" applies, spaces in range text are replaced with hyphens.
-- With "exception = true", that also occurs with "adj=on|abbr=on".
-- If "adj" is defined here, that text (unchanged) is used with "adj=on".
["+"] = " + ",
[","] = ", ",
[", and"] = ", and ",
[", or"] = ", or ",
["by"] = " by ",
["-"] = "–",
["to about"] = " to about ",
["and"] = { off = " and ", on = " and ", exception = true },
["as"] = { off = " as ", on = " as ", exception = true }, -- Manx range separator
["and"] = { off = " as ", on = " as ", exception = true },
["and(-)"] = { input = " and ", output = "–" },
["or"] = { off = " or " , on = " or " , exception = true },
["to"] = { off = " to " , on = " to " , exception = true },
["to(-)"] = { input = " to ", output = "–" },
["+/-"] = { off = " ± ", on = " ± ", adj = " ± ", is_range_change = true },
["by(x)"] = { input = " by ", output = " × ", out_range_x = true },
["x"] = { off = " by ", on = " × ", abbr_range_x = true },
["xx"] = " × ",
["*"] = "×",
["/"] = " / ", -- for a table of high/low temperatures with {{convert|83|/|63|F|disp=br()|abbr=values}}
}
local range_aliases = {
-- ["alternative name for a range"] = "standard range name"
["–"] = "-",
["–"] = "-",
["×"] = "x",
["×"] = "x",
["±"] = "+/-",
["±"] = "+/-",
}
-- Convert accepts range text delimited with whitespace, for example, {{convert|1 to 2|ft}}.
-- In addition, the following "words" are accepted without spaces, for example, {{convert|1-2|ft}}.
-- Words must be in correct order for searching, for example, 'x' after 'xx'.
local range_words = { '-', '–', 'xx', 'x', '*' }
local ranges = {
types = range_types,
aliases = range_aliases,
words = range_words,
}
-- Valid option names.
local en_option_name = {
-- ["local text for option name"] = "en name used in this module"
["$"] = "$",
["abbr"] = "abbr",
["adj"] = "adj",
["altitude_ft"] = "altitude_ft",
["altitude_m"] = "altitude_m",
["comma"] = "comma",
["debug"] = "debug",
["disp"] = "disp",
["frac"] = "frac",
["input"] = "input",
["lang"] = "lang",
["lk"] = "lk",
["order"] = "order",
["qid"] = "qid",
["qual"] = "qual",
["qualifier"] = "qual",
["round"] = "round",
["sigfig"] = "sigfig",
["sing"] = "adj", -- "sing" is an old alias for "adj"
["sortable"] = "sortable",
["sp"] = "sp",
["spell"] = "spell",
["stylein"] = "stylein",
["styleout"] = "styleout",
["tracking"] = "tracking",
}
-- Valid option values.
-- Convention: parms.opt_xxx refers to an option that is set here
-- (not intended to be set by the template which invokes this module).
-- Example: At enwiki, "abbr" includes:
-- ["values"] = "opt_values"
-- As a result, if the template uses abbr=values, Module:Convert sets:
-- parms["opt_values"] = true
-- parms["abbr"] = nil
-- Therefore parms.abbr will be nil, or will have one of the listed values
-- that do not start with "opt_".
-- An option value of form "xxx?" is the same as "xxx" but shows the input as deprecated.
local en_option_value = {
["$"] = 'TEXT', -- TEXT should be a currency symbol that will be used instead of "$"
["abbr"] = {
-- ["local text for option value"] = "en value used in this module"
["def"] = "", -- ignored (some wrapper templates call convert with "abbr=def" to mean "default abbreviation")
["h"] = "on", -- abbr=on + use "h" for hand unit (default)
["hh"] = "opt_hand_hh", -- abbr=on + use "hh" for hand unit
["in"] = "in", -- use symbol for LHS unit
["none"] = "off", -- old name for "off"
["off"] = "off", -- use name for all units
["on"] = "on", -- use symbol for all units
["out"] = "out", -- use symbol for RHS unit (default)
["unit"] = "unit", -- abbr=on but abbreviate units only: e6km → million km (not ×10⁶ km)
["values"] = "opt_values", -- show only input and output numbers, not units
["~"] = "opt_also_symbol", -- show input unit symbol as well as name
},
["adj"] = {
["mid"] = "opt_adjectival, opt_adj_mid", -- adj=on with user-specified text after input unit (between input and output)
["off"] = "", -- ignored (off is the default)
["on"] = "opt_adjectival", -- unit name is singular and hyphenated
["pre"] = "opt_one_preunit", -- user-specified text before input unit
["ri0"] = "opt_ri=0", -- round input with precision = 0
["ri1"] = "opt_ri=1", -- round input with precision = 1
["ri2"] = "opt_ri=2", -- round input with precision = 2
["ri3"] = "opt_ri=3", -- round input with precision = 3
},
["altitude_ft"] = 'INTEGER',
["altitude_m"] = 'INTEGER',
["comma"] = {
["5"] = "opt_comma5", -- only use numsep grouping if 5 or more digits
["gaps"] = "opt_gaps", -- use gaps, not numsep, to separate groups of digits
["gaps3"] = "opt_gaps, opt_gaps3", -- group only in threes rather than default of no gap before a single digit after decimal mark
["off"] = "opt_nocomma", -- no numsep in input or output numbers
},
["debug"] = {
["yes"] = "opt_sortable_debug", -- make the normally hidden sort key visible
},
["disp"] = {
["5"] = "opt_round=5?", -- round output value to nearest 5
["b"] = "b", -- join: '(...)'
["(or)"] = "(or)", -- join: '(...)' with 'or' between outputs in a combination
["br"] = "br", -- join: '<br />'
["br()"] = "br()", -- join: '<br />(...)'
["comma"] = "comma", -- join: ','
["flip"] = "opt_flip", -- reverse order of input/output
["number"] = "opt_output_number_only", -- display output value (not input, and not output symbol/name)
["or"] = "or", -- join: 'or'
["out"] = "opt_output_only",
["output number only"] = "opt_output_number_only",
["output only"] = "opt_output_only",
["preunit"] = "opt_two_preunits", -- user-specified text before input and output units
["sqbr"] = "sqbr", -- join: '[...]'
["table"] = "opt_table", -- output is suitable for a table cell with align="right"
["tablecen"] = "opt_tablecen", -- output is suitable for a table cell with align="center"
["unit"] = "opt_input_unit_only", -- display input symbol/name (not output, and not input value)
["unit or text"] = "opt_input_unit_only, opt_ignore_error", -- display input symbol/name, or given unit code if not known
["unit2"] = "opt_output_unit_only",
["x"] = "x", -- join: <first>...<second> (user-specified text)
},
["frac"] = 'INTEGER',
["input"] = 'TEXT', -- TEXT should be value><space><unitcode> or <wikidata-property-id>
["lang"] = { -- language for output digits (both en and local digits are always accepted for input)
["en"] = "opt_lang_en", -- use en digits for numbers, regardless of local language
["local"] = "opt_lang_local", -- use local digits for numbers (default, although config can change default to en)
},
["lk"] = {
["in"] = "in", -- link LHS unit name or symbol
["off"] = "off", -- do not link: same as default except for hand unit
["on"] = "on", -- link all unit names or symbols (but not twice for the same unit)
["out"] = "out", -- link RHS unit name or symbol
},
["order"] = {
["flip"] = "opt_flip", -- reverse order of input/output
["out"] = "opt_order_out", -- do not show input; instead, use order in output combination, with the first output shown as the input
},
["qid"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["qual"] = 'TEXT', -- TEXT should be a Wikidata Q item identifier
["round"] = {
["0.5"] = "opt_round=0.5", -- round output value to nearest 0.5
["5"] = "opt_round=5", -- round output value to nearest 5
["10"] = "opt_round=10", -- round output value to nearest 10 (same as but clearer than "|-1")
["25"] = "opt_round=25", -- round output value to nearest 25
["50"] = "opt_round=50", -- round output value to nearest 50
["each"] = "opt_round_each", -- using default precision in a range, round each output separately (default uses highest precision of each item in range)
},
["sigfig"] = 'INTEGER',
["sortable"] = {
["off"] = "", -- ignored (off is the default)
["on"] = "opt_sortable_on", -- output sort key for use in a sortable table, based on value from converting to a standard base unit
["debug"] = "opt_sortable_on, opt_sortable_debug", -- |sortable=debug is the same as |sortable=on|debug=yes
},
["sp"] = {
["us"] = "opt_sp_us", -- use U.S. spelling (like "meter" instead of default "metre")
},
["spell"] = { -- only English spelling is supported; not scientific notation; only some fractions
["in"] = "opt_spell_in", -- spell input value in words
["In"] = "opt_spell_in, opt_spell_upper", -- spell input value in words with first letter uppercase
["on"] = "opt_spell_in, opt_spell_out", -- spell input and output values in words
["On"] = "opt_spell_in, opt_spell_out, opt_spell_upper", -- same, with first letter of first word in result uppercase
},
["stylein"] = 'TEXT',
["styleout"] = 'TEXT',
["tracking"] = 'TEXT',
}
local titles = {
["frac"] = "Fraction/styles.css",
["sfrac"] = "Sfrac/styles.css",
}
return {
SIprefixes = SIprefixes,
all_categories = all_categories,
all_messages = all_messages,
currency = { ['$'] = true, ['£'] = true, ['€'] = true, ['₱'] = true, ['₽'] = true, ['¥'] = true },
customary_units = customary_units,
disp_joins = disp_joins,
en_option_name = en_option_name,
en_option_value = en_option_value,
eng_scales = eng_scales,
ranges = ranges,
titles = titles,
}
q75z7sckgiprvirbw8r75xxivdmdhf5
Module:Lang
828
30693
392719
336923
2026-09-02T02:32:40Z
MacTire02
219
++
392719
Scribunto
text/plain
--[=[
Lua support for the {{lang}}, {{langx}}, {{lang-??}}, and {{transliteration}} templates and replacement of various supporting templates.
]=]
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local unicode = require ("Module:Unicode data"); -- for is_Latin() and is_rtl()
local yesno = require ('Module:Yesno');
local sandbox = (mw.getCurrentFrame():getTitle():match ('/sandbox') or ''); -- when called from a sandbox template or module load sandbox data and sandbox configuration
local lang_data = mw.loadData ('Module:Lang/data' .. sandbox); -- language name override and transliteration tool-tip tables
local lang_name_table = lang_data.lang_name_table; -- language codes, names, regions, scripts, suppressed scripts
local lang_table = lang_data.lang_name_table.lang;
local lang_dep_table = lang_data.lang_name_table.lang_dep;
local script_table = lang_data.lang_name_table.script;
local region_table = lang_data.lang_name_table.region;
local variant_table = lang_data.lang_name_table.variant;
local suppressed_table = lang_data.lang_name_table.suppressed;
local override_table = lang_data.override;
local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms'); -- ISO 639-2/639-2T code translation to 639-1 code
local cfg = mw.loadData ('Module:Lang/configuration' .. sandbox); -- for internationalization
local is_latn_data = mw.loadData ('Module:Lang/data/is latn data');
local sizeof_ranges_t = is_latn_data.sizeof_ranges_t;
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
local content_lang = mw.language.getContentLanguage();
local this_wiki_lang_tag = content_lang.code; -- get this wiki's language tag
local this_wiki_lang_dir = content_lang:getDir(); -- get this wiki's language direction
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic()
local maint_cats = {}; -- maintenance categories go here
local maint_msgs = {}; -- and their messages go here
--[[--------------------------< M A K E _ E R R O R _ S P A N >--------------------------------------------------
]]
local function make_error_span (template, msg)
return table.concat ({'<span style="color:var(--color-error,#d33)">', cfg.misc_text_t.error, ': ', template, msg, '</span>'})
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.
]]
local function substitute (message, data_t)
return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end
--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
Assembles an error message from template name, message text, help link, and error category.
]]
local function make_error_msg (msg, args_t, template)
local category;
local text; -- handle the oddity that is {{langx}}
if cfg.templates_t.langxx == template then
text = args_t.text or args_t[1]; -- for {{lang-xx}}
else
text = args_t.text or args_t[2]; -- for {{lang}}, {{langx}}, and {{transliteration}}
end
if cfg.templates_t.transliteration == template then
category = cfg.make_error_msg_t.xlit_err_cat;
else
category = cfg.make_error_msg_t.lang_err_cat;
end
local category_link = ((0 == namespace or 10 == namespace) and not args_t.nocat) and substitute ('[[Category:$1]]', {category}) or '';
return substitute ('[$1] <span style="color:var(--color-error,#d33)">$2: {{$3}}: $4 ([[:Category:$5|$6]])</span>$7', -- { prevents template name from being treated as a template call in certain situations
{
text or cfg.make_error_msg_t.undefined,
cfg.misc_text_t.error,
template,
msg,
category,
cfg.misc_text_t.help,
category_link
})
end
--[[--------------------------< P A R A M E T E R _ V A L I D A T E >------------------------------------------
]]
local function parameter_validate (args_t, template)
local err_msg = cfg.parameter_validate_t.invalid_param;
if cfg.templates_t.lang == template then -- for {{lang}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_t[param] and -- unique {{lang}} parameters
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langx == template then -- for {{langx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_langx_t[param] and -- unique {{langx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langxx == template then -- for {{lang-xx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_xx_t[param] and -- unique {{lang-xx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
end
end
--[[--------------------------< 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 V E R T _ I T A L I C S >-------------------------------------------------
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing
apostrophes are converted to their HTML numeric entity equivalent so that the new italic markup doesn't become
bold markup inadvertently.
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal,
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements.
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns.
This function expects that markup in args.text is complete and correct; if it is not, oddness may result.
]]
local function invert_italics (source)
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns
[""]="\'\'", -- empty string becomes italic markup
["\'\'"]="", -- italic markup becomes empty string
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold
};
local seg = {};
source = source:gsub ("%f[\']\'%f[^\']", '''); -- protect single quote marks from being interpreted as bold markup
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text'
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup
elseif '' ~= seg[1] then
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup
elseif '' ~= seg[3] then
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup
else
seg[2] = source -- when there is no markup
end
seg[1] = invert_pattern_table[seg[1]] or seg[1]; -- replace leading markup according to pattern table
seg[3] = invert_pattern_table[seg[3]] or seg[3]; -- replace leading markup according to pattern table
return table.concat (seg); -- put it all back together and done
end
--[[--------------------------< V A L I D A T E _ I T A L I C >------------------------------------------------
Validates |italic= or |italics= assigned values.
When |italic= is set and has an acceptable assigned value, return the matching CSS font-style property value or,
for the special case 'default', return nil.
When |italic= is not set, or has an unacceptable assigned value, return nil and a nil error message.
When both |italic= and |italics= are set, returns nil and a 'conflicting' error message.
The return value nil causes the calling lang, lang_xx, or xlit function to set args.italic according to the template's
defined default ('inherit' for {{lang}}, 'inherit' or 'italic' for {{lang-??}} depending on
the individual template's requirements, 'italic' for {{transliteration}}) or to the value appropriate to |script=, if set ({{lang}}
and {{lang-??}} only).
Accepted values and the values that this function returns are are:
nil - when |italic= absent or not set; returns nil
default - for completeness, should rarely if ever be used; returns nil
yes - force args.text to be rendered in italic font; returns 'italic'
no - force args.text to be rendered in normal font; returns 'normal'
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit'
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert'
]]
local function validate_italic (args)
local properties = {[cfg.keywords_t.affirmative] = 'italic', [cfg.keywords_t.negative] = 'normal', [cfg.keywords_t.unset] = 'inherit', [cfg.keywords_t.invert] = 'invert', [cfg.keywords_t.default] = nil};
local count = 0
for _, arg in pairs {'italic', 'italics', 'i'} do
if args[arg] then
count = count + 1
end
end
if count > 1 then -- return nil and an error message if more than one is set
return nil, cfg.validate_italic_t.multi_italic;
end
return properties[args.italic or args.italics or args.i], nil; -- return an appropriate value and a nil error message
end
--[=[--------------------------< V A L I D A T E _ C A T _ A R G S >----------------------------------------------------------
Default behavior of the {{lang}} and {{lang-??}} templates is to add categorization when the templates are used in main space.
This default functionality may be suppressed by setting |nocat=yes or |cat=no. This function selects one of these two parameters
to control categorization.
Because having two parameters with 'opposite' names and 'opposite' values is confusing, this function accepts only affirmative
values for |nocat= and only negative values for |cat=; in both cases the 'other' sense (and non-sense) is not accepted and the
parameter is treated as if it were not set in the template.
Sets args.nocat to true if categorization is to be turned off; to nil if the default behavior should apply.
Accepted values for |nocat= are the text strings:
'yes', 'y', 'true', 't', on, '1' -- [[Module:Yesno]] returns logical true for all of these; false or nil else
for |cat=
'no', 'n', 'false', 'f', 'off', '0' -- [[Module:Yesno]] returns logical false for all of these; true or nil else
]=]
local function validate_cat_args (args)
if not (args.nocat or args.cat) then -- both are nil, so categorize
return;
end
if false == yesno (args.cat) or true == yesno (args.nocat) then
args.nocat = true; -- set to true when args.nocat is affirmative; nil else (as if the parameter were not set in the template)
else -- args.nocat is the parameter actually used.
args.nocat = nil;
end
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
--[[--------------------------< F O R M A T _ I E T F _ T A G >------------------------------------------------
Prettify IETF tags to use recommended subtag formats:
code: lower case
script: sentence case
region: upper case
variant: lower case
private: lower case prefixed with -x-
]]
local function format_ietf_tag (code, script, region, variant, private)
local out = {};
if is_set (private) then
return table.concat ({code:lower(), 'x', private:lower()}, '-'); -- if private, all other tags ignored
end
table.insert (out, code:lower());
if is_set (script) then
script = script:lower():gsub ('^%a', string.upper);
table.insert (out, script);
end
if is_set (region) then
table.insert (out, region:upper());
end
if is_set (variant) then
table.insert (out, variant:lower());
end
return table.concat (out, '-');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
Extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character IANA language code
script subtag - four character IANA script code
region subtag - two-letter or three digit IANA region code
variant subtag - four digit or 5-8 alnum variant code; only one variant subtag supported
private subtag - x- followed by 1-8 alnum private code; only supported with the primary language tag
in any one of these forms
lang lang-variant
lang-script lang-script-variant
lang-region lang-region-variant
lang-script-region lang-script-region-variant
lang-x-private
each of lang, script, region, variant, and private, when used, must be valid.
Languages with both two- and three-character code synonyms are promoted to the two-character synonym because
the IANA registry file omits the synonymous three-character code; we cannot depend on browsers understanding
the synonymous three-character codes in the lang= attribute.
For {{lang-??}} templates, the parameters |script=, |region=, and |variant= are supported (not supported in {{lang}}
because those parameters are superfluous to the IETF subtags in |code=).
Returns six values; all lower case. Valid parts are returned as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil; the sixth returned item is an error message (if an error detected) or nil.
See http://www.rfc-editor.org/rfc/bcp/bcp47.txt section 2.1.
]]
local function get_ietf_parts (source, args_script, args_region, args_variant)
local code, script, region, variant, private; -- IETF tag parts
if not is_set (source) then
return nil, nil, nil, nil, nil, cfg.get_ietf_parts_t.missing_lang_tag;
end
local pattern = { -- table of tables holding acceptable IETF tag patterns and short names of the IETF part captured by the pattern
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits)
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits)
{'^(%a%a%a?)$'}, -- 18 - ll
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters)
}
local t = {}; -- table of captures; serves as a translator between captured IETF tag parts and named variables
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i])
if c1 then -- c1 always set on match
code = c1; -- first capture is always code
t = {
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table
};
script = t.s or ''; -- translate table contents to named variables;
region = t.r or ''; -- absent table entries are nil so set named IETF parts to empty string for concatenation
variant= t.v or '';
private = t.p or '';
break; -- and done
end
end
if not code then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_tag, {source}); -- don't know what we got but it is malformed
end
code = code:lower(); -- ensure that we use and return lower case version of this
if not (override_table[code] or lang_table[code] or synonym_table[code] or lang_dep_table[code]) then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_code, {code}); -- invalid language code, don't know about the others (don't care?)
end
if synonym_table[code] then -- if 639-2/639-2T code has a 639-1 synonym
table.insert (maint_cats, substitute (cfg.get_ietf_parts_t.maint_promo_cat, {code}));
table.insert (maint_msgs, substitute (cfg.get_ietf_parts_t.maint_promo_msg, {code, synonym_table[code]}));
code = synonym_table[code]; -- use the synonym
end
if is_set (script) then
if is_set (args_script) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_scr; -- both code with script and |script= not allowed
end
else
script = args_script or ''; -- use args.script if provided
end
if is_set (script) then
script = script:lower(); -- ensure that we use and return lower case version of this
if not script_table[script] then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_scr_code, {script, code}); -- language code OK, invalid script, don't know about the others (don't care?)
end
end
if suppressed_table[script] then -- ensure that code-script does not use a suppressed script
if in_array (code, suppressed_table[script]) then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.script_code, {script, code}); -- language code OK, script is suppressed for this code
end
end
if is_set (region) then
if is_set (args_region) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_reg; -- both code with region and |region= not allowed
end
else
region = args_region or ''; -- use args.region if provided
end
if is_set (region) then
region = region:lower(); -- ensure that we use and return lower case version of this
if not region_table[region] then
return code, script, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_reg_code, {region, code});
end
end
if is_set (variant) then
if is_set (args_variant) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_var; -- both code with variant and |variant= not allowed
end
else
variant = args_variant or ''; -- use args.variant if provided
end
if is_set (variant) then
variant = variant:lower(); -- ensure that we use and return lower case version of this
if not variant_table[variant] then -- make sure variant is valid
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var, {variant});
end -- does this duplicate/replace tests in lang() and lang_xx()?
if is_set (script) then -- if script set it must be part of the 'prefix'
if not in_array (table.concat ({code, '-', script}), variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_scr, {variant, code, script});
end
elseif is_set (region) then -- if region set, there are some prefixes that require lang code and region (en-CA-newfound)
if not in_array (code, variant_table[variant]['prefixes']) then -- first see if lang code is all that's required (en-oxendict though en-GB-oxendict is preferred)
if not in_array (table.concat ({code, '-', region}), variant_table[variant]['prefixes']) then -- now try for lang code and region (en-CA-newfound)
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_reg, {variant, code, region});
end
end
else -- cheap way to determine if there are prefixes; fonipa and others don't have prefixes; # operator always returns 0
if variant_table[variant]['prefixes'][1] and not in_array (code, variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code, {variant, code});
end
end
end
if is_set (private) then
private = private:lower(); -- ensure that we use and return lower case version of this
if not override_table[table.concat ({code, '-x-', private})] then -- make sure private tag is valid; note that index
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_pri, {private});
end
end
return code, script, region, variant, private, nil; -- return the good bits; make sure that msg is nil
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, 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 is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< D I V _ M A R K U P _ A D D >--------------------------------------------------
Adds <i> and </i> tags to list-item text or to implied <p>..</p> text. Mixed not supported.
]]
local function div_markup_add (text, style)
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text
if 'italic' == style then
return text:gsub ('(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item
else
return text;
end
end
if text:find ('\n+') then -- look for any number of \n characters in text
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics MediaWiki
if 'italic' == style then
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each implied p (two or more consecutive '\n\n' sequences)
else
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each implied p
text = text:gsub ('\n', ''); -- strip newline characters
end
end
return text;
end
--[[--------------------------< T I T L E _ W R A P P E R _ M A K E >------------------------------------------
Makes a <span title="<title text>"><content_text></span> or <div title="<title text>"><content_text></div> where
<title text> is in the tool-tip in the wiki's local language and <content_text> is non-local-language text in
HTML markup. This because the lang= attribute applies to the content of its enclosing tag.
<tag> holds a string 'div' or 'span' used to choose the correct wrapping tag.
]]
local function title_wrapper_make (title_text, content_text, tag)
local wrapper_t = {};
table.insert (wrapper_t, table.concat ({'<', tag})); -- open opening wrapper tag
table.insert (wrapper_t, ' title=\"'); -- begin title attribute
table.insert (wrapper_t, title_text); -- add <title_text>
table.insert (wrapper_t, '\">'); -- end title attribute and close opening wrapper tag
table.insert (wrapper_t, content_text); -- add <content_text>
table.insert (wrapper_t, table.concat ({'</', tag, '>'})); -- add closing wrapper tag
return table.concat (wrapper_t); -- make a big string and done
end
--[[--------------------------< M A K E _ T E X T _ H T M L >--------------------------------------------------
Add the HTML markup to text according to the type of content that it is: <span> or <i> tags for inline content or
<div> tags for block content
The lang= attribute also applies to the content of the tag where it is placed so this is wrong because 'Spanish
language text' is English:
<i lang="es" title="Spanish language text">casa</i>
should be:
<span title="Spanish language text"><i lang="es">casa</i></span>
or for <div>...</div>:
<div title="Spanish language text"><div lang="es"><spanish-language-text></div></div>
]]
local function make_text_html (code, text, tag, rtl, style, size, language)
local html_t = {};
local style_added = '';
local wrapper_tag = tag; -- <tag> gets modified so save a copy for use when/if we create a wrapper span or div
if text:match ('^%*') then
table.insert (html_t, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plain splat confuses MediaWiki
text = text:gsub ('^%*', ''); -- remove the splat from the text
end
if 'span' == tag then -- default HTML tag for inline content
if 'italic' == style then -- but if italic
tag = 'i'; -- change to <i> tags
end
else -- must be div so go
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i>
end
table.insert (html_t, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> HTML tag
code = code:gsub ('%-x%-.*', ''); -- strip private use subtag from code tag because meaningless outside of Wikipedia
table.insert (html_t, table.concat ({' lang="', code, '\"'})); -- add language attribute
if (rtl or unicode.is_rtl(text)) and ('ltr' == this_wiki_lang_dir) then -- text is right-to-left on a left-to-right wiki
table.insert (html_t, ' dir="rtl"'); -- add direction attribute for right-to-left languages
elseif not (rtl or unicode.is_rtl(text)) and ('rtl' == this_wiki_lang_dir) then -- text is left-to-right on a right-to-left wiki
table.insert (html_t, ' dir="ltr"'); -- add direction attribute for left-to-right languages
end
if 'normal' == style then -- when |italic=no
table.insert (html_t, ' style=\"font-style: normal;'); -- override external markup, if any
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
if is_set (size) then -- when |size=<something>
if is_set (style_added) then
table.insert (html_t, table.concat ({' font-size: ', size, ';'})); -- add when style attribute already inserted
else
table.insert (html_t, table.concat ({' style=\"font-size: ', size, ';'})); -- create style attribute
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
end
table.insert (html_t, table.concat ({style_added, '>'})); -- close the opening HTML tag
table.insert (html_t, text); -- insert the text
table.insert (html_t, table.concat ({'</', tag, '>'})); -- close the 'text' <i>, <span>, or <div> HTML tag
if is_set (language) then -- create a <title_text> string for the title= attribute in a wrapper span or div
local title_text;
if 'zxx' == code then -- special case for this tag 'no linguistic content'
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.zxx}); -- not a language so don't use 'language' in title text
elseif mw.ustring.find (language, 'languages', 1, true) then
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.collective}); -- for collective languages
else
title_text = substitute ('$1-$2', {language, cfg.make_text_html_t.individual}); -- for individual languages
end
return title_wrapper_make (title_text, table.concat (html_t), wrapper_tag);
else
return table.concat (html_t);
end
end
--[=[-------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
For individual language, <language>, returns:
[[Category:Articles containing <language>-language text]]
For English:
[[Category:Articles containing explicitly cited English-language text]]
For ISO 639-2 collective languages (and for 639-1 bh):
[[Category:Articles with text in <language> languages]]
]=]
local function make_category (code, language_name, nocat, name_get)
if ((0 ~= namespace) or nocat) and not name_get then -- only categorize in article space
return ''; -- return empty string for concatenation
end
if mw.ustring.find (language_name, 'languages', 1, true) then
return substitute ('[[$1 $2]]', {cfg.make_category_t.collective_cat, language_name});
end
if this_wiki_lang_tag == code then
return substitute ('[[$1 $2 $3-$4]]', { -- unique category name for the local language
cfg.make_category_t.cat_prefix,
cfg.make_category_t.explicit_cat,
language_name,
cfg.make_category_t.cat_postfix,
});
else
return substitute ('[[$1 $2-$3]]', { -- category for individual languages
cfg.make_category_t.cat_prefix,
language_name,
cfg.make_category_t.cat_postfix,
});
end
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
Return translit <i lang=xx-Latn>...</i> where xx is the language code; else return empty string.
The value |script= is not used in {{transliteration}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transliteration}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
To avoid confusion, in this module and the templates that use it, the transliteration script parameter is renamed
to be |translit-script= (in this function, tscript).
This function is used by both lang_xx() and xlit()
lang_xx() always provides code, language_name, and translit; may provide tscript; never provides style
xlit() always provides language_name, translit, and one of code or tscript, never both; always provides style
For {{transliteration}}, style only applies when a language code is provided.
]]
local function make_translit (code, language_name, translit, std, tscript, style, engvar)
local title_t = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local title_text = ''; -- tool tip text for title= attribute
std = std and std:lower(); -- lower case for table indexing
if not is_set (std) and not is_set (tscript) then -- when neither standard nor script specified
title_text = language_name; -- write a generic tool tip
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', {title_text, cfg.misc_text_t.language}); -- skip this text (individual and macro languages only)
end
title_text = substitute ('$1 $2', {title_text, mw.ustring.lower (cfg.engvar_t[engvar]['romanisz_lc'])}); -- finish the tool tip; use romanization when neither script nor standard supplied
elseif is_set (std) and is_set (tscript) then -- when both are specified
if title_t[std] then -- and if standard is legitimate
if title_t[std][tscript] then -- and if script for that standard is legitimate
if script_table[tscript] then
title_text = substitute ('$1$2 ($3 $4) $5', { -- add the appropriate text to the tool tip
title_text,
title_t[std][tscript:lower()],
script_table[tscript],
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
return ''; -- invalid standard, setup for error message
end
elseif is_set (std) then -- translit-script not set, use language code
if not title_t[std] then return ''; end -- invalid standard, setup for error message
if title_t[std][code] then -- if language code is in the table (xlit may not provide a language code)
local fmt_str = '$1$2 ($3 $4) $5'; -- generic format string for tool tip
if language_name:match ('languages') then
fmt_str = '$1$2 ($3) $5'; -- format string for collective languages tool tip
end
title_text = substitute (fmt_str, { -- add the appropriate text to the tool tip
title_text,
title_t[std][code:lower()],
language_name,
cfg.misc_text_t.language,
cfg.make_translit_t.transliteration,
});
else -- code doesn't match
title_text = title_text .. title_t[std]['default']; -- so use the standard's default
end
else -- here if translit-script set but translit-std not set
if title_t['no_std'][tscript] then
title_text = title_text .. title_t['no_std'][tscript]; -- use translit-script if set
elseif title_t['no_std'][code] then
title_text = title_text .. title_t['no_std'][code]; -- use language code
else
if is_set (tscript) then
title_text = substitute ('$1$2-$3 $4', { -- write a script tool tip
title_text,
language_name,
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
elseif is_set (code) then
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end
local tag
if is_set (code) then -- when a language code is provided (always with {{lang-??}} templates, not always with {{transliteration}})
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span style="font-style: %s" lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ({{transliteration}} only)
end
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end
--[[--------------------------< V A L I D A T E _ T E X T >----------------------------------------------------
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an
error message. The tests are for empty or missing text and for improper or disallowed use of apostrophe markup.
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert.
]]
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end
local style = args.italic;
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end
--[[--------------------------< R E N D E R _ M A I N T >------------------------------------------------------
Render mainenance messages and categories.
]]
local function render_maint (nocat)
local maint = {};
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span class="lang-comment" style="font-style: normal; display: none; color: #33aa33; margin-left: 0.3em;">'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({'[[Category:', cat, ']]'})); -- format and add the categories
end
end
return table.concat (maint);
end
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.
]]
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------
Looks for a poem strip marker in text; returns true when found; false else.
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.
]]
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------
Inspects content of and selectively trims text. Returns text and the name of an appropriate HTML tag for text.
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.
]]
local function html_tag_select (text)
local tag;
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end
return text, tag;
end
--[[--------------------------< V A L I D A T E _ P R O T O >--------------------------------------------------
Validates value assigned to |proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.
]]
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end
--[[--------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------
Common function to return language name from the data set according to IETF tag.
Returns language name if found in data tables; nil else.
]]
local function language_name_get (ietf, code, cat)
ietf = ietf:lower(); -- ietf:lower() because format_ietf_tag() returns mixed case
local name; -- remains nil if not found
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to IANA active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the IANA deprecated tag/name table
name = lang_dep_table[code];
end
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end
return name; -- name from data tables or nil
end
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.
Returns an error message when mismatch detected; nil else.
]]
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower(); -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end
--[[--------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------
conducts a binary search of <ranges_t> for a sub-range that holds <target>.
returns boolean true if a sub-range holding <target> is found; boolean false else.
]]
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end
if flag then
break; -- here when we just evaluated the last range and <target> not found
end
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end
--[[--------------------------< I S _ L A T I N >--------------------------------------------------------------
compare <text> as codepoints to lists of known codepoints accepted as Latn script
returns boolean true and modified <text> when <text> is wrapped in accept-as-written markup
returns boolean true and <text> when codepoint is known
returns boolean false, <text>, non-Latn codepoint position in <text> (left to right), and the codepoint character
when codepoint is not known
TODO: when text has accept-as-written markup, return a non-boolean value to indicate that <text> is not wholly
latn script? Use that return value to create non-Latn HTML lang= attribute because <text> isn't really
latn so lang=und (undetermined)? or instead, omit the -Latn subtag? (without -Latn need to force |italic=yes)
]]
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end
--[[--------------------------< _ L A N G >--------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or cfg.templates_t.lang;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
validate_cat_args (args); -- determine if categorization should be suppressed
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code ({{{1}}} in {{lang}})
if msg then
return make_error_msg (msg, args, template);
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
if is_set (subtags.script) then -- if script set, override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if cfg.keywords_t.invert == args.italic and 'span' == tag then -- invert only supported for in-line content
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name));
table.insert (out, make_category (code, language_name, args.nocat));
table.insert (out, render_maint (args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function lang (frame)
local args_t = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text
valueFunc = function (key, value)
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space
return value; -- return untrimmed 'text'
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
args_t.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang|...}}
local msg = parameter_validate (args_t, cfg.templates_t.lang); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.lang); -- when template has unsupported params, abandon with error message
end
return _lang (args_t);
end
--[[--------------------------< T R A N S L A T I O N _ M A K E >----------------------------------------------
Stand-alone function to create literal translation of main text.
Also used by {{lang-x2}}.
]]
local function translation_make (args_t)
local translation_t = {', '}; -- initialize output
if 'none' ~= args_t.label then -- if we want a label
table.insert (translation_t, '<small>'); -- open the <small> HTML tag
if cfg.keywords_t.negative == args_t.link then
table.insert (translation_t, substitute ('<abbr title="$1">$2</abbr>', {cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr})); -- unlinked form
else
table.insert (translation_t, make_wikilink (cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr)); -- linked form
end
table.insert (translation_t, " </small>"); -- close the <small> HTML tag
end
table.insert (translation_t, table.concat ({ -- user styling spans match spand from {{gloss}}
'<span class="gloss-quot">\'</span>', -- user styling span for quote marks; use HTML entities to avoid wiki markup confusion
'<span class="gloss-text">', -- open user styling span for the translation
args_t.translation, -- the translation
'</span>', -- close user styling span for the translation
'<span class="gloss-quot">\'</span>' -- user styling span for quote marks
}));
return table.concat (translation_t); -- make a big string and done
end
--[[--------------------------< _ L A N G _ X X >--------------------------------------------------------------
For the {{lang-??}} templates, the only parameter required to be set in the template is the language code. All
other parameters can, usually should, be written in the template call. For {{lang-??}} templates for languages
that can have multiple writing systems, it may be appropriate to set |script= as well.
For each {{lang-??}} template choose the appropriate entry-point function so that this function knows the default
styling that should be applied to text.
For normal, upright style:
<includeonly>{{#invoke:lang|lang_xx_inherit|code=xx}}</includeonly>
For italic style:
<includeonly>{{#invoke:lang|lang_xx_italic|code=xx}}</includeonly>
All other parameters should be received from the template's frame (parent frame)
Supported parameters are:
|code = (required) the IANA language code
|script = IANA script code; especially for use with languages that use multiple writing systems
|region = IANA region code
|variant = IANA variant code
|text = (required) the displayed text in language specified by code
|link = boolean false ('no') does not link code-spcified language name to associated language article
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected
|cat = boolian false ('no') opposite form of |nocat=
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state
|lit = text that is a literal translation of text
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.')
any other text replaces language-name label - automatic wikilinking disabled
for those {{lang-??}} templates that support transliteration (those templates where |text= is not entirely latn script):
|translit = text that is a transliteration of text
|translit-std = the standard that applies to the transliteration
|translit-script = ISO 15924 script name; falls back to code
For {{lang-??}}, the positional parameters are:
{{{1}}} text
{{{2}}} transliterated text
{{{3}}} literal translation text
no other positional parameters are allowed
]]
local function _lang_xx (args, base_template) -- base_template will be either of 'langx' or 'lang-xx'
local out = {};
local language_name; -- used to make display text, article links
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, and variant
local code; -- the language code
local translit_script_name; -- name associated with IANA (ISO 15924) script code
local translit;
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or base_template;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
local text_idx = (cfg.templates_t.langx == base_template) and 2 or 1; -- for {{langx}} 'text' positional parameter is '2'
local translit_idx = (cfg.templates_t.langx == base_template) and 3 or 2;
local xlate_idx = (cfg.templates_t.langx == base_template) and 4 or 3;
if args[text_idx] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {text_idx, cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[text_idx] or args.text; -- prefer positional 'text' parameter
end
msg = validate_text (template, args); -- ensure that |text= is set, does not contain italic markup and is protected from improper bolding
if is_set (msg) then
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
if args[translit_idx] and args.translit then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {translit_idx, cfg.lang_t.conflict_n_param_types.translit}), args, template);
else
args.translit = args[translit_idx] or args.translit -- prefer positional 'translit' parameter
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if args[xlate_idx] and (args.translation or args.lit) then
return make_error_msg (substitute (cfg.lang_xx_t.conflict_n_lit, {xlate_idx}), args, template);
elseif args.translation and args.lit then
return make_error_msg (cfg.lang_xx_t.conflict_lit, args, template);
else
args.translation = args[xlate_idx] or args.translation or args.lit; -- prefer positional 'translation' parameter
end
if args.links and args.link then
return make_error_msg (cfg.lang_xx_t.conflict_link, args, template);
else
args.link = args.link or args.links; -- prefer args.link
end
validate_cat_args (args); -- determine if categorization should be suppressed
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code, args.script, args.region, args.variant); -- private omitted because private
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
if args.translit then
local latn, pos, char;
latn, args.translit, pos, char = is_latin (args.translit, (('' ~= subtags.private) and (code .. '-x-' .. subtags.private)) or code);
if not latn then
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template);
end
end
local is_latn_text, text, pos, char = is_latin (args.text, code); -- make a boolean
args.text = text; -- may have been modified (accept-as-written markup removed)
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if cfg.templates_t.langx == base_template then -- auto-italics for {{langx}} templates; adapted from {{lang}} (no support for poem tag)
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and is_latn_text) then -- text is not this wiki's language, no script specified and is wholly latn script (auto-italics)
args.italic = 'italic'; -- set font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
else -- {{lang-xx}} does not do auto italics; retained for those wikis that don't support {{langx}}
if nil == args.italic then -- args.italic controls
if is_set (subtags.script) then
if 'latn' == subtags.script then
args.italic = 'italic'; -- |script=Latn; set for font-style:italic
else
args.italic = initial_style_state; -- italic not set; script is not latn; set for font-style:<initial_style_state>
end
else
args.italic = initial_style_state; -- here when |italic= and |script= not set; set for font-style:<initial_style_state>
end
end
end
if is_set (subtags.script) then -- if script set override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {args.proto}), args, template);
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = language_name; -- category names retain IANA parenthetical diambiguators (if any)
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
if args.label then
if 'none' ~= args.label then
table.insert (out, table.concat ({args.label, ': '})); -- custom label
end
else
if cfg.keywords_t.negative == args.link then
table.insert (out, language_name); -- language name without wikilink
else
if mw.ustring.find (language_name, 'languages', 1, true) then
table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink
elseif lang_data.article_name[args.code:lower()] then -- is IETF tag in article name over ride?
table.insert (out, make_wikilink (lang_data.article_name[args.code:lower()], language_name)); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article override
table.insert (out, make_wikilink (lang_data.article_name[code], language_name)); -- language name with wikilink from override data
else
table.insert (out, make_wikilink (substitute ('$1 $2', {language_name, cfg.misc_text_t.language}), language_name)); -- language name with wikilink
end
end
table.insert (out, ': '); -- separator
end
if cfg.keywords_t.invert == args.italic then
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, ('none' == args.label) and language_name or nil))
if is_set (args.translit) and not is_latn_text then -- transliteration; not supported when args.text is wholly latn text (this is an imperfect test)
table.insert (out, ', '); -- comma to separate text from translit
if 'none' ~= args.label then
table.insert (out, '<small>');
if script_table[args['translit-script']] then -- when |translit-script= is set, try to use the script's name
translit_script_name = script_table[args['translit-script']];
else
translit_script_name = language_name; -- fall back on language name
end
local translit_title_obj = mw.title.makeTitle (0, substitute ('$1 $2',{cfg.lang_xx_t.romanization, translit_script_name})); -- make a title object; no engvar, article titles use US spelling
if translit_title_obj.exists and (cfg.keywords_t.negative ~= args.link) then
table.insert (out, make_wikilink (substitute ('$1 $2', {cfg.lang_xx_t.romanization, translit_script_name or language_name}),
substitute ('$1', {cfg.engvar_t[args.engvar]['romanisz_pt']})) .. ':'); -- make a wikilink if there is an article to link to; engvar the display text
else
table.insert (out, substitute ('$1:', {cfg.engvar_t[args.engvar]['romanisz_pt']})); -- else plain text per engvar
end
table.insert (out, ' </small>'); -- close the small tag
end
translit = make_translit (args.code, language_name, args.translit, args['translit-std'], args['translit-script'], nil, args.engvar)
if is_set (translit) then
table.insert (out, translit);
else
return make_error_msg (substitute ('$1: $2', {cfg.lang_xx_t.invalid_xlit_std, args['translit-std'] or '[missing]'}), args, template);
end
elseif is_set (args.translit) and is_latn_text then -- when creating a transliteration of Latn script <text>
return make_error_msg (cfg.lang_xx_t.xlit_of_latn, args, template); -- emit error message and abandon
end
if is_set (args.translation) then -- translation (not supported in {{lang}})
table.insert (out, translation_make (args));
end
table.insert (out, make_category (code, category_name, args.nocat));
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X _ A R G S _ G E T >----------------------------------------------
Common function to get args table from {{lang-??}} templates.
Returns table of args.
Text positional parameters are not trimmed here but are selectively trimmed at html_tag_select().
]]
local function lang_xx_args_get (frame, base_template)
local args_t = getArgs(frame,
{
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}}
valueFunc = function (key, value)
if ((cfg.templates_t.langx == base_template) and 2 or 1) == key then -- the 'text' positional parameter; 1 for {{lang-??}}, 2 for {{langx}}; do not trim wite space
return value; -- return untrimmed 'text' positional parameter
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
return args_t;
end
--[[--------------------------< L A N G _ X X _ I T A L I C >--------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_italic(). Sets the initial style state to italic.
]]
local function lang_xx_italic (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_italic|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I T A L I C >------------------------------------------------
Entry point from another module. Sets the initial style state to italic.
]]
local function _lang_xx_italic (args)
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< L A N G _ X X _ I N H E R I T >------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_inherit(). Sets the initial style state to inherit.
]]
local function lang_xx_inherit (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_inherit|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I N H E R I T >----------------------------------------------
Entry point from another module. Sets the initial style state to inherit.
]]
local function _lang_xx_inherit (args)
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< _ L A N G X >------------------------------------------------------------------
Entry point from another module.
]]
local function _langx (args_t)
local langx_data = mw.loadData ('Module:Lang/langx'); -- get necessary data
local rtl_t = langx_data.rtl_t; -- get list of language tags for languages that are rendered right-to-left
local link_t = langx_data.link_t; -- get list of language tags for {{lang-??}} templates that set |link=<something>
local size_t = langx_data.size_t; -- get list of language tags for {{lang-??}} templates that set |size=<something>
local msg = parameter_validate (args_t, cfg.templates_t.langx);
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.langx);
end
args_t.code = args_t[1] or args_t.code; -- get the language tag; must be {{{1}}} or |code=
if not args_t.code then
return make_error_msg (cfg.get_ietf_parts_t.missing_lang_tag, args_t, cfg.templates_t.langx);
end
args_t.rtl = args_t.rtl or (rtl_t[args_t.code] and cfg.keywords_t.affirmative); -- prefer |rtl= in template call, use rtl_t else
args_t.link = args_t.link or link_t[args_t.code]; -- prefer |link= in template call, use link_t felse
args_t.size = args_t.size or size_t[args_t.code]; -- prefer |size= in template call, use size_t else
args_t[1] = nil; -- unset to mimic {{lang-??}} templates which set |code=xx
local lang_subtag = args_t.code; -- use only the base language subtag for unsupported tag test; some args_t.code are modified by |script= etc
return _lang_xx (args_t, cfg.templates_t.langx);
end
--[[--------------------------< L A N G X >--------------------------------------------------------------------
Entry point for {{langx}}.
this function calls _lang_xx() to render non-English text. The {{lang-??}} templates have three positional paramters
but {{langx}} has four:
| 1 | 2 | 3 | 4
{{lang-xx |<text> |<xlit> |<xlat> }}
{{langx |<tag> |<text> |<xlit> |<xlat> }}
The calls to lang_xx_args_get() and _lang_xx() use 'langx' as a flag for those functions to select the proper
positional parameters.
{{lang-??}} depends on the calling template to select 'inherit' or 'italic' to establish the default rendering.
{{langx}} can't do that. The initial version of {{langx}} relied on a list of language tags (inherit_t in ~/langx)
scraped from those {{lang-??}} templates that call lang_xx_inherit() to render text in upright font. langx() now
uses auto-italics code adapted from {{lang}} (doesn't support poem tags).
]]
local function langx (frame)
local args_t = lang_xx_args_get (frame, cfg.templates_t.langx); -- get the arguments; 'langx' is the <base_template> used to decide which positional param is 'text', 'translit', 'lit'
return _langx (args_t);
end
--[[--------------------------< _ I S _ I E T F _ T A G >------------------------------------------------------
Returns true when a language name associated with IETF language tag exists; nil else. IETF language tag must be valid.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _is_ietf_tag (tag) -- entry point when this module is require()d into another
local c, s, r, v, p, err; -- code, script, region, variant, private, error message
c, s, r, v, p, err = get_ietf_parts (tag); -- disassemble tag into constituent part and validate
return ((c and not err) and true) or nil; -- return true when code portion has a value without error message; nil else
end
--[[--------------------------< I S _ I E T F _ T A G >--------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_ietf_tag (frame)
return _is_ietf_tag (getArgs (frame)[1]); -- args[1] is the IETF language tag to be tested; also get parent frame
end
--[[--------------------------< I S _ I E T F _ T A G _ F R A M E >--------------------------------------------
Module entry point from an {{#invoke:}}; same as is_ietf_tag() except does not get parameters from the parent
(template) frame. This function not useful when called by {{lang|fn=is_ietf_tag_frame|<tag>}} because <tag>
is in the parent frame.
]]
local function is_ietf_tag_frame (frame)
return _is_ietf_tag (getArgs (frame, {frameOnly = true,})[1]); -- args[1] is the IETF language tag to be tested; do not get parent frame
end
--[[--------------------------< _ N A M E _ F R O M _ T A G >--------------------------------------------------
Returns language name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Set invoke's |link= parameter to yes to get wikilinked version of the language name.
Module entry point from another module.
]]
local function _name_from_tag (args)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args['link']; -- make a boolean
local label = args.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local language_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args['template'] and table.concat ({'{{', args['template'], '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
language_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if 'yes' ~= args.raw then
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
end
if link then -- when |link=yes, wikilink the language name
if mw.ustring.find (language_name, 'languages', 1, true) then
language_name = make_wikilink (language_name, label); -- collective language name uses simple wikilink
elseif lang_data.article_name[raw_code:lower()] then -- is IETF tag in article name override?
language_name = make_wikilink (lang_data.article_name[raw_code:lower()], label or language_name); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article name override?
language_name = make_wikilink (lang_data.article_name[code], label or language_name); -- language name with wikilink from override data
else
language_name = make_wikilink (substitute ('$1 $2', {language_name, cfg.misc_text_t.language}), label or language_name); -- language name with wikilink
end
end
return language_name;
end
--[[--------------------------< N A M E _ F R O M _ T A G >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function name_from_tag (frame) -- entry point from an {{#invoke:lang|name_from_tag|<IETF tag>|link=<yes>|template=<template name>}}
return _name_from_tag (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< _ T A G _ F R O M _ N A M E >--------------------------------------------------
Returns the IETF language tag associated with the language name. Spelling of language name must be correct
according to the spelling in the source tables. When a standard language name has a parenthetical disambiguator,
that disambiguator must be omitted (they are not present in the data name-to-tag tables).
Module entry point from another module.
]]
local function _tag_from_name (args) -- entry point from another module
local msg;
if args[1] and '' ~= args[1] then
local data = mw.loadData ('Module:Lang/tag from name'); -- get the reversed data tables TODO: change when going live
local lang = args[1]:lower(); -- allow any-case for the language name (speeling must till be correct)
local tag = data.rev_override_table[lang] or data.rev_lang_table[lang] or data.rev_lang_dep_table[lang]; -- get the code; look first in the override then in the standard
if tag then
return tag, true; -- language name found so return tag and done; second return used by is_lang_name()
else
msg = substitute (cfg.tag_from_name_t.lang_not_found, {args[1]}); -- language name not found, error message
end
else
msg = cfg.tag_from_name_t.missing_lang_name; -- language name not found, error message
end
local template = '';
if args.template and '' ~= args.template then
template = table.concat ({'{{', args['template'], '}}: '}); -- make template name (if provided by the template)
end
return make_error_span (template, msg);
end
--[[--------------------------< T A G _ F R O M _ N A M E >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function tag_from_name (frame) -- entry point from an {{#invoke:lang|tag_from_name|<language name>|link=<yes>|template=<template name>}}
local result, _ = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by is_lang_name()
return result;
end
--[[--------------------------< I S _ L A N G _ N A M E >------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_lang_name (frame)
local _, result = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by tag_from_name()
return result and true or nil;
end
--[[--------------------------< _ X L I T >--------------------------------------------------------------------
Module entry point from another module.
]]
local function _xlit (args)
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local language_name; -- language name that matches language code; used for tool tip
local translit; -- transliterated text to display
local script; -- IANA script
local msg; -- for when called functions return an error message
local template = args.template or cfg.templates_t.transliteration;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
if is_set (args[3]) then -- [3] set when {{transliteration|code|standard|text}}
args.text = args[3]; -- get the transliterated text
args.translit_std = args[2] and args[2]:lower(); -- get the standard; lower case for table indexing
if not title_table[args.translit_std] then
return make_error_msg (substitute (cfg.transl_t.unrecog_xlit_std, {args.translit_std}), args, template);
end
else
if is_set (args[2]) then -- [2] set when {{transliteration|code|text}}
args.text = args[2]; -- get the transliterated text
else
if args[1] and (args[1]:match ('^%a%a%a?%a?$') or -- args[2] missing; is args[1] a language or script tag or is it the transliterated text?
args[1]:match ('^%a%a%a?%-x%-')) then -- or is args[1] a private-use tag
return make_error_msg (cfg.transl_t.no_text, args, template); -- args[1] is a code so we're missing text
else
args.text = args[1]; -- args[1] is not a code so we're missing that; assign args.text for error message
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template);
end
end
end
if is_set (args[1]) then -- IANA language code used for HTML lang= attribute; or ISO 15924 script code
if args[1]:match ('^%a%a%a?%a?$') or args[1]:match ('^%a%a%a?%-x%-') then -- args[1] has correct form?
args.code = args[1]:lower(); -- use the language/script code; only (2, 3, or 4 alpha characters) or private-use; lower case because table indexes are lower case
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args[1]}), args, template); -- invalid language / script code
end
else
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template); -- missing language / script code so quit
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, args.code); -- is latn text? strip accept-as-written markup
if not is_latn_text then -- when text is not latn
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template); -- abandon with error message
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if 'italic' == args.italic then -- 'italic' when |italic=yes; because that is same as absent or not set and |italic=default
args.italic = nil; -- set to nil;
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if override_table[args.code] then -- is code a language code defined in the override table?
language_name = override_table[args.code];
args.code = args.code:match ('^%a%a%a?'); -- if private use, strip all but language subtag
elseif lang_table[args.code] then -- is code a language code defined in the standard language code tables?
language_name = lang_table[args.code];
elseif lang_dep_table[args.code] then -- is code a language code defined in the deprecated language code tables?
language_name = lang_dep_table[args.code];
elseif script_table[args.code] then -- if here, code is not a language code; is it a script code?
language_name = script_table[args.code];
script = args.code; -- code was an ISO 15924 script so use that instead
args.code = ''; -- unset because not a language code
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args.code}), args, template); -- invalid language / script code
end
-- here only when all parameters passed to make_translit() are valid
return make_translit (args.code, language_name, args.text, args.translit_std, script, args.italic, args.engvar);
end
--[[--------------------------< X L I T >----------------------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function xlit (frame)
return _xlit (getArgs(frame));
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Returns category name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _category_from_tag (args_t)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args_t[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args_t.link; -- make a boolean
local label = args_t.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local category_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args_t.template and table.concat ({'{{', args_t.template, '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
category_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = make_category (code, category_name, nil, true):gsub ('[%[%]]', '');
if link then
return table.concat ({'[[:', category_name, ']]'});
else
return category_name;
end
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function category_from_tag (frame) -- entry point from an {{#invoke:lang|category_from_tag|<IETF tag>|template=<template name>}}
return _category_from_tag (getArgs (frame)); -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
category_from_tag = category_from_tag, -- frame entry points when this module is #invoke:ed into templates/wikitext
lang = lang, -- entry point for {{lang}}
langx = langx, -- entry point for {{langx}}
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}}
lang_xx_italic = lang_xx_italic,
is_ietf_tag = is_ietf_tag,
is_ietf_tag_frame = is_ietf_tag_frame,
is_lang_name = is_lang_name,
tag_from_name = tag_from_name, -- returns IETF tag associated with language name
name_from_tag = name_from_tag, -- used for template documentation; possible use in ISO 639 name from code templates
xlit = xlit, -- entry point for {{transliteration}}
_category_from_tag = _category_from_tag, -- API entry points when this module is require()d into other modules
_lang = _lang,
_langx = _langx,
_lang_xx_inherit = _lang_xx_inherit,
_lang_xx_italic = _lang_xx_italic,
_is_ietf_tag = _is_ietf_tag,
get_ietf_parts = get_ietf_parts,
_tag_from_name = _tag_from_name,
_name_from_tag = _name_from_tag,
_xlit = _xlit,
_translation_make = translation_make,
};
4lchs3y6tbwcup48cwp3ayuhrxmusvw
392723
392719
2026-09-02T02:46:10Z
MacTire02
219
prowal
392723
Scribunto
text/plain
--[=[
Lua support for the {{lang}}, {{langx}}, {{lang-??}}, and {{transliteration}} templates and replacement of various supporting templates.
]=]
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local unicode = require ("Module:Unicode data"); -- for is_Latin() and is_rtl()
local yesno = require ('Module:Yesno');
local sandbox = (mw.getCurrentFrame():getTitle():match ('/sandbox') or ''); -- when called from a sandbox template or module load sandbox data and sandbox configuration
local lang_data = mw.loadData ('Module:Lang/data' .. sandbox); -- language name override and transliteration tool-tip tables
local lang_name_table = lang_data.lang_name_table; -- language codes, names, regions, scripts, suppressed scripts
local lang_table = lang_data.lang_name_table.lang;
local lang_dep_table = lang_data.lang_name_table.lang_dep;
local script_table = lang_data.lang_name_table.script;
local region_table = lang_data.lang_name_table.region;
local variant_table = lang_data.lang_name_table.variant;
local suppressed_table = lang_data.lang_name_table.suppressed;
local override_table = lang_data.override;
local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms'); -- ISO 639-2/639-2T code translation to 639-1 code
local cfg = mw.loadData ('Module:Lang/configuration' .. sandbox); -- for internationalization
local is_latn_data = mw.loadData ('Module:Lang/data/is latn data');
local sizeof_ranges_t = is_latn_data.sizeof_ranges_t;
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
local content_lang = mw.language.getContentLanguage();
local this_wiki_lang_tag = content_lang.code; -- get this wiki's language tag
local this_wiki_lang_dir = content_lang:getDir(); -- get this wiki's language direction
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic()
local maint_cats = {}; -- maintenance categories go here
local maint_msgs = {}; -- and their messages go here
--[[--------------------------< M A K E _ E R R O R _ S P A N >--------------------------------------------------
]]
local function make_error_span (template, msg)
return table.concat ({'<span style="color:var(--color-error,#d33)">', cfg.misc_text_t.error, ': ', template, msg, '</span>'})
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.
]]
local function substitute (message, data_t)
return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end
--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
Assembles an error message from template name, message text, help link, and error category.
]]
local function make_error_msg (msg, args_t, template)
local category;
local text; -- handle the oddity that is {{langx}}
if cfg.templates_t.langxx == template then
text = args_t.text or args_t[1]; -- for {{lang-xx}}
else
text = args_t.text or args_t[2]; -- for {{lang}}, {{langx}}, and {{transliteration}}
end
if cfg.templates_t.transliteration == template then
category = cfg.make_error_msg_t.xlit_err_cat;
else
category = cfg.make_error_msg_t.lang_err_cat;
end
local category_link = ((0 == namespace or 10 == namespace) and not args_t.nocat) and substitute ('[[Category:$1]]', {category}) or '';
return substitute ('[$1] <span style="color:var(--color-error,#d33)">$2: {{$3}}: $4 ([[:Category:$5|$6]])</span>$7', -- { prevents template name from being treated as a template call in certain situations
{
text or cfg.make_error_msg_t.undefined,
cfg.misc_text_t.error,
template,
msg,
category,
cfg.misc_text_t.help,
category_link
})
end
--[[--------------------------< P A R A M E T E R _ V A L I D A T E >------------------------------------------
]]
local function parameter_validate (args_t, template)
local err_msg = cfg.parameter_validate_t.invalid_param;
if cfg.templates_t.lang == template then -- for {{lang}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_t[param] and -- unique {{lang}} parameters
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langx == template then -- for {{langx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_langx_t[param] and -- unique {{langx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langxx == template then -- for {{lang-xx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_xx_t[param] and -- unique {{lang-xx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
end
end
--[[--------------------------< 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 V E R T _ I T A L I C S >-------------------------------------------------
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing
apostrophes are converted to their HTML numeric entity equivalent so that the new italic markup doesn't become
bold markup inadvertently.
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal,
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements.
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns.
This function expects that markup in args.text is complete and correct; if it is not, oddness may result.
]]
local function invert_italics (source)
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns
[""]="\'\'", -- empty string becomes italic markup
["\'\'"]="", -- italic markup becomes empty string
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold
};
local seg = {};
source = source:gsub ("%f[\']\'%f[^\']", '''); -- protect single quote marks from being interpreted as bold markup
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text'
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup
elseif '' ~= seg[1] then
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup
elseif '' ~= seg[3] then
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup
else
seg[2] = source -- when there is no markup
end
seg[1] = invert_pattern_table[seg[1]] or seg[1]; -- replace leading markup according to pattern table
seg[3] = invert_pattern_table[seg[3]] or seg[3]; -- replace leading markup according to pattern table
return table.concat (seg); -- put it all back together and done
end
--[[--------------------------< V A L I D A T E _ I T A L I C >------------------------------------------------
Validates |italic= or |italics= assigned values.
When |italic= is set and has an acceptable assigned value, return the matching CSS font-style property value or,
for the special case 'default', return nil.
When |italic= is not set, or has an unacceptable assigned value, return nil and a nil error message.
When both |italic= and |italics= are set, returns nil and a 'conflicting' error message.
The return value nil causes the calling lang, lang_xx, or xlit function to set args.italic according to the template's
defined default ('inherit' for {{lang}}, 'inherit' or 'italic' for {{lang-??}} depending on
the individual template's requirements, 'italic' for {{transliteration}}) or to the value appropriate to |script=, if set ({{lang}}
and {{lang-??}} only).
Accepted values and the values that this function returns are are:
nil - when |italic= absent or not set; returns nil
default - for completeness, should rarely if ever be used; returns nil
yes - force args.text to be rendered in italic font; returns 'italic'
no - force args.text to be rendered in normal font; returns 'normal'
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit'
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert'
]]
local function validate_italic (args)
local properties = {[cfg.keywords_t.affirmative] = 'italic', [cfg.keywords_t.negative] = 'normal', [cfg.keywords_t.unset] = 'inherit', [cfg.keywords_t.invert] = 'invert', [cfg.keywords_t.default] = nil};
local count = 0
for _, arg in pairs {'italic', 'italics', 'i'} do
if args[arg] then
count = count + 1
end
end
if count > 1 then -- return nil and an error message if more than one is set
return nil, cfg.validate_italic_t.multi_italic;
end
return properties[args.italic or args.italics or args.i], nil; -- return an appropriate value and a nil error message
end
--[=[--------------------------< V A L I D A T E _ C A T _ A R G S >----------------------------------------------------------
Default behavior of the {{lang}} and {{lang-??}} templates is to add categorization when the templates are used in main space.
This default functionality may be suppressed by setting |nocat=yes or |cat=no. This function selects one of these two parameters
to control categorization.
Because having two parameters with 'opposite' names and 'opposite' values is confusing, this function accepts only affirmative
values for |nocat= and only negative values for |cat=; in both cases the 'other' sense (and non-sense) is not accepted and the
parameter is treated as if it were not set in the template.
Sets args.nocat to true if categorization is to be turned off; to nil if the default behavior should apply.
Accepted values for |nocat= are the text strings:
'yes', 'y', 'true', 't', on, '1' -- [[Module:Yesno]] returns logical true for all of these; false or nil else
for |cat=
'no', 'n', 'false', 'f', 'off', '0' -- [[Module:Yesno]] returns logical false for all of these; true or nil else
]=]
local function validate_cat_args (args)
if not (args.nocat or args.cat) then -- both are nil, so categorize
return;
end
if false == yesno (args.cat) or true == yesno (args.nocat) then
args.nocat = true; -- set to true when args.nocat is affirmative; nil else (as if the parameter were not set in the template)
else -- args.nocat is the parameter actually used.
args.nocat = nil;
end
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
--[[--------------------------< F O R M A T _ I E T F _ T A G >------------------------------------------------
Prettify IETF tags to use recommended subtag formats:
code: lower case
script: sentence case
region: upper case
variant: lower case
private: lower case prefixed with -x-
]]
local function format_ietf_tag (code, script, region, variant, private)
local out = {};
if is_set (private) then
return table.concat ({code:lower(), 'x', private:lower()}, '-'); -- if private, all other tags ignored
end
table.insert (out, code:lower());
if is_set (script) then
script = script:lower():gsub ('^%a', string.upper);
table.insert (out, script);
end
if is_set (region) then
table.insert (out, region:upper());
end
if is_set (variant) then
table.insert (out, variant:lower());
end
return table.concat (out, '-');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
Extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character IANA language code
script subtag - four character IANA script code
region subtag - two-letter or three digit IANA region code
variant subtag - four digit or 5-8 alnum variant code; only one variant subtag supported
private subtag - x- followed by 1-8 alnum private code; only supported with the primary language tag
in any one of these forms
lang lang-variant
lang-script lang-script-variant
lang-region lang-region-variant
lang-script-region lang-script-region-variant
lang-x-private
each of lang, script, region, variant, and private, when used, must be valid.
Languages with both two- and three-character code synonyms are promoted to the two-character synonym because
the IANA registry file omits the synonymous three-character code; we cannot depend on browsers understanding
the synonymous three-character codes in the lang= attribute.
For {{lang-??}} templates, the parameters |script=, |region=, and |variant= are supported (not supported in {{lang}}
because those parameters are superfluous to the IETF subtags in |code=).
Returns six values; all lower case. Valid parts are returned as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil; the sixth returned item is an error message (if an error detected) or nil.
See http://www.rfc-editor.org/rfc/bcp/bcp47.txt section 2.1.
]]
local function get_ietf_parts (source, args_script, args_region, args_variant)
local code, script, region, variant, private; -- IETF tag parts
if not is_set (source) then
return nil, nil, nil, nil, nil, cfg.get_ietf_parts_t.missing_lang_tag;
end
local pattern = { -- table of tables holding acceptable IETF tag patterns and short names of the IETF part captured by the pattern
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits)
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits)
{'^(%a%a%a?)$'}, -- 18 - ll
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters)
}
local t = {}; -- table of captures; serves as a translator between captured IETF tag parts and named variables
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i])
if c1 then -- c1 always set on match
code = c1; -- first capture is always code
t = {
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table
};
script = t.s or ''; -- translate table contents to named variables;
region = t.r or ''; -- absent table entries are nil so set named IETF parts to empty string for concatenation
variant= t.v or '';
private = t.p or '';
break; -- and done
end
end
if not code then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_tag, {source}); -- don't know what we got but it is malformed
end
code = code:lower(); -- ensure that we use and return lower case version of this
if not (override_table[code] or lang_table[code] or synonym_table[code] or lang_dep_table[code]) then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_code, {code}); -- invalid language code, don't know about the others (don't care?)
end
if synonym_table[code] then -- if 639-2/639-2T code has a 639-1 synonym
table.insert (maint_cats, substitute (cfg.get_ietf_parts_t.maint_promo_cat, {code}));
table.insert (maint_msgs, substitute (cfg.get_ietf_parts_t.maint_promo_msg, {code, synonym_table[code]}));
code = synonym_table[code]; -- use the synonym
end
if is_set (script) then
if is_set (args_script) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_scr; -- both code with script and |script= not allowed
end
else
script = args_script or ''; -- use args.script if provided
end
if is_set (script) then
script = script:lower(); -- ensure that we use and return lower case version of this
if not script_table[script] then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_scr_code, {script, code}); -- language code OK, invalid script, don't know about the others (don't care?)
end
end
if suppressed_table[script] then -- ensure that code-script does not use a suppressed script
if in_array (code, suppressed_table[script]) then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.script_code, {script, code}); -- language code OK, script is suppressed for this code
end
end
if is_set (region) then
if is_set (args_region) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_reg; -- both code with region and |region= not allowed
end
else
region = args_region or ''; -- use args.region if provided
end
if is_set (region) then
region = region:lower(); -- ensure that we use and return lower case version of this
if not region_table[region] then
return code, script, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_reg_code, {region, code});
end
end
if is_set (variant) then
if is_set (args_variant) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_var; -- both code with variant and |variant= not allowed
end
else
variant = args_variant or ''; -- use args.variant if provided
end
if is_set (variant) then
variant = variant:lower(); -- ensure that we use and return lower case version of this
if not variant_table[variant] then -- make sure variant is valid
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var, {variant});
end -- does this duplicate/replace tests in lang() and lang_xx()?
if is_set (script) then -- if script set it must be part of the 'prefix'
if not in_array (table.concat ({code, '-', script}), variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_scr, {variant, code, script});
end
elseif is_set (region) then -- if region set, there are some prefixes that require lang code and region (en-CA-newfound)
if not in_array (code, variant_table[variant]['prefixes']) then -- first see if lang code is all that's required (en-oxendict though en-GB-oxendict is preferred)
if not in_array (table.concat ({code, '-', region}), variant_table[variant]['prefixes']) then -- now try for lang code and region (en-CA-newfound)
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_reg, {variant, code, region});
end
end
else -- cheap way to determine if there are prefixes; fonipa and others don't have prefixes; # operator always returns 0
if variant_table[variant]['prefixes'][1] and not in_array (code, variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code, {variant, code});
end
end
end
if is_set (private) then
private = private:lower(); -- ensure that we use and return lower case version of this
if not override_table[table.concat ({code, '-x-', private})] then -- make sure private tag is valid; note that index
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_pri, {private});
end
end
return code, script, region, variant, private, nil; -- return the good bits; make sure that msg is nil
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, 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 is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< D I V _ M A R K U P _ A D D >--------------------------------------------------
Adds <i> and </i> tags to list-item text or to implied <p>..</p> text. Mixed not supported.
]]
local function div_markup_add (text, style)
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text
if 'italic' == style then
return text:gsub ('(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item
else
return text;
end
end
if text:find ('\n+') then -- look for any number of \n characters in text
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics MediaWiki
if 'italic' == style then
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each implied p (two or more consecutive '\n\n' sequences)
else
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each implied p
text = text:gsub ('\n', ''); -- strip newline characters
end
end
return text;
end
--[[--------------------------< T I T L E _ W R A P P E R _ M A K E >------------------------------------------
Makes a <span title="<title text>"><content_text></span> or <div title="<title text>"><content_text></div> where
<title text> is in the tool-tip in the wiki's local language and <content_text> is non-local-language text in
HTML markup. This because the lang= attribute applies to the content of its enclosing tag.
<tag> holds a string 'div' or 'span' used to choose the correct wrapping tag.
]]
local function title_wrapper_make (title_text, content_text, tag)
local wrapper_t = {};
table.insert (wrapper_t, table.concat ({'<', tag})); -- open opening wrapper tag
table.insert (wrapper_t, ' title=\"'); -- begin title attribute
table.insert (wrapper_t, title_text); -- add <title_text>
table.insert (wrapper_t, '\">'); -- end title attribute and close opening wrapper tag
table.insert (wrapper_t, content_text); -- add <content_text>
table.insert (wrapper_t, table.concat ({'</', tag, '>'})); -- add closing wrapper tag
return table.concat (wrapper_t); -- make a big string and done
end
--[[--------------------------< M A K E _ T E X T _ H T M L >--------------------------------------------------
Add the HTML markup to text according to the type of content that it is: <span> or <i> tags for inline content or
<div> tags for block content
The lang= attribute also applies to the content of the tag where it is placed so this is wrong because 'Spanish
language text' is English:
<i lang="es" title="Spanish language text">casa</i>
should be:
<span title="Spanish language text"><i lang="es">casa</i></span>
or for <div>...</div>:
<div title="Spanish language text"><div lang="es"><spanish-language-text></div></div>
]]
local function make_text_html (code, text, tag, rtl, style, size, language)
local html_t = {};
local style_added = '';
local wrapper_tag = tag; -- <tag> gets modified so save a copy for use when/if we create a wrapper span or div
if text:match ('^%*') then
table.insert (html_t, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plain splat confuses MediaWiki
text = text:gsub ('^%*', ''); -- remove the splat from the text
end
if 'span' == tag then -- default HTML tag for inline content
if 'italic' == style then -- but if italic
tag = 'i'; -- change to <i> tags
end
else -- must be div so go
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i>
end
table.insert (html_t, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> HTML tag
code = code:gsub ('%-x%-.*', ''); -- strip private use subtag from code tag because meaningless outside of Wikipedia
table.insert (html_t, table.concat ({' lang="', code, '\"'})); -- add language attribute
if (rtl or unicode.is_rtl(text)) and ('ltr' == this_wiki_lang_dir) then -- text is right-to-left on a left-to-right wiki
table.insert (html_t, ' dir="rtl"'); -- add direction attribute for right-to-left languages
elseif not (rtl or unicode.is_rtl(text)) and ('rtl' == this_wiki_lang_dir) then -- text is left-to-right on a right-to-left wiki
table.insert (html_t, ' dir="ltr"'); -- add direction attribute for left-to-right languages
end
if 'normal' == style then -- when |italic=no
table.insert (html_t, ' style=\"font-style: normal;'); -- override external markup, if any
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
if is_set (size) then -- when |size=<something>
if is_set (style_added) then
table.insert (html_t, table.concat ({' font-size: ', size, ';'})); -- add when style attribute already inserted
else
table.insert (html_t, table.concat ({' style=\"font-size: ', size, ';'})); -- create style attribute
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
end
table.insert (html_t, table.concat ({style_added, '>'})); -- close the opening HTML tag
table.insert (html_t, text); -- insert the text
table.insert (html_t, table.concat ({'</', tag, '>'})); -- close the 'text' <i>, <span>, or <div> HTML tag
if is_set (language) then -- create a <title_text> string for the title= attribute in a wrapper span or div
local title_text;
if 'zxx' == code then -- special case for this tag 'no linguistic content'
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.zxx}); -- not a language so don't use 'language' in title text
elseif mw.ustring.find (language, 'languages', 1, true) then
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.collective}); -- for collective languages
else
title_text = substitute ('$1-$2', {language, cfg.make_text_html_t.individual}); -- for individual languages
end
return title_wrapper_make (title_text, table.concat (html_t), wrapper_tag);
else
return table.concat (html_t);
end
end
--[=[-------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
For individual language, <language>, returns:
[[Category:Articles containing <language>-language text]]
For English:
[[Category:Articles containing explicitly cited English-language text]]
For ISO 639-2 collective languages (and for 639-1 bh):
[[Category:Articles with text in <language> languages]]
]=]
local function make_category (code, language_name, nocat, name_get)
if ((0 ~= namespace) or nocat) and not name_get then -- only categorize in article space
return ''; -- return empty string for concatenation
end
if mw.ustring.find (language_name, 'languages', 1, true) then
return substitute ('[[$1 $2]]', {cfg.make_category_t.collective_cat, language_name});
end
if this_wiki_lang_tag == code then
return substitute ('[[$1 $2 $3-$4]]', { -- unique category name for the local language
cfg.make_category_t.cat_prefix,
cfg.make_category_t.explicit_cat,
language_name,
cfg.make_category_t.cat_postfix,
});
else
return substitute ('[[$1 $2-$3]]', { -- category for individual languages
cfg.make_category_t.cat_prefix,
language_name,
cfg.make_category_t.cat_postfix,
});
end
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
Return translit <i lang=xx-Latn>...</i> where xx is the language code; else return empty string.
The value |script= is not used in {{transliteration}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transliteration}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
To avoid confusion, in this module and the templates that use it, the transliteration script parameter is renamed
to be |translit-script= (in this function, tscript).
This function is used by both lang_xx() and xlit()
lang_xx() always provides code, language_name, and translit; may provide tscript; never provides style
xlit() always provides language_name, translit, and one of code or tscript, never both; always provides style
For {{transliteration}}, style only applies when a language code is provided.
]]
local function make_translit (code, language_name, translit, std, tscript, style, engvar)
local title_t = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local title_text = ''; -- tool tip text for title= attribute
std = std and std:lower(); -- lower case for table indexing
if not is_set (std) and not is_set (tscript) then -- when neither standard nor script specified
title_text = language_name; -- write a generic tool tip
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', {title_text, cfg.misc_text_t.language}); -- skip this text (individual and macro languages only)
end
title_text = substitute ('$1 $2', {title_text, mw.ustring.lower (cfg.engvar_t[engvar]['romanisz_lc'])}); -- finish the tool tip; use romanization when neither script nor standard supplied
elseif is_set (std) and is_set (tscript) then -- when both are specified
if title_t[std] then -- and if standard is legitimate
if title_t[std][tscript] then -- and if script for that standard is legitimate
if script_table[tscript] then
title_text = substitute ('$1$2 ($3 $4) $5', { -- add the appropriate text to the tool tip
title_text,
title_t[std][tscript:lower()],
script_table[tscript],
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
return ''; -- invalid standard, setup for error message
end
elseif is_set (std) then -- translit-script not set, use language code
if not title_t[std] then return ''; end -- invalid standard, setup for error message
if title_t[std][code] then -- if language code is in the table (xlit may not provide a language code)
local fmt_str = '$1$2 ($3 $4) $5'; -- generic format string for tool tip
if language_name:match ('languages') then
fmt_str = '$1$2 ($3) $5'; -- format string for collective languages tool tip
end
title_text = substitute (fmt_str, { -- add the appropriate text to the tool tip
title_text,
title_t[std][code:lower()],
language_name,
cfg.misc_text_t.language,
cfg.make_translit_t.transliteration,
});
else -- code doesn't match
title_text = title_text .. title_t[std]['default']; -- so use the standard's default
end
else -- here if translit-script set but translit-std not set
if title_t['no_std'][tscript] then
title_text = title_text .. title_t['no_std'][tscript]; -- use translit-script if set
elseif title_t['no_std'][code] then
title_text = title_text .. title_t['no_std'][code]; -- use language code
else
if is_set (tscript) then
title_text = substitute ('$1$2-$3 $4', { -- write a script tool tip
title_text,
language_name,
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
elseif is_set (code) then
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end
local tag
if is_set (code) then -- when a language code is provided (always with {{lang-??}} templates, not always with {{transliteration}})
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span style="font-style: %s" lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ({{transliteration}} only)
end
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end
--[[--------------------------< V A L I D A T E _ T E X T >----------------------------------------------------
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an
error message. The tests are for empty or missing text and for improper or disallowed use of apostrophe markup.
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert.
]]
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end
local style = args.italic;
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end
--[[--------------------------< R E N D E R _ M A I N T >------------------------------------------------------
Render mainenance messages and categories.
]]
local function render_maint (nocat)
local maint = {};
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span class="lang-comment" style="font-style: normal; display: none; color: #33aa33; margin-left: 0.3em;">'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({'[[Category:', cat, ']]'})); -- format and add the categories
end
end
return table.concat (maint);
end
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.
]]
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------
Looks for a poem strip marker in text; returns true when found; false else.
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.
]]
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------
Inspects content of and selectively trims text. Returns text and the name of an appropriate HTML tag for text.
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.
]]
local function html_tag_select (text)
local tag;
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end
return text, tag;
end
--[[--------------------------< V A L I D A T E _ P R O T O >--------------------------------------------------
Validates value assigned to |proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.
]]
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end
--[[--------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------
Common function to return language name from the data set according to IETF tag.
Returns language name if found in data tables; nil else.
]]
local function language_name_get (ietf, code, cat)
ietf = ietf:lower(); -- ietf:lower() because format_ietf_tag() returns mixed case
local name; -- remains nil if not found
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to IANA active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the IANA deprecated tag/name table
name = lang_dep_table[code];
end
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end
return name; -- name from data tables or nil
end
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.
Returns an error message when mismatch detected; nil else.
]]
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower(); -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end
--[[--------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------
conducts a binary search of <ranges_t> for a sub-range that holds <target>.
returns boolean true if a sub-range holding <target> is found; boolean false else.
]]
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end
if flag then
break; -- here when we just evaluated the last range and <target> not found
end
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end
--[[--------------------------< I S _ L A T I N >--------------------------------------------------------------
compare <text> as codepoints to lists of known codepoints accepted as Latn script
returns boolean true and modified <text> when <text> is wrapped in accept-as-written markup
returns boolean true and <text> when codepoint is known
returns boolean false, <text>, non-Latn codepoint position in <text> (left to right), and the codepoint character
when codepoint is not known
TODO: when text has accept-as-written markup, return a non-boolean value to indicate that <text> is not wholly
latn script? Use that return value to create non-Latn HTML lang= attribute because <text> isn't really
latn so lang=und (undetermined)? or instead, omit the -Latn subtag? (without -Latn need to force |italic=yes)
]]
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end
--[[--------------------------< _ L A N G >--------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or cfg.templates_t.lang;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
validate_cat_args (args); -- determine if categorization should be suppressed
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code ({{{1}}} in {{lang}})
if msg then
return make_error_msg (msg, args, template);
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
if is_set (subtags.script) then -- if script set, override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if cfg.keywords_t.invert == args.italic and 'span' == tag then -- invert only supported for in-line content
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name));
table.insert (out, make_category (code, language_name, args.nocat));
table.insert (out, render_maint (args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function lang (frame)
local args_t = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text
valueFunc = function (key, value)
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space
return value; -- return untrimmed 'text'
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
args_t.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang|...}}
local msg = parameter_validate (args_t, cfg.templates_t.lang); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.lang); -- when template has unsupported params, abandon with error message
end
return _lang (args_t);
end
--[[--------------------------< T R A N S L A T I O N _ M A K E >----------------------------------------------
Stand-alone function to create literal translation of main text.
Also used by {{lang-x2}}.
]]
local function translation_make (args_t)
local translation_t = {', '}; -- initialize output
if 'none' ~= args_t.label then -- if we want a label
table.insert (translation_t, '<small>'); -- open the <small> HTML tag
if cfg.keywords_t.negative == args_t.link then
table.insert (translation_t, substitute ('<abbr title="$1">$2</abbr>', {cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr})); -- unlinked form
else
table.insert (translation_t, make_wikilink (cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr)); -- linked form
end
table.insert (translation_t, " </small>"); -- close the <small> HTML tag
end
table.insert (translation_t, table.concat ({ -- user styling spans match spand from {{gloss}}
'<span class="gloss-quot">\'</span>', -- user styling span for quote marks; use HTML entities to avoid wiki markup confusion
'<span class="gloss-text">', -- open user styling span for the translation
args_t.translation, -- the translation
'</span>', -- close user styling span for the translation
'<span class="gloss-quot">\'</span>' -- user styling span for quote marks
}));
return table.concat (translation_t); -- make a big string and done
end
--[[--------------------------< _ L A N G _ X X >--------------------------------------------------------------
For the {{lang-??}} templates, the only parameter required to be set in the template is the language code. All
other parameters can, usually should, be written in the template call. For {{lang-??}} templates for languages
that can have multiple writing systems, it may be appropriate to set |script= as well.
For each {{lang-??}} template choose the appropriate entry-point function so that this function knows the default
styling that should be applied to text.
For normal, upright style:
<includeonly>{{#invoke:lang|lang_xx_inherit|code=xx}}</includeonly>
For italic style:
<includeonly>{{#invoke:lang|lang_xx_italic|code=xx}}</includeonly>
All other parameters should be received from the template's frame (parent frame)
Supported parameters are:
|code = (required) the IANA language code
|script = IANA script code; especially for use with languages that use multiple writing systems
|region = IANA region code
|variant = IANA variant code
|text = (required) the displayed text in language specified by code
|link = boolean false ('no') does not link code-spcified language name to associated language article
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected
|cat = boolian false ('no') opposite form of |nocat=
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state
|lit = text that is a literal translation of text
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.')
any other text replaces language-name label - automatic wikilinking disabled
for those {{lang-??}} templates that support transliteration (those templates where |text= is not entirely latn script):
|translit = text that is a transliteration of text
|translit-std = the standard that applies to the transliteration
|translit-script = ISO 15924 script name; falls back to code
For {{lang-??}}, the positional parameters are:
{{{1}}} text
{{{2}}} transliterated text
{{{3}}} literal translation text
no other positional parameters are allowed
]]
local function _lang_xx (args, base_template) -- base_template will be either of 'langx' or 'lang-xx'
local out = {};
local language_name; -- used to make display text, article links
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, and variant
local code; -- the language code
local translit_script_name; -- name associated with IANA (ISO 15924) script code
local translit;
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or base_template;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
local text_idx = (cfg.templates_t.langx == base_template) and 2 or 1; -- for {{langx}} 'text' positional parameter is '2'
local translit_idx = (cfg.templates_t.langx == base_template) and 3 or 2;
local xlate_idx = (cfg.templates_t.langx == base_template) and 4 or 3;
if args[text_idx] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {text_idx, cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[text_idx] or args.text; -- prefer positional 'text' parameter
end
msg = validate_text (template, args); -- ensure that |text= is set, does not contain italic markup and is protected from improper bolding
if is_set (msg) then
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
if args[translit_idx] and args.translit then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {translit_idx, cfg.lang_t.conflict_n_param_types.translit}), args, template);
else
args.translit = args[translit_idx] or args.translit -- prefer positional 'translit' parameter
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if args[xlate_idx] and (args.translation or args.lit) then
return make_error_msg (substitute (cfg.lang_xx_t.conflict_n_lit, {xlate_idx}), args, template);
elseif args.translation and args.lit then
return make_error_msg (cfg.lang_xx_t.conflict_lit, args, template);
else
args.translation = args[xlate_idx] or args.translation or args.lit; -- prefer positional 'translation' parameter
end
if args.links and args.link then
return make_error_msg (cfg.lang_xx_t.conflict_link, args, template);
else
args.link = args.link or args.links; -- prefer args.link
end
validate_cat_args (args); -- determine if categorization should be suppressed
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code, args.script, args.region, args.variant); -- private omitted because private
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
if args.translit then
local latn, pos, char;
latn, args.translit, pos, char = is_latin (args.translit, (('' ~= subtags.private) and (code .. '-x-' .. subtags.private)) or code);
if not latn then
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template);
end
end
local is_latn_text, text, pos, char = is_latin (args.text, code); -- make a boolean
args.text = text; -- may have been modified (accept-as-written markup removed)
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if cfg.templates_t.langx == base_template then -- auto-italics for {{langx}} templates; adapted from {{lang}} (no support for poem tag)
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and is_latn_text) then -- text is not this wiki's language, no script specified and is wholly latn script (auto-italics)
args.italic = 'italic'; -- set font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
else -- {{lang-xx}} does not do auto italics; retained for those wikis that don't support {{langx}}
if nil == args.italic then -- args.italic controls
if is_set (subtags.script) then
if 'latn' == subtags.script then
args.italic = 'italic'; -- |script=Latn; set for font-style:italic
else
args.italic = initial_style_state; -- italic not set; script is not latn; set for font-style:<initial_style_state>
end
else
args.italic = initial_style_state; -- here when |italic= and |script= not set; set for font-style:<initial_style_state>
end
end
end
if is_set (subtags.script) then -- if script set override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {args.proto}), args, template);
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = language_name; -- category names retain IANA parenthetical diambiguators (if any)
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
if args.label then
if 'none' ~= args.label then
table.insert (out, table.concat ({args.label, ': '})); -- custom label
end
else
if cfg.keywords_t.negative == args.link then
table.insert (out, language_name); -- language name without wikilink
else
if mw.ustring.find (language_name, 'languages', 1, true) then
table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink
elseif lang_data.article_name[args.code:lower()] then -- is IETF tag in article name over ride?
table.insert (out, make_wikilink (lang_data.article_name[args.code:lower()], language_name)); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article override
table.insert (out, make_wikilink (lang_data.article_name[code], language_name)); -- language name with wikilink from override data
else
table.insert (out, make_wikilink (substitute ('$1 $2', {language_name, cfg.misc_text_t.language}), language_name)); -- language name with wikilink
end
end
table.insert (out, ': '); -- separator
end
if cfg.keywords_t.invert == args.italic then
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, ('none' == args.label) and language_name or nil))
if is_set (args.translit) and not is_latn_text then -- transliteration; not supported when args.text is wholly latn text (this is an imperfect test)
table.insert (out, ', '); -- comma to separate text from translit
if 'none' ~= args.label then
table.insert (out, '<small>');
if script_table[args['translit-script']] then -- when |translit-script= is set, try to use the script's name
translit_script_name = script_table[args['translit-script']];
else
translit_script_name = language_name; -- fall back on language name
end
local translit_title_obj = mw.title.makeTitle (0, substitute ('$1 $2',{cfg.lang_xx_t.romanization, translit_script_name})); -- make a title object; no engvar, article titles use US spelling
if translit_title_obj.exists and (cfg.keywords_t.negative ~= args.link) then
table.insert (out, make_wikilink (substitute ('$1 $2', {cfg.lang_xx_t.romanization, translit_script_name or language_name}),
substitute ('$1', {cfg.engvar_t[args.engvar]['romanisz_pt']})) .. ':'); -- make a wikilink if there is an article to link to; engvar the display text
else
table.insert (out, substitute ('$1:', {cfg.engvar_t[args.engvar]['romanisz_pt']})); -- else plain text per engvar
end
table.insert (out, ' </small>'); -- close the small tag
end
translit = make_translit (args.code, language_name, args.translit, args['translit-std'], args['translit-script'], nil, args.engvar)
if is_set (translit) then
table.insert (out, translit);
else
return make_error_msg (substitute ('$1: $2', {cfg.lang_xx_t.invalid_xlit_std, args['translit-std'] or '[missing]'}), args, template);
end
elseif is_set (args.translit) and is_latn_text then -- when creating a transliteration of Latn script <text>
return make_error_msg (cfg.lang_xx_t.xlit_of_latn, args, template); -- emit error message and abandon
end
if is_set (args.translation) then -- translation (not supported in {{lang}})
table.insert (out, translation_make (args));
end
table.insert (out, make_category (code, category_name, args.nocat));
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X _ A R G S _ G E T >----------------------------------------------
Common function to get args table from {{lang-??}} templates.
Returns table of args.
Text positional parameters are not trimmed here but are selectively trimmed at html_tag_select().
]]
local function lang_xx_args_get (frame, base_template)
local args_t = getArgs(frame,
{
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}}
valueFunc = function (key, value)
if ((cfg.templates_t.langx == base_template) and 2 or 1) == key then -- the 'text' positional parameter; 1 for {{lang-??}}, 2 for {{langx}}; do not trim wite space
return value; -- return untrimmed 'text' positional parameter
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
return args_t;
end
--[[--------------------------< L A N G _ X X _ I T A L I C >--------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_italic(). Sets the initial style state to italic.
]]
local function lang_xx_italic (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_italic|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I T A L I C >------------------------------------------------
Entry point from another module. Sets the initial style state to italic.
]]
local function _lang_xx_italic (args)
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< L A N G _ X X _ I N H E R I T >------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_inherit(). Sets the initial style state to inherit.
]]
local function lang_xx_inherit (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_inherit|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I N H E R I T >----------------------------------------------
Entry point from another module. Sets the initial style state to inherit.
]]
local function _lang_xx_inherit (args)
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< _ L A N G X >------------------------------------------------------------------
Entry point from another module.
]]
local function _langx (args_t)
local langx_data = mw.loadData ('Module:Lang/langx'); -- get necessary data
local rtl_t = langx_data.rtl_t; -- get list of language tags for languages that are rendered right-to-left
local link_t = langx_data.link_t; -- get list of language tags for {{lang-??}} templates that set |link=<something>
local size_t = langx_data.size_t; -- get list of language tags for {{lang-??}} templates that set |size=<something>
local msg = parameter_validate (args_t, cfg.templates_t.langx);
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.langx);
end
args_t.code = args_t[1] or args_t.code; -- get the language tag; must be {{{1}}} or |code=
if not args_t.code then
return make_error_msg (cfg.get_ietf_parts_t.missing_lang_tag, args_t, cfg.templates_t.langx);
end
args_t.rtl = args_t.rtl or (rtl_t[args_t.code] and cfg.keywords_t.affirmative); -- prefer |rtl= in template call, use rtl_t else
args_t.link = args_t.link or link_t[args_t.code]; -- prefer |link= in template call, use link_t felse
args_t.size = args_t.size or size_t[args_t.code]; -- prefer |size= in template call, use size_t else
args_t[1] = nil; -- unset to mimic {{lang-??}} templates which set |code=xx
local lang_subtag = args_t.code; -- use only the base language subtag for unsupported tag test; some args_t.code are modified by |script= etc
return _lang_xx (args_t, cfg.templates_t.langx);
end
--[[--------------------------< L A N G X >--------------------------------------------------------------------
Entry point for {{langx}}.
this function calls _lang_xx() to render non-English text. The {{lang-??}} templates have three positional paramters
but {{langx}} has four:
| 1 | 2 | 3 | 4
{{lang-xx |<text> |<xlit> |<xlat> }}
{{langx |<tag> |<text> |<xlit> |<xlat> }}
The calls to lang_xx_args_get() and _lang_xx() use 'langx' as a flag for those functions to select the proper
positional parameters.
{{lang-??}} depends on the calling template to select 'inherit' or 'italic' to establish the default rendering.
{{langx}} can't do that. The initial version of {{langx}} relied on a list of language tags (inherit_t in ~/langx)
scraped from those {{lang-??}} templates that call lang_xx_inherit() to render text in upright font. langx() now
uses auto-italics code adapted from {{lang}} (doesn't support poem tags).
]]
local function langx (frame)
local args_t = lang_xx_args_get (frame, cfg.templates_t.langx); -- get the arguments; 'langx' is the <base_template> used to decide which positional param is 'text', 'translit', 'lit'
return _langx (args_t);
end
--[[--------------------------< _ I S _ I E T F _ T A G >------------------------------------------------------
Returns true when a language name associated with IETF language tag exists; nil else. IETF language tag must be valid.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _is_ietf_tag (tag) -- entry point when this module is require()d into another
local c, s, r, v, p, err; -- code, script, region, variant, private, error message
c, s, r, v, p, err = get_ietf_parts (tag); -- disassemble tag into constituent part and validate
return ((c and not err) and true) or nil; -- return true when code portion has a value without error message; nil else
end
--[[--------------------------< I S _ I E T F _ T A G >--------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_ietf_tag (frame)
return _is_ietf_tag (getArgs (frame)[1]); -- args[1] is the IETF language tag to be tested; also get parent frame
end
--[[--------------------------< I S _ I E T F _ T A G _ F R A M E >--------------------------------------------
Module entry point from an {{#invoke:}}; same as is_ietf_tag() except does not get parameters from the parent
(template) frame. This function not useful when called by {{lang|fn=is_ietf_tag_frame|<tag>}} because <tag>
is in the parent frame.
]]
local function is_ietf_tag_frame (frame)
return _is_ietf_tag (getArgs (frame, {frameOnly = true,})[1]); -- args[1] is the IETF language tag to be tested; do not get parent frame
end
--[[--------------------------< _ N A M E _ F R O M _ T A G >--------------------------------------------------
Returns language name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Set invoke's |link= parameter to yes to get wikilinked version of the language name.
Module entry point from another module.
]]
local function _name_from_tag (args)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args['link']; -- make a boolean
local label = args.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local language_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args['template'] and table.concat ({'{{', args['template'], '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
language_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if 'yes' ~= args.raw then
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
end
if link then -- when |link=yes, wikilink the language name
if mw.ustring.find (language_name, 'languages', 1, true) then
language_name = make_wikilink (language_name, label); -- collective language name uses simple wikilink
elseif lang_data.article_name[raw_code:lower()] then -- is IETF tag in article name override?
language_name = make_wikilink (lang_data.article_name[raw_code:lower()], label or language_name); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article name override?
language_name = make_wikilink (lang_data.article_name[code], label or language_name); -- language name with wikilink from override data
else
language_name = make_wikilink (language_name, label or language_name); -- Manx language name with wikilink
end
end
return language_name;
end
--[[--------------------------< N A M E _ F R O M _ T A G >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function name_from_tag (frame) -- entry point from an {{#invoke:lang|name_from_tag|<IETF tag>|link=<yes>|template=<template name>}}
return _name_from_tag (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< _ T A G _ F R O M _ N A M E >--------------------------------------------------
Returns the IETF language tag associated with the language name. Spelling of language name must be correct
according to the spelling in the source tables. When a standard language name has a parenthetical disambiguator,
that disambiguator must be omitted (they are not present in the data name-to-tag tables).
Module entry point from another module.
]]
local function _tag_from_name (args) -- entry point from another module
local msg;
if args[1] and '' ~= args[1] then
local data = mw.loadData ('Module:Lang/tag from name'); -- get the reversed data tables TODO: change when going live
local lang = args[1]:lower(); -- allow any-case for the language name (speeling must till be correct)
local tag = data.rev_override_table[lang] or data.rev_lang_table[lang] or data.rev_lang_dep_table[lang]; -- get the code; look first in the override then in the standard
if tag then
return tag, true; -- language name found so return tag and done; second return used by is_lang_name()
else
msg = substitute (cfg.tag_from_name_t.lang_not_found, {args[1]}); -- language name not found, error message
end
else
msg = cfg.tag_from_name_t.missing_lang_name; -- language name not found, error message
end
local template = '';
if args.template and '' ~= args.template then
template = table.concat ({'{{', args['template'], '}}: '}); -- make template name (if provided by the template)
end
return make_error_span (template, msg);
end
--[[--------------------------< T A G _ F R O M _ N A M E >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function tag_from_name (frame) -- entry point from an {{#invoke:lang|tag_from_name|<language name>|link=<yes>|template=<template name>}}
local result, _ = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by is_lang_name()
return result;
end
--[[--------------------------< I S _ L A N G _ N A M E >------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_lang_name (frame)
local _, result = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by tag_from_name()
return result and true or nil;
end
--[[--------------------------< _ X L I T >--------------------------------------------------------------------
Module entry point from another module.
]]
local function _xlit (args)
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local language_name; -- language name that matches language code; used for tool tip
local translit; -- transliterated text to display
local script; -- IANA script
local msg; -- for when called functions return an error message
local template = args.template or cfg.templates_t.transliteration;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
if is_set (args[3]) then -- [3] set when {{transliteration|code|standard|text}}
args.text = args[3]; -- get the transliterated text
args.translit_std = args[2] and args[2]:lower(); -- get the standard; lower case for table indexing
if not title_table[args.translit_std] then
return make_error_msg (substitute (cfg.transl_t.unrecog_xlit_std, {args.translit_std}), args, template);
end
else
if is_set (args[2]) then -- [2] set when {{transliteration|code|text}}
args.text = args[2]; -- get the transliterated text
else
if args[1] and (args[1]:match ('^%a%a%a?%a?$') or -- args[2] missing; is args[1] a language or script tag or is it the transliterated text?
args[1]:match ('^%a%a%a?%-x%-')) then -- or is args[1] a private-use tag
return make_error_msg (cfg.transl_t.no_text, args, template); -- args[1] is a code so we're missing text
else
args.text = args[1]; -- args[1] is not a code so we're missing that; assign args.text for error message
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template);
end
end
end
if is_set (args[1]) then -- IANA language code used for HTML lang= attribute; or ISO 15924 script code
if args[1]:match ('^%a%a%a?%a?$') or args[1]:match ('^%a%a%a?%-x%-') then -- args[1] has correct form?
args.code = args[1]:lower(); -- use the language/script code; only (2, 3, or 4 alpha characters) or private-use; lower case because table indexes are lower case
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args[1]}), args, template); -- invalid language / script code
end
else
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template); -- missing language / script code so quit
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, args.code); -- is latn text? strip accept-as-written markup
if not is_latn_text then -- when text is not latn
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template); -- abandon with error message
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if 'italic' == args.italic then -- 'italic' when |italic=yes; because that is same as absent or not set and |italic=default
args.italic = nil; -- set to nil;
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if override_table[args.code] then -- is code a language code defined in the override table?
language_name = override_table[args.code];
args.code = args.code:match ('^%a%a%a?'); -- if private use, strip all but language subtag
elseif lang_table[args.code] then -- is code a language code defined in the standard language code tables?
language_name = lang_table[args.code];
elseif lang_dep_table[args.code] then -- is code a language code defined in the deprecated language code tables?
language_name = lang_dep_table[args.code];
elseif script_table[args.code] then -- if here, code is not a language code; is it a script code?
language_name = script_table[args.code];
script = args.code; -- code was an ISO 15924 script so use that instead
args.code = ''; -- unset because not a language code
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args.code}), args, template); -- invalid language / script code
end
-- here only when all parameters passed to make_translit() are valid
return make_translit (args.code, language_name, args.text, args.translit_std, script, args.italic, args.engvar);
end
--[[--------------------------< X L I T >----------------------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function xlit (frame)
return _xlit (getArgs(frame));
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Returns category name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _category_from_tag (args_t)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args_t[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args_t.link; -- make a boolean
local label = args_t.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local category_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args_t.template and table.concat ({'{{', args_t.template, '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
category_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = make_category (code, category_name, nil, true):gsub ('[%[%]]', '');
if link then
return table.concat ({'[[:', category_name, ']]'});
else
return category_name;
end
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function category_from_tag (frame) -- entry point from an {{#invoke:lang|category_from_tag|<IETF tag>|template=<template name>}}
return _category_from_tag (getArgs (frame)); -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
category_from_tag = category_from_tag, -- frame entry points when this module is #invoke:ed into templates/wikitext
lang = lang, -- entry point for {{lang}}
langx = langx, -- entry point for {{langx}}
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}}
lang_xx_italic = lang_xx_italic,
is_ietf_tag = is_ietf_tag,
is_ietf_tag_frame = is_ietf_tag_frame,
is_lang_name = is_lang_name,
tag_from_name = tag_from_name, -- returns IETF tag associated with language name
name_from_tag = name_from_tag, -- used for template documentation; possible use in ISO 639 name from code templates
xlit = xlit, -- entry point for {{transliteration}}
_category_from_tag = _category_from_tag, -- API entry points when this module is require()d into other modules
_lang = _lang,
_langx = _langx,
_lang_xx_inherit = _lang_xx_inherit,
_lang_xx_italic = _lang_xx_italic,
_is_ietf_tag = _is_ietf_tag,
get_ietf_parts = get_ietf_parts,
_tag_from_name = _tag_from_name,
_name_from_tag = _name_from_tag,
_xlit = _xlit,
_translation_make = translation_make,
};
rrpjq1fr0f1xw4spux9xfrmszmfveeh
392724
392723
2026-09-02T02:49:12Z
MacTire02
219
++
392724
Scribunto
text/plain
--[=[
Lua support for the {{lang}}, {{langx}}, {{lang-??}}, and {{transliteration}} templates and replacement of various supporting templates.
]=]
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local unicode = require ("Module:Unicode data"); -- for is_Latin() and is_rtl()
local yesno = require ('Module:Yesno');
local sandbox = (mw.getCurrentFrame():getTitle():match ('/sandbox') or ''); -- when called from a sandbox template or module load sandbox data and sandbox configuration
local lang_data = mw.loadData ('Module:Lang/data' .. sandbox); -- language name override and transliteration tool-tip tables
local lang_name_table = lang_data.lang_name_table; -- language codes, names, regions, scripts, suppressed scripts
local lang_table = lang_data.lang_name_table.lang;
local lang_dep_table = lang_data.lang_name_table.lang_dep;
local script_table = lang_data.lang_name_table.script;
local region_table = lang_data.lang_name_table.region;
local variant_table = lang_data.lang_name_table.variant;
local suppressed_table = lang_data.lang_name_table.suppressed;
local override_table = lang_data.override;
local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms'); -- ISO 639-2/639-2T code translation to 639-1 code
local cfg = mw.loadData ('Module:Lang/configuration' .. sandbox); -- for internationalization
local is_latn_data = mw.loadData ('Module:Lang/data/is latn data');
local sizeof_ranges_t = is_latn_data.sizeof_ranges_t;
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
local content_lang = mw.language.getContentLanguage();
local this_wiki_lang_tag = content_lang.code; -- get this wiki's language tag
local this_wiki_lang_dir = content_lang:getDir(); -- get this wiki's language direction
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic()
local maint_cats = {}; -- maintenance categories go here
local maint_msgs = {}; -- and their messages go here
--[[--------------------------< M A K E _ E R R O R _ S P A N >--------------------------------------------------
]]
local function make_error_span (template, msg)
return table.concat ({'<span style="color:var(--color-error,#d33)">', cfg.misc_text_t.error, ': ', template, msg, '</span>'})
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.
]]
local function substitute (message, data_t)
return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end
--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
Assembles an error message from template name, message text, help link, and error category.
]]
local function make_error_msg (msg, args_t, template)
local category;
local text; -- handle the oddity that is {{langx}}
if cfg.templates_t.langxx == template then
text = args_t.text or args_t[1]; -- for {{lang-xx}}
else
text = args_t.text or args_t[2]; -- for {{lang}}, {{langx}}, and {{transliteration}}
end
if cfg.templates_t.transliteration == template then
category = cfg.make_error_msg_t.xlit_err_cat;
else
category = cfg.make_error_msg_t.lang_err_cat;
end
local category_link = ((0 == namespace or 10 == namespace) and not args_t.nocat) and substitute ('[[Category:$1]]', {category}) or '';
return substitute ('[$1] <span style="color:var(--color-error,#d33)">$2: {{$3}}: $4 ([[:Category:$5|$6]])</span>$7', -- { prevents template name from being treated as a template call in certain situations
{
text or cfg.make_error_msg_t.undefined,
cfg.misc_text_t.error,
template,
msg,
category,
cfg.misc_text_t.help,
category_link
})
end
--[[--------------------------< P A R A M E T E R _ V A L I D A T E >------------------------------------------
]]
local function parameter_validate (args_t, template)
local err_msg = cfg.parameter_validate_t.invalid_param;
if cfg.templates_t.lang == template then -- for {{lang}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_t[param] and -- unique {{lang}} parameters
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langx == template then -- for {{langx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_langx_t[param] and -- unique {{langx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langxx == template then -- for {{lang-xx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_xx_t[param] and -- unique {{lang-xx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
end
end
--[[--------------------------< 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 V E R T _ I T A L I C S >-------------------------------------------------
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing
apostrophes are converted to their HTML numeric entity equivalent so that the new italic markup doesn't become
bold markup inadvertently.
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal,
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements.
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns.
This function expects that markup in args.text is complete and correct; if it is not, oddness may result.
]]
local function invert_italics (source)
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns
[""]="\'\'", -- empty string becomes italic markup
["\'\'"]="", -- italic markup becomes empty string
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold
};
local seg = {};
source = source:gsub ("%f[\']\'%f[^\']", '''); -- protect single quote marks from being interpreted as bold markup
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text'
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup
elseif '' ~= seg[1] then
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup
elseif '' ~= seg[3] then
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup
else
seg[2] = source -- when there is no markup
end
seg[1] = invert_pattern_table[seg[1]] or seg[1]; -- replace leading markup according to pattern table
seg[3] = invert_pattern_table[seg[3]] or seg[3]; -- replace leading markup according to pattern table
return table.concat (seg); -- put it all back together and done
end
--[[--------------------------< V A L I D A T E _ I T A L I C >------------------------------------------------
Validates |italic= or |italics= assigned values.
When |italic= is set and has an acceptable assigned value, return the matching CSS font-style property value or,
for the special case 'default', return nil.
When |italic= is not set, or has an unacceptable assigned value, return nil and a nil error message.
When both |italic= and |italics= are set, returns nil and a 'conflicting' error message.
The return value nil causes the calling lang, lang_xx, or xlit function to set args.italic according to the template's
defined default ('inherit' for {{lang}}, 'inherit' or 'italic' for {{lang-??}} depending on
the individual template's requirements, 'italic' for {{transliteration}}) or to the value appropriate to |script=, if set ({{lang}}
and {{lang-??}} only).
Accepted values and the values that this function returns are are:
nil - when |italic= absent or not set; returns nil
default - for completeness, should rarely if ever be used; returns nil
yes - force args.text to be rendered in italic font; returns 'italic'
no - force args.text to be rendered in normal font; returns 'normal'
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit'
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert'
]]
local function validate_italic (args)
local properties = {[cfg.keywords_t.affirmative] = 'italic', [cfg.keywords_t.negative] = 'normal', [cfg.keywords_t.unset] = 'inherit', [cfg.keywords_t.invert] = 'invert', [cfg.keywords_t.default] = nil};
local count = 0
for _, arg in pairs {'italic', 'italics', 'i'} do
if args[arg] then
count = count + 1
end
end
if count > 1 then -- return nil and an error message if more than one is set
return nil, cfg.validate_italic_t.multi_italic;
end
return properties[args.italic or args.italics or args.i], nil; -- return an appropriate value and a nil error message
end
--[=[--------------------------< V A L I D A T E _ C A T _ A R G S >----------------------------------------------------------
Default behavior of the {{lang}} and {{lang-??}} templates is to add categorization when the templates are used in main space.
This default functionality may be suppressed by setting |nocat=yes or |cat=no. This function selects one of these two parameters
to control categorization.
Because having two parameters with 'opposite' names and 'opposite' values is confusing, this function accepts only affirmative
values for |nocat= and only negative values for |cat=; in both cases the 'other' sense (and non-sense) is not accepted and the
parameter is treated as if it were not set in the template.
Sets args.nocat to true if categorization is to be turned off; to nil if the default behavior should apply.
Accepted values for |nocat= are the text strings:
'yes', 'y', 'true', 't', on, '1' -- [[Module:Yesno]] returns logical true for all of these; false or nil else
for |cat=
'no', 'n', 'false', 'f', 'off', '0' -- [[Module:Yesno]] returns logical false for all of these; true or nil else
]=]
local function validate_cat_args (args)
if not (args.nocat or args.cat) then -- both are nil, so categorize
return;
end
if false == yesno (args.cat) or true == yesno (args.nocat) then
args.nocat = true; -- set to true when args.nocat is affirmative; nil else (as if the parameter were not set in the template)
else -- args.nocat is the parameter actually used.
args.nocat = nil;
end
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
--[[--------------------------< F O R M A T _ I E T F _ T A G >------------------------------------------------
Prettify IETF tags to use recommended subtag formats:
code: lower case
script: sentence case
region: upper case
variant: lower case
private: lower case prefixed with -x-
]]
local function format_ietf_tag (code, script, region, variant, private)
local out = {};
if is_set (private) then
return table.concat ({code:lower(), 'x', private:lower()}, '-'); -- if private, all other tags ignored
end
table.insert (out, code:lower());
if is_set (script) then
script = script:lower():gsub ('^%a', string.upper);
table.insert (out, script);
end
if is_set (region) then
table.insert (out, region:upper());
end
if is_set (variant) then
table.insert (out, variant:lower());
end
return table.concat (out, '-');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
Extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character IANA language code
script subtag - four character IANA script code
region subtag - two-letter or three digit IANA region code
variant subtag - four digit or 5-8 alnum variant code; only one variant subtag supported
private subtag - x- followed by 1-8 alnum private code; only supported with the primary language tag
in any one of these forms
lang lang-variant
lang-script lang-script-variant
lang-region lang-region-variant
lang-script-region lang-script-region-variant
lang-x-private
each of lang, script, region, variant, and private, when used, must be valid.
Languages with both two- and three-character code synonyms are promoted to the two-character synonym because
the IANA registry file omits the synonymous three-character code; we cannot depend on browsers understanding
the synonymous three-character codes in the lang= attribute.
For {{lang-??}} templates, the parameters |script=, |region=, and |variant= are supported (not supported in {{lang}}
because those parameters are superfluous to the IETF subtags in |code=).
Returns six values; all lower case. Valid parts are returned as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil; the sixth returned item is an error message (if an error detected) or nil.
See http://www.rfc-editor.org/rfc/bcp/bcp47.txt section 2.1.
]]
local function get_ietf_parts (source, args_script, args_region, args_variant)
local code, script, region, variant, private; -- IETF tag parts
if not is_set (source) then
return nil, nil, nil, nil, nil, cfg.get_ietf_parts_t.missing_lang_tag;
end
local pattern = { -- table of tables holding acceptable IETF tag patterns and short names of the IETF part captured by the pattern
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits)
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits)
{'^(%a%a%a?)$'}, -- 18 - ll
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters)
}
local t = {}; -- table of captures; serves as a translator between captured IETF tag parts and named variables
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i])
if c1 then -- c1 always set on match
code = c1; -- first capture is always code
t = {
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table
};
script = t.s or ''; -- translate table contents to named variables;
region = t.r or ''; -- absent table entries are nil so set named IETF parts to empty string for concatenation
variant= t.v or '';
private = t.p or '';
break; -- and done
end
end
if not code then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_tag, {source}); -- don't know what we got but it is malformed
end
code = code:lower(); -- ensure that we use and return lower case version of this
if not (override_table[code] or lang_table[code] or synonym_table[code] or lang_dep_table[code]) then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_code, {code}); -- invalid language code, don't know about the others (don't care?)
end
if synonym_table[code] then -- if 639-2/639-2T code has a 639-1 synonym
table.insert (maint_cats, substitute (cfg.get_ietf_parts_t.maint_promo_cat, {code}));
table.insert (maint_msgs, substitute (cfg.get_ietf_parts_t.maint_promo_msg, {code, synonym_table[code]}));
code = synonym_table[code]; -- use the synonym
end
if is_set (script) then
if is_set (args_script) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_scr; -- both code with script and |script= not allowed
end
else
script = args_script or ''; -- use args.script if provided
end
if is_set (script) then
script = script:lower(); -- ensure that we use and return lower case version of this
if not script_table[script] then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_scr_code, {script, code}); -- language code OK, invalid script, don't know about the others (don't care?)
end
end
if suppressed_table[script] then -- ensure that code-script does not use a suppressed script
if in_array (code, suppressed_table[script]) then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.script_code, {script, code}); -- language code OK, script is suppressed for this code
end
end
if is_set (region) then
if is_set (args_region) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_reg; -- both code with region and |region= not allowed
end
else
region = args_region or ''; -- use args.region if provided
end
if is_set (region) then
region = region:lower(); -- ensure that we use and return lower case version of this
if not region_table[region] then
return code, script, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_reg_code, {region, code});
end
end
if is_set (variant) then
if is_set (args_variant) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_var; -- both code with variant and |variant= not allowed
end
else
variant = args_variant or ''; -- use args.variant if provided
end
if is_set (variant) then
variant = variant:lower(); -- ensure that we use and return lower case version of this
if not variant_table[variant] then -- make sure variant is valid
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var, {variant});
end -- does this duplicate/replace tests in lang() and lang_xx()?
if is_set (script) then -- if script set it must be part of the 'prefix'
if not in_array (table.concat ({code, '-', script}), variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_scr, {variant, code, script});
end
elseif is_set (region) then -- if region set, there are some prefixes that require lang code and region (en-CA-newfound)
if not in_array (code, variant_table[variant]['prefixes']) then -- first see if lang code is all that's required (en-oxendict though en-GB-oxendict is preferred)
if not in_array (table.concat ({code, '-', region}), variant_table[variant]['prefixes']) then -- now try for lang code and region (en-CA-newfound)
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_reg, {variant, code, region});
end
end
else -- cheap way to determine if there are prefixes; fonipa and others don't have prefixes; # operator always returns 0
if variant_table[variant]['prefixes'][1] and not in_array (code, variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code, {variant, code});
end
end
end
if is_set (private) then
private = private:lower(); -- ensure that we use and return lower case version of this
if not override_table[table.concat ({code, '-x-', private})] then -- make sure private tag is valid; note that index
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_pri, {private});
end
end
return code, script, region, variant, private, nil; -- return the good bits; make sure that msg is nil
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, 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 is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< D I V _ M A R K U P _ A D D >--------------------------------------------------
Adds <i> and </i> tags to list-item text or to implied <p>..</p> text. Mixed not supported.
]]
local function div_markup_add (text, style)
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text
if 'italic' == style then
return text:gsub ('(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item
else
return text;
end
end
if text:find ('\n+') then -- look for any number of \n characters in text
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics MediaWiki
if 'italic' == style then
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each implied p (two or more consecutive '\n\n' sequences)
else
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each implied p
text = text:gsub ('\n', ''); -- strip newline characters
end
end
return text;
end
--[[--------------------------< T I T L E _ W R A P P E R _ M A K E >------------------------------------------
Makes a <span title="<title text>"><content_text></span> or <div title="<title text>"><content_text></div> where
<title text> is in the tool-tip in the wiki's local language and <content_text> is non-local-language text in
HTML markup. This because the lang= attribute applies to the content of its enclosing tag.
<tag> holds a string 'div' or 'span' used to choose the correct wrapping tag.
]]
local function title_wrapper_make (title_text, content_text, tag)
local wrapper_t = {};
table.insert (wrapper_t, table.concat ({'<', tag})); -- open opening wrapper tag
table.insert (wrapper_t, ' title=\"'); -- begin title attribute
table.insert (wrapper_t, title_text); -- add <title_text>
table.insert (wrapper_t, '\">'); -- end title attribute and close opening wrapper tag
table.insert (wrapper_t, content_text); -- add <content_text>
table.insert (wrapper_t, table.concat ({'</', tag, '>'})); -- add closing wrapper tag
return table.concat (wrapper_t); -- make a big string and done
end
--[[--------------------------< M A K E _ T E X T _ H T M L >--------------------------------------------------
Add the HTML markup to text according to the type of content that it is: <span> or <i> tags for inline content or
<div> tags for block content
The lang= attribute also applies to the content of the tag where it is placed so this is wrong because 'Spanish
language text' is English:
<i lang="es" title="Spanish language text">casa</i>
should be:
<span title="Spanish language text"><i lang="es">casa</i></span>
or for <div>...</div>:
<div title="Spanish language text"><div lang="es"><spanish-language-text></div></div>
]]
local function make_text_html (code, text, tag, rtl, style, size, language)
local html_t = {};
local style_added = '';
local wrapper_tag = tag; -- <tag> gets modified so save a copy for use when/if we create a wrapper span or div
if text:match ('^%*') then
table.insert (html_t, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plain splat confuses MediaWiki
text = text:gsub ('^%*', ''); -- remove the splat from the text
end
if 'span' == tag then -- default HTML tag for inline content
if 'italic' == style then -- but if italic
tag = 'i'; -- change to <i> tags
end
else -- must be div so go
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i>
end
table.insert (html_t, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> HTML tag
code = code:gsub ('%-x%-.*', ''); -- strip private use subtag from code tag because meaningless outside of Wikipedia
table.insert (html_t, table.concat ({' lang="', code, '\"'})); -- add language attribute
if (rtl or unicode.is_rtl(text)) and ('ltr' == this_wiki_lang_dir) then -- text is right-to-left on a left-to-right wiki
table.insert (html_t, ' dir="rtl"'); -- add direction attribute for right-to-left languages
elseif not (rtl or unicode.is_rtl(text)) and ('rtl' == this_wiki_lang_dir) then -- text is left-to-right on a right-to-left wiki
table.insert (html_t, ' dir="ltr"'); -- add direction attribute for left-to-right languages
end
if 'normal' == style then -- when |italic=no
table.insert (html_t, ' style=\"font-style: normal;'); -- override external markup, if any
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
if is_set (size) then -- when |size=<something>
if is_set (style_added) then
table.insert (html_t, table.concat ({' font-size: ', size, ';'})); -- add when style attribute already inserted
else
table.insert (html_t, table.concat ({' style=\"font-size: ', size, ';'})); -- create style attribute
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
end
table.insert (html_t, table.concat ({style_added, '>'})); -- close the opening HTML tag
table.insert (html_t, text); -- insert the text
table.insert (html_t, table.concat ({'</', tag, '>'})); -- close the 'text' <i>, <span>, or <div> HTML tag
if is_set (language) then -- create a <title_text> string for the title= attribute in a wrapper span or div
local title_text;
if 'zxx' == code then -- special case for this tag 'no linguistic content'
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.zxx}); -- not a language so don't use 'language' in title text
elseif mw.ustring.find (language, 'languages', 1, true) then
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.collective}); -- for collective languages
else
title_text = substitute ('$1-$2', {language, cfg.make_text_html_t.individual}); -- for individual languages
end
return title_wrapper_make (title_text, table.concat (html_t), wrapper_tag);
else
return table.concat (html_t);
end
end
--[=[-------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
For individual language, <language>, returns:
[[Category:Articles containing <language>-language text]]
For English:
[[Category:Articles containing explicitly cited English-language text]]
For ISO 639-2 collective languages (and for 639-1 bh):
[[Category:Articles with text in <language> languages]]
]=]
local function make_category (code, language_name, nocat, name_get)
if ((0 ~= namespace) or nocat) and not name_get then -- only categorize in article space
return ''; -- return empty string for concatenation
end
if mw.ustring.find (language_name, 'languages', 1, true) then
return substitute ('[[$1 $2]]', {cfg.make_category_t.collective_cat, language_name});
end
if this_wiki_lang_tag == code then
return substitute ('[[$1 $2 $3-$4]]', { -- unique category name for the local language
cfg.make_category_t.cat_prefix,
cfg.make_category_t.explicit_cat,
language_name,
cfg.make_category_t.cat_postfix,
});
else
return substitute ('[[$1 $2-$3]]', { -- category for individual languages
cfg.make_category_t.cat_prefix,
language_name,
cfg.make_category_t.cat_postfix,
});
end
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
Return translit <i lang=xx-Latn>...</i> where xx is the language code; else return empty string.
The value |script= is not used in {{transliteration}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transliteration}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
To avoid confusion, in this module and the templates that use it, the transliteration script parameter is renamed
to be |translit-script= (in this function, tscript).
This function is used by both lang_xx() and xlit()
lang_xx() always provides code, language_name, and translit; may provide tscript; never provides style
xlit() always provides language_name, translit, and one of code or tscript, never both; always provides style
For {{transliteration}}, style only applies when a language code is provided.
]]
local function make_translit (code, language_name, translit, std, tscript, style, engvar)
local title_t = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local title_text = ''; -- tool tip text for title= attribute
std = std and std:lower(); -- lower case for table indexing
if not is_set (std) and not is_set (tscript) then -- when neither standard nor script specified
title_text = language_name; -- write a generic tool tip
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', {title_text, cfg.misc_text_t.language}); -- skip this text (individual and macro languages only)
end
title_text = substitute ('$1 $2', {title_text, mw.ustring.lower (cfg.engvar_t[engvar]['romanisz_lc'])}); -- finish the tool tip; use romanization when neither script nor standard supplied
elseif is_set (std) and is_set (tscript) then -- when both are specified
if title_t[std] then -- and if standard is legitimate
if title_t[std][tscript] then -- and if script for that standard is legitimate
if script_table[tscript] then
title_text = substitute ('$1$2 ($3 $4) $5', { -- add the appropriate text to the tool tip
title_text,
title_t[std][tscript:lower()],
script_table[tscript],
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
return ''; -- invalid standard, setup for error message
end
elseif is_set (std) then -- translit-script not set, use language code
if not title_t[std] then return ''; end -- invalid standard, setup for error message
if title_t[std][code] then -- if language code is in the table (xlit may not provide a language code)
local fmt_str = '$1$2 ($3 $4) $5'; -- generic format string for tool tip
if language_name:match ('languages') then
fmt_str = '$1$2 ($3) $5'; -- format string for collective languages tool tip
end
title_text = substitute (fmt_str, { -- add the appropriate text to the tool tip
title_text,
title_t[std][code:lower()],
language_name,
cfg.misc_text_t.language,
cfg.make_translit_t.transliteration,
});
else -- code doesn't match
title_text = title_text .. title_t[std]['default']; -- so use the standard's default
end
else -- here if translit-script set but translit-std not set
if title_t['no_std'][tscript] then
title_text = title_text .. title_t['no_std'][tscript]; -- use translit-script if set
elseif title_t['no_std'][code] then
title_text = title_text .. title_t['no_std'][code]; -- use language code
else
if is_set (tscript) then
title_text = substitute ('$1$2-$3 $4', { -- write a script tool tip
title_text,
language_name,
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
elseif is_set (code) then
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end
local tag
if is_set (code) then -- when a language code is provided (always with {{lang-??}} templates, not always with {{transliteration}})
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span style="font-style: %s" lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ({{transliteration}} only)
end
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end
--[[--------------------------< V A L I D A T E _ T E X T >----------------------------------------------------
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an
error message. The tests are for empty or missing text and for improper or disallowed use of apostrophe markup.
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert.
]]
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end
local style = args.italic;
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end
--[[--------------------------< R E N D E R _ M A I N T >------------------------------------------------------
Render mainenance messages and categories.
]]
local function render_maint (nocat)
local maint = {};
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span class="lang-comment" style="font-style: normal; display: none; color: #33aa33; margin-left: 0.3em;">'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({'[[Category:', cat, ']]'})); -- format and add the categories
end
end
return table.concat (maint);
end
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.
]]
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------
Looks for a poem strip marker in text; returns true when found; false else.
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.
]]
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------
Inspects content of and selectively trims text. Returns text and the name of an appropriate HTML tag for text.
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.
]]
local function html_tag_select (text)
local tag;
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end
return text, tag;
end
--[[--------------------------< V A L I D A T E _ P R O T O >--------------------------------------------------
Validates value assigned to |proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.
]]
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end
--[[--------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------
Common function to return language name from the data set according to IETF tag.
Returns language name if found in data tables; nil else.
]]
local function language_name_get (ietf, code, cat)
ietf = ietf:lower(); -- ietf:lower() because format_ietf_tag() returns mixed case
local name; -- remains nil if not found
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to IANA active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the IANA deprecated tag/name table
name = lang_dep_table[code];
end
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end
return name; -- name from data tables or nil
end
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.
Returns an error message when mismatch detected; nil else.
]]
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower(); -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end
--[[--------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------
conducts a binary search of <ranges_t> for a sub-range that holds <target>.
returns boolean true if a sub-range holding <target> is found; boolean false else.
]]
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end
if flag then
break; -- here when we just evaluated the last range and <target> not found
end
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end
--[[--------------------------< I S _ L A T I N >--------------------------------------------------------------
compare <text> as codepoints to lists of known codepoints accepted as Latn script
returns boolean true and modified <text> when <text> is wrapped in accept-as-written markup
returns boolean true and <text> when codepoint is known
returns boolean false, <text>, non-Latn codepoint position in <text> (left to right), and the codepoint character
when codepoint is not known
TODO: when text has accept-as-written markup, return a non-boolean value to indicate that <text> is not wholly
latn script? Use that return value to create non-Latn HTML lang= attribute because <text> isn't really
latn so lang=und (undetermined)? or instead, omit the -Latn subtag? (without -Latn need to force |italic=yes)
]]
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end
--[[--------------------------< _ L A N G >--------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or cfg.templates_t.lang;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
validate_cat_args (args); -- determine if categorization should be suppressed
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code ({{{1}}} in {{lang}})
if msg then
return make_error_msg (msg, args, template);
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
if is_set (subtags.script) then -- if script set, override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if cfg.keywords_t.invert == args.italic and 'span' == tag then -- invert only supported for in-line content
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name));
table.insert (out, make_category (code, language_name, args.nocat));
table.insert (out, render_maint (args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function lang (frame)
local args_t = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text
valueFunc = function (key, value)
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space
return value; -- return untrimmed 'text'
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
args_t.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang|...}}
local msg = parameter_validate (args_t, cfg.templates_t.lang); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.lang); -- when template has unsupported params, abandon with error message
end
return _lang (args_t);
end
--[[--------------------------< T R A N S L A T I O N _ M A K E >----------------------------------------------
Stand-alone function to create literal translation of main text.
Also used by {{lang-x2}}.
]]
local function translation_make (args_t)
local translation_t = {', '}; -- initialize output
if 'none' ~= args_t.label then -- if we want a label
table.insert (translation_t, '<small>'); -- open the <small> HTML tag
if cfg.keywords_t.negative == args_t.link then
table.insert (translation_t, substitute ('<abbr title="$1">$2</abbr>', {cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr})); -- unlinked form
else
table.insert (translation_t, make_wikilink (cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr)); -- linked form
end
table.insert (translation_t, " </small>"); -- close the <small> HTML tag
end
table.insert (translation_t, table.concat ({ -- user styling spans match spand from {{gloss}}
'<span class="gloss-quot">\'</span>', -- user styling span for quote marks; use HTML entities to avoid wiki markup confusion
'<span class="gloss-text">', -- open user styling span for the translation
args_t.translation, -- the translation
'</span>', -- close user styling span for the translation
'<span class="gloss-quot">\'</span>' -- user styling span for quote marks
}));
return table.concat (translation_t); -- make a big string and done
end
--[[--------------------------< _ L A N G _ X X >--------------------------------------------------------------
For the {{lang-??}} templates, the only parameter required to be set in the template is the language code. All
other parameters can, usually should, be written in the template call. For {{lang-??}} templates for languages
that can have multiple writing systems, it may be appropriate to set |script= as well.
For each {{lang-??}} template choose the appropriate entry-point function so that this function knows the default
styling that should be applied to text.
For normal, upright style:
<includeonly>{{#invoke:lang|lang_xx_inherit|code=xx}}</includeonly>
For italic style:
<includeonly>{{#invoke:lang|lang_xx_italic|code=xx}}</includeonly>
All other parameters should be received from the template's frame (parent frame)
Supported parameters are:
|code = (required) the IANA language code
|script = IANA script code; especially for use with languages that use multiple writing systems
|region = IANA region code
|variant = IANA variant code
|text = (required) the displayed text in language specified by code
|link = boolean false ('no') does not link code-spcified language name to associated language article
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected
|cat = boolian false ('no') opposite form of |nocat=
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state
|lit = text that is a literal translation of text
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.')
any other text replaces language-name label - automatic wikilinking disabled
for those {{lang-??}} templates that support transliteration (those templates where |text= is not entirely latn script):
|translit = text that is a transliteration of text
|translit-std = the standard that applies to the transliteration
|translit-script = ISO 15924 script name; falls back to code
For {{lang-??}}, the positional parameters are:
{{{1}}} text
{{{2}}} transliterated text
{{{3}}} literal translation text
no other positional parameters are allowed
]]
local function _lang_xx (args, base_template) -- base_template will be either of 'langx' or 'lang-xx'
local out = {};
local language_name; -- used to make display text, article links
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, and variant
local code; -- the language code
local translit_script_name; -- name associated with IANA (ISO 15924) script code
local translit;
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or base_template;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
local text_idx = (cfg.templates_t.langx == base_template) and 2 or 1; -- for {{langx}} 'text' positional parameter is '2'
local translit_idx = (cfg.templates_t.langx == base_template) and 3 or 2;
local xlate_idx = (cfg.templates_t.langx == base_template) and 4 or 3;
if args[text_idx] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {text_idx, cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[text_idx] or args.text; -- prefer positional 'text' parameter
end
msg = validate_text (template, args); -- ensure that |text= is set, does not contain italic markup and is protected from improper bolding
if is_set (msg) then
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
if args[translit_idx] and args.translit then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {translit_idx, cfg.lang_t.conflict_n_param_types.translit}), args, template);
else
args.translit = args[translit_idx] or args.translit -- prefer positional 'translit' parameter
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if args[xlate_idx] and (args.translation or args.lit) then
return make_error_msg (substitute (cfg.lang_xx_t.conflict_n_lit, {xlate_idx}), args, template);
elseif args.translation and args.lit then
return make_error_msg (cfg.lang_xx_t.conflict_lit, args, template);
else
args.translation = args[xlate_idx] or args.translation or args.lit; -- prefer positional 'translation' parameter
end
if args.links and args.link then
return make_error_msg (cfg.lang_xx_t.conflict_link, args, template);
else
args.link = args.link or args.links; -- prefer args.link
end
validate_cat_args (args); -- determine if categorization should be suppressed
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code, args.script, args.region, args.variant); -- private omitted because private
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
if args.translit then
local latn, pos, char;
latn, args.translit, pos, char = is_latin (args.translit, (('' ~= subtags.private) and (code .. '-x-' .. subtags.private)) or code);
if not latn then
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template);
end
end
local is_latn_text, text, pos, char = is_latin (args.text, code); -- make a boolean
args.text = text; -- may have been modified (accept-as-written markup removed)
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if cfg.templates_t.langx == base_template then -- auto-italics for {{langx}} templates; adapted from {{lang}} (no support for poem tag)
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and is_latn_text) then -- text is not this wiki's language, no script specified and is wholly latn script (auto-italics)
args.italic = 'italic'; -- set font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
else -- {{lang-xx}} does not do auto italics; retained for those wikis that don't support {{langx}}
if nil == args.italic then -- args.italic controls
if is_set (subtags.script) then
if 'latn' == subtags.script then
args.italic = 'italic'; -- |script=Latn; set for font-style:italic
else
args.italic = initial_style_state; -- italic not set; script is not latn; set for font-style:<initial_style_state>
end
else
args.italic = initial_style_state; -- here when |italic= and |script= not set; set for font-style:<initial_style_state>
end
end
end
if is_set (subtags.script) then -- if script set override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {args.proto}), args, template);
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = language_name; -- category names retain IANA parenthetical diambiguators (if any)
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
if args.label then
if 'none' ~= args.label then
table.insert (out, table.concat ({args.label, ': '})); -- custom label
end
else
if cfg.keywords_t.negative == args.link then
table.insert (out, language_name); -- language name without wikilink
else
if mw.ustring.find (language_name, 'languages', 1, true) then
table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink
elseif lang_data.article_name[args.code:lower()] then -- is IETF tag in article name over ride?
table.insert (out, make_wikilink (lang_data.article_name[args.code:lower()], language_name)); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article override
table.insert (out, make_wikilink (lang_data.article_name[code], language_name)); -- language name with wikilink from override data
else
table.insert (out, make_wikilink (language_name, language_name)); -- Manx language name with wikilink
end
end
table.insert (out, ': '); -- separator
end
if cfg.keywords_t.invert == args.italic then
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, ('none' == args.label) and language_name or nil))
if is_set (args.translit) and not is_latn_text then -- transliteration; not supported when args.text is wholly latn text (this is an imperfect test)
table.insert (out, ', '); -- comma to separate text from translit
if 'none' ~= args.label then
table.insert (out, '<small>');
if script_table[args['translit-script']] then -- when |translit-script= is set, try to use the script's name
translit_script_name = script_table[args['translit-script']];
else
translit_script_name = language_name; -- fall back on language name
end
local translit_title_obj = mw.title.makeTitle (0, substitute ('$1 $2',{cfg.lang_xx_t.romanization, translit_script_name})); -- make a title object; no engvar, article titles use US spelling
if translit_title_obj.exists and (cfg.keywords_t.negative ~= args.link) then
table.insert (out, make_wikilink (substitute ('$1 $2', {cfg.lang_xx_t.romanization, translit_script_name or language_name}),
substitute ('$1', {cfg.engvar_t[args.engvar]['romanisz_pt']})) .. ':'); -- make a wikilink if there is an article to link to; engvar the display text
else
table.insert (out, substitute ('$1:', {cfg.engvar_t[args.engvar]['romanisz_pt']})); -- else plain text per engvar
end
table.insert (out, ' </small>'); -- close the small tag
end
translit = make_translit (args.code, language_name, args.translit, args['translit-std'], args['translit-script'], nil, args.engvar)
if is_set (translit) then
table.insert (out, translit);
else
return make_error_msg (substitute ('$1: $2', {cfg.lang_xx_t.invalid_xlit_std, args['translit-std'] or '[missing]'}), args, template);
end
elseif is_set (args.translit) and is_latn_text then -- when creating a transliteration of Latn script <text>
return make_error_msg (cfg.lang_xx_t.xlit_of_latn, args, template); -- emit error message and abandon
end
if is_set (args.translation) then -- translation (not supported in {{lang}})
table.insert (out, translation_make (args));
end
table.insert (out, make_category (code, category_name, args.nocat));
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X _ A R G S _ G E T >----------------------------------------------
Common function to get args table from {{lang-??}} templates.
Returns table of args.
Text positional parameters are not trimmed here but are selectively trimmed at html_tag_select().
]]
local function lang_xx_args_get (frame, base_template)
local args_t = getArgs(frame,
{
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}}
valueFunc = function (key, value)
if ((cfg.templates_t.langx == base_template) and 2 or 1) == key then -- the 'text' positional parameter; 1 for {{lang-??}}, 2 for {{langx}}; do not trim wite space
return value; -- return untrimmed 'text' positional parameter
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
return args_t;
end
--[[--------------------------< L A N G _ X X _ I T A L I C >--------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_italic(). Sets the initial style state to italic.
]]
local function lang_xx_italic (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_italic|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I T A L I C >------------------------------------------------
Entry point from another module. Sets the initial style state to italic.
]]
local function _lang_xx_italic (args)
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< L A N G _ X X _ I N H E R I T >------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_inherit(). Sets the initial style state to inherit.
]]
local function lang_xx_inherit (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_inherit|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I N H E R I T >----------------------------------------------
Entry point from another module. Sets the initial style state to inherit.
]]
local function _lang_xx_inherit (args)
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< _ L A N G X >------------------------------------------------------------------
Entry point from another module.
]]
local function _langx (args_t)
local langx_data = mw.loadData ('Module:Lang/langx'); -- get necessary data
local rtl_t = langx_data.rtl_t; -- get list of language tags for languages that are rendered right-to-left
local link_t = langx_data.link_t; -- get list of language tags for {{lang-??}} templates that set |link=<something>
local size_t = langx_data.size_t; -- get list of language tags for {{lang-??}} templates that set |size=<something>
local msg = parameter_validate (args_t, cfg.templates_t.langx);
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.langx);
end
args_t.code = args_t[1] or args_t.code; -- get the language tag; must be {{{1}}} or |code=
if not args_t.code then
return make_error_msg (cfg.get_ietf_parts_t.missing_lang_tag, args_t, cfg.templates_t.langx);
end
args_t.rtl = args_t.rtl or (rtl_t[args_t.code] and cfg.keywords_t.affirmative); -- prefer |rtl= in template call, use rtl_t else
args_t.link = args_t.link or link_t[args_t.code]; -- prefer |link= in template call, use link_t felse
args_t.size = args_t.size or size_t[args_t.code]; -- prefer |size= in template call, use size_t else
args_t[1] = nil; -- unset to mimic {{lang-??}} templates which set |code=xx
local lang_subtag = args_t.code; -- use only the base language subtag for unsupported tag test; some args_t.code are modified by |script= etc
return _lang_xx (args_t, cfg.templates_t.langx);
end
--[[--------------------------< L A N G X >--------------------------------------------------------------------
Entry point for {{langx}}.
this function calls _lang_xx() to render non-English text. The {{lang-??}} templates have three positional paramters
but {{langx}} has four:
| 1 | 2 | 3 | 4
{{lang-xx |<text> |<xlit> |<xlat> }}
{{langx |<tag> |<text> |<xlit> |<xlat> }}
The calls to lang_xx_args_get() and _lang_xx() use 'langx' as a flag for those functions to select the proper
positional parameters.
{{lang-??}} depends on the calling template to select 'inherit' or 'italic' to establish the default rendering.
{{langx}} can't do that. The initial version of {{langx}} relied on a list of language tags (inherit_t in ~/langx)
scraped from those {{lang-??}} templates that call lang_xx_inherit() to render text in upright font. langx() now
uses auto-italics code adapted from {{lang}} (doesn't support poem tags).
]]
local function langx (frame)
local args_t = lang_xx_args_get (frame, cfg.templates_t.langx); -- get the arguments; 'langx' is the <base_template> used to decide which positional param is 'text', 'translit', 'lit'
return _langx (args_t);
end
--[[--------------------------< _ I S _ I E T F _ T A G >------------------------------------------------------
Returns true when a language name associated with IETF language tag exists; nil else. IETF language tag must be valid.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _is_ietf_tag (tag) -- entry point when this module is require()d into another
local c, s, r, v, p, err; -- code, script, region, variant, private, error message
c, s, r, v, p, err = get_ietf_parts (tag); -- disassemble tag into constituent part and validate
return ((c and not err) and true) or nil; -- return true when code portion has a value without error message; nil else
end
--[[--------------------------< I S _ I E T F _ T A G >--------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_ietf_tag (frame)
return _is_ietf_tag (getArgs (frame)[1]); -- args[1] is the IETF language tag to be tested; also get parent frame
end
--[[--------------------------< I S _ I E T F _ T A G _ F R A M E >--------------------------------------------
Module entry point from an {{#invoke:}}; same as is_ietf_tag() except does not get parameters from the parent
(template) frame. This function not useful when called by {{lang|fn=is_ietf_tag_frame|<tag>}} because <tag>
is in the parent frame.
]]
local function is_ietf_tag_frame (frame)
return _is_ietf_tag (getArgs (frame, {frameOnly = true,})[1]); -- args[1] is the IETF language tag to be tested; do not get parent frame
end
--[[--------------------------< _ N A M E _ F R O M _ T A G >--------------------------------------------------
Returns language name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Set invoke's |link= parameter to yes to get wikilinked version of the language name.
Module entry point from another module.
]]
local function _name_from_tag (args)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args['link']; -- make a boolean
local label = args.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local language_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args['template'] and table.concat ({'{{', args['template'], '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
language_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if 'yes' ~= args.raw then
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
end
if link then -- when |link=yes, wikilink the language name
if mw.ustring.find (language_name, 'languages', 1, true) then
language_name = make_wikilink (language_name, label); -- collective language name uses simple wikilink
elseif lang_data.article_name[raw_code:lower()] then -- is IETF tag in article name override?
language_name = make_wikilink (lang_data.article_name[raw_code:lower()], label or language_name); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article name override?
language_name = make_wikilink (lang_data.article_name[code], label or language_name); -- language name with wikilink from override data
else
language_name = make_wikilink (language_name, label or language_name); -- Manx language name with wikilink
end
end
return language_name;
end
--[[--------------------------< N A M E _ F R O M _ T A G >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function name_from_tag (frame) -- entry point from an {{#invoke:lang|name_from_tag|<IETF tag>|link=<yes>|template=<template name>}}
return _name_from_tag (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< _ T A G _ F R O M _ N A M E >--------------------------------------------------
Returns the IETF language tag associated with the language name. Spelling of language name must be correct
according to the spelling in the source tables. When a standard language name has a parenthetical disambiguator,
that disambiguator must be omitted (they are not present in the data name-to-tag tables).
Module entry point from another module.
]]
local function _tag_from_name (args) -- entry point from another module
local msg;
if args[1] and '' ~= args[1] then
local data = mw.loadData ('Module:Lang/tag from name'); -- get the reversed data tables TODO: change when going live
local lang = args[1]:lower(); -- allow any-case for the language name (speeling must till be correct)
local tag = data.rev_override_table[lang] or data.rev_lang_table[lang] or data.rev_lang_dep_table[lang]; -- get the code; look first in the override then in the standard
if tag then
return tag, true; -- language name found so return tag and done; second return used by is_lang_name()
else
msg = substitute (cfg.tag_from_name_t.lang_not_found, {args[1]}); -- language name not found, error message
end
else
msg = cfg.tag_from_name_t.missing_lang_name; -- language name not found, error message
end
local template = '';
if args.template and '' ~= args.template then
template = table.concat ({'{{', args['template'], '}}: '}); -- make template name (if provided by the template)
end
return make_error_span (template, msg);
end
--[[--------------------------< T A G _ F R O M _ N A M E >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function tag_from_name (frame) -- entry point from an {{#invoke:lang|tag_from_name|<language name>|link=<yes>|template=<template name>}}
local result, _ = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by is_lang_name()
return result;
end
--[[--------------------------< I S _ L A N G _ N A M E >------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_lang_name (frame)
local _, result = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by tag_from_name()
return result and true or nil;
end
--[[--------------------------< _ X L I T >--------------------------------------------------------------------
Module entry point from another module.
]]
local function _xlit (args)
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local language_name; -- language name that matches language code; used for tool tip
local translit; -- transliterated text to display
local script; -- IANA script
local msg; -- for when called functions return an error message
local template = args.template or cfg.templates_t.transliteration;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
if is_set (args[3]) then -- [3] set when {{transliteration|code|standard|text}}
args.text = args[3]; -- get the transliterated text
args.translit_std = args[2] and args[2]:lower(); -- get the standard; lower case for table indexing
if not title_table[args.translit_std] then
return make_error_msg (substitute (cfg.transl_t.unrecog_xlit_std, {args.translit_std}), args, template);
end
else
if is_set (args[2]) then -- [2] set when {{transliteration|code|text}}
args.text = args[2]; -- get the transliterated text
else
if args[1] and (args[1]:match ('^%a%a%a?%a?$') or -- args[2] missing; is args[1] a language or script tag or is it the transliterated text?
args[1]:match ('^%a%a%a?%-x%-')) then -- or is args[1] a private-use tag
return make_error_msg (cfg.transl_t.no_text, args, template); -- args[1] is a code so we're missing text
else
args.text = args[1]; -- args[1] is not a code so we're missing that; assign args.text for error message
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template);
end
end
end
if is_set (args[1]) then -- IANA language code used for HTML lang= attribute; or ISO 15924 script code
if args[1]:match ('^%a%a%a?%a?$') or args[1]:match ('^%a%a%a?%-x%-') then -- args[1] has correct form?
args.code = args[1]:lower(); -- use the language/script code; only (2, 3, or 4 alpha characters) or private-use; lower case because table indexes are lower case
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args[1]}), args, template); -- invalid language / script code
end
else
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template); -- missing language / script code so quit
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, args.code); -- is latn text? strip accept-as-written markup
if not is_latn_text then -- when text is not latn
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template); -- abandon with error message
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if 'italic' == args.italic then -- 'italic' when |italic=yes; because that is same as absent or not set and |italic=default
args.italic = nil; -- set to nil;
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if override_table[args.code] then -- is code a language code defined in the override table?
language_name = override_table[args.code];
args.code = args.code:match ('^%a%a%a?'); -- if private use, strip all but language subtag
elseif lang_table[args.code] then -- is code a language code defined in the standard language code tables?
language_name = lang_table[args.code];
elseif lang_dep_table[args.code] then -- is code a language code defined in the deprecated language code tables?
language_name = lang_dep_table[args.code];
elseif script_table[args.code] then -- if here, code is not a language code; is it a script code?
language_name = script_table[args.code];
script = args.code; -- code was an ISO 15924 script so use that instead
args.code = ''; -- unset because not a language code
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args.code}), args, template); -- invalid language / script code
end
-- here only when all parameters passed to make_translit() are valid
return make_translit (args.code, language_name, args.text, args.translit_std, script, args.italic, args.engvar);
end
--[[--------------------------< X L I T >----------------------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function xlit (frame)
return _xlit (getArgs(frame));
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Returns category name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _category_from_tag (args_t)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args_t[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args_t.link; -- make a boolean
local label = args_t.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local category_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args_t.template and table.concat ({'{{', args_t.template, '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
category_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = make_category (code, category_name, nil, true):gsub ('[%[%]]', '');
if link then
return table.concat ({'[[:', category_name, ']]'});
else
return category_name;
end
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function category_from_tag (frame) -- entry point from an {{#invoke:lang|category_from_tag|<IETF tag>|template=<template name>}}
return _category_from_tag (getArgs (frame)); -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
category_from_tag = category_from_tag, -- frame entry points when this module is #invoke:ed into templates/wikitext
lang = lang, -- entry point for {{lang}}
langx = langx, -- entry point for {{langx}}
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}}
lang_xx_italic = lang_xx_italic,
is_ietf_tag = is_ietf_tag,
is_ietf_tag_frame = is_ietf_tag_frame,
is_lang_name = is_lang_name,
tag_from_name = tag_from_name, -- returns IETF tag associated with language name
name_from_tag = name_from_tag, -- used for template documentation; possible use in ISO 639 name from code templates
xlit = xlit, -- entry point for {{transliteration}}
_category_from_tag = _category_from_tag, -- API entry points when this module is require()d into other modules
_lang = _lang,
_langx = _langx,
_lang_xx_inherit = _lang_xx_inherit,
_lang_xx_italic = _lang_xx_italic,
_is_ietf_tag = _is_ietf_tag,
get_ietf_parts = get_ietf_parts,
_tag_from_name = _tag_from_name,
_name_from_tag = _name_from_tag,
_xlit = _xlit,
_translation_make = translation_make,
};
df6lwn3npt578tp55101dhzcbix5ilt
392725
392724
2026-09-02T02:51:41Z
MacTire02
219
++
392725
Scribunto
text/plain
--[=[
Lua support for the {{lang}}, {{langx}}, {{lang-??}}, and {{transliteration}} templates and replacement of various supporting templates.
]=]
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local unicode = require ("Module:Unicode data"); -- for is_Latin() and is_rtl()
local yesno = require ('Module:Yesno');
local sandbox = (mw.getCurrentFrame():getTitle():match ('/sandbox') or ''); -- when called from a sandbox template or module load sandbox data and sandbox configuration
local lang_data = mw.loadData ('Module:Lang/data' .. sandbox); -- language name override and transliteration tool-tip tables
local lang_name_table = lang_data.lang_name_table; -- language codes, names, regions, scripts, suppressed scripts
local lang_table = lang_data.lang_name_table.lang;
local lang_dep_table = lang_data.lang_name_table.lang_dep;
local script_table = lang_data.lang_name_table.script;
local region_table = lang_data.lang_name_table.region;
local variant_table = lang_data.lang_name_table.variant;
local suppressed_table = lang_data.lang_name_table.suppressed;
local override_table = lang_data.override;
local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms'); -- ISO 639-2/639-2T code translation to 639-1 code
local cfg = mw.loadData ('Module:Lang/configuration' .. sandbox); -- for internationalization
local is_latn_data = mw.loadData ('Module:Lang/data/is latn data');
local sizeof_ranges_t = is_latn_data.sizeof_ranges_t;
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
local content_lang = mw.language.getContentLanguage();
local this_wiki_lang_tag = content_lang.code; -- get this wiki's language tag
local this_wiki_lang_dir = content_lang:getDir(); -- get this wiki's language direction
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic()
local maint_cats = {}; -- maintenance categories go here
local maint_msgs = {}; -- and their messages go here
--[[--------------------------< M A K E _ E R R O R _ S P A N >--------------------------------------------------
]]
local function make_error_span (template, msg)
return table.concat ({'<span style="color:var(--color-error,#d33)">', cfg.misc_text_t.error, ': ', template, msg, '</span>'})
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.
]]
local function substitute (message, data_t)
return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end
--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
Assembles an error message from template name, message text, help link, and error category.
]]
local function make_error_msg (msg, args_t, template)
local category;
local text; -- handle the oddity that is {{langx}}
if cfg.templates_t.langxx == template then
text = args_t.text or args_t[1]; -- for {{lang-xx}}
else
text = args_t.text or args_t[2]; -- for {{lang}}, {{langx}}, and {{transliteration}}
end
if cfg.templates_t.transliteration == template then
category = cfg.make_error_msg_t.xlit_err_cat;
else
category = cfg.make_error_msg_t.lang_err_cat;
end
local category_link = ((0 == namespace or 10 == namespace) and not args_t.nocat) and substitute ('[[Category:$1]]', {category}) or '';
return substitute ('[$1] <span style="color:var(--color-error,#d33)">$2: {{$3}}: $4 ([[:Category:$5|$6]])</span>$7', -- { prevents template name from being treated as a template call in certain situations
{
text or cfg.make_error_msg_t.undefined,
cfg.misc_text_t.error,
template,
msg,
category,
cfg.misc_text_t.help,
category_link
})
end
--[[--------------------------< P A R A M E T E R _ V A L I D A T E >------------------------------------------
]]
local function parameter_validate (args_t, template)
local err_msg = cfg.parameter_validate_t.invalid_param;
if cfg.templates_t.lang == template then -- for {{lang}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_t[param] and -- unique {{lang}} parameters
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langx == template then -- for {{langx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_langx_t[param] and -- unique {{langx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langxx == template then -- for {{lang-xx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_xx_t[param] and -- unique {{lang-xx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
end
end
--[[--------------------------< 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 V E R T _ I T A L I C S >-------------------------------------------------
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing
apostrophes are converted to their HTML numeric entity equivalent so that the new italic markup doesn't become
bold markup inadvertently.
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal,
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements.
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns.
This function expects that markup in args.text is complete and correct; if it is not, oddness may result.
]]
local function invert_italics (source)
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns
[""]="\'\'", -- empty string becomes italic markup
["\'\'"]="", -- italic markup becomes empty string
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold
};
local seg = {};
source = source:gsub ("%f[\']\'%f[^\']", '''); -- protect single quote marks from being interpreted as bold markup
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text'
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup
elseif '' ~= seg[1] then
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup
elseif '' ~= seg[3] then
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup
else
seg[2] = source -- when there is no markup
end
seg[1] = invert_pattern_table[seg[1]] or seg[1]; -- replace leading markup according to pattern table
seg[3] = invert_pattern_table[seg[3]] or seg[3]; -- replace leading markup according to pattern table
return table.concat (seg); -- put it all back together and done
end
--[[--------------------------< V A L I D A T E _ I T A L I C >------------------------------------------------
Validates |italic= or |italics= assigned values.
When |italic= is set and has an acceptable assigned value, return the matching CSS font-style property value or,
for the special case 'default', return nil.
When |italic= is not set, or has an unacceptable assigned value, return nil and a nil error message.
When both |italic= and |italics= are set, returns nil and a 'conflicting' error message.
The return value nil causes the calling lang, lang_xx, or xlit function to set args.italic according to the template's
defined default ('inherit' for {{lang}}, 'inherit' or 'italic' for {{lang-??}} depending on
the individual template's requirements, 'italic' for {{transliteration}}) or to the value appropriate to |script=, if set ({{lang}}
and {{lang-??}} only).
Accepted values and the values that this function returns are are:
nil - when |italic= absent or not set; returns nil
default - for completeness, should rarely if ever be used; returns nil
yes - force args.text to be rendered in italic font; returns 'italic'
no - force args.text to be rendered in normal font; returns 'normal'
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit'
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert'
]]
local function validate_italic (args)
local properties = {[cfg.keywords_t.affirmative] = 'italic', [cfg.keywords_t.negative] = 'normal', [cfg.keywords_t.unset] = 'inherit', [cfg.keywords_t.invert] = 'invert', [cfg.keywords_t.default] = nil};
local count = 0
for _, arg in pairs {'italic', 'italics', 'i'} do
if args[arg] then
count = count + 1
end
end
if count > 1 then -- return nil and an error message if more than one is set
return nil, cfg.validate_italic_t.multi_italic;
end
return properties[args.italic or args.italics or args.i], nil; -- return an appropriate value and a nil error message
end
--[=[--------------------------< V A L I D A T E _ C A T _ A R G S >----------------------------------------------------------
Default behavior of the {{lang}} and {{lang-??}} templates is to add categorization when the templates are used in main space.
This default functionality may be suppressed by setting |nocat=yes or |cat=no. This function selects one of these two parameters
to control categorization.
Because having two parameters with 'opposite' names and 'opposite' values is confusing, this function accepts only affirmative
values for |nocat= and only negative values for |cat=; in both cases the 'other' sense (and non-sense) is not accepted and the
parameter is treated as if it were not set in the template.
Sets args.nocat to true if categorization is to be turned off; to nil if the default behavior should apply.
Accepted values for |nocat= are the text strings:
'yes', 'y', 'true', 't', on, '1' -- [[Module:Yesno]] returns logical true for all of these; false or nil else
for |cat=
'no', 'n', 'false', 'f', 'off', '0' -- [[Module:Yesno]] returns logical false for all of these; true or nil else
]=]
local function validate_cat_args (args)
if not (args.nocat or args.cat) then -- both are nil, so categorize
return;
end
if false == yesno (args.cat) or true == yesno (args.nocat) then
args.nocat = true; -- set to true when args.nocat is affirmative; nil else (as if the parameter were not set in the template)
else -- args.nocat is the parameter actually used.
args.nocat = nil;
end
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
--[[--------------------------< F O R M A T _ I E T F _ T A G >------------------------------------------------
Prettify IETF tags to use recommended subtag formats:
code: lower case
script: sentence case
region: upper case
variant: lower case
private: lower case prefixed with -x-
]]
local function format_ietf_tag (code, script, region, variant, private)
local out = {};
if is_set (private) then
return table.concat ({code:lower(), 'x', private:lower()}, '-'); -- if private, all other tags ignored
end
table.insert (out, code:lower());
if is_set (script) then
script = script:lower():gsub ('^%a', string.upper);
table.insert (out, script);
end
if is_set (region) then
table.insert (out, region:upper());
end
if is_set (variant) then
table.insert (out, variant:lower());
end
return table.concat (out, '-');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
Extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character IANA language code
script subtag - four character IANA script code
region subtag - two-letter or three digit IANA region code
variant subtag - four digit or 5-8 alnum variant code; only one variant subtag supported
private subtag - x- followed by 1-8 alnum private code; only supported with the primary language tag
in any one of these forms
lang lang-variant
lang-script lang-script-variant
lang-region lang-region-variant
lang-script-region lang-script-region-variant
lang-x-private
each of lang, script, region, variant, and private, when used, must be valid.
Languages with both two- and three-character code synonyms are promoted to the two-character synonym because
the IANA registry file omits the synonymous three-character code; we cannot depend on browsers understanding
the synonymous three-character codes in the lang= attribute.
For {{lang-??}} templates, the parameters |script=, |region=, and |variant= are supported (not supported in {{lang}}
because those parameters are superfluous to the IETF subtags in |code=).
Returns six values; all lower case. Valid parts are returned as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil; the sixth returned item is an error message (if an error detected) or nil.
See http://www.rfc-editor.org/rfc/bcp/bcp47.txt section 2.1.
]]
local function get_ietf_parts (source, args_script, args_region, args_variant)
local code, script, region, variant, private; -- IETF tag parts
if not is_set (source) then
return nil, nil, nil, nil, nil, cfg.get_ietf_parts_t.missing_lang_tag;
end
local pattern = { -- table of tables holding acceptable IETF tag patterns and short names of the IETF part captured by the pattern
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits)
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits)
{'^(%a%a%a?)$'}, -- 18 - ll
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters)
}
local t = {}; -- table of captures; serves as a translator between captured IETF tag parts and named variables
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i])
if c1 then -- c1 always set on match
code = c1; -- first capture is always code
t = {
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table
};
script = t.s or ''; -- translate table contents to named variables;
region = t.r or ''; -- absent table entries are nil so set named IETF parts to empty string for concatenation
variant= t.v or '';
private = t.p or '';
break; -- and done
end
end
if not code then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_tag, {source}); -- don't know what we got but it is malformed
end
code = code:lower(); -- ensure that we use and return lower case version of this
if not (override_table[code] or lang_table[code] or synonym_table[code] or lang_dep_table[code]) then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_code, {code}); -- invalid language code, don't know about the others (don't care?)
end
if synonym_table[code] then -- if 639-2/639-2T code has a 639-1 synonym
table.insert (maint_cats, substitute (cfg.get_ietf_parts_t.maint_promo_cat, {code}));
table.insert (maint_msgs, substitute (cfg.get_ietf_parts_t.maint_promo_msg, {code, synonym_table[code]}));
code = synonym_table[code]; -- use the synonym
end
if is_set (script) then
if is_set (args_script) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_scr; -- both code with script and |script= not allowed
end
else
script = args_script or ''; -- use args.script if provided
end
if is_set (script) then
script = script:lower(); -- ensure that we use and return lower case version of this
if not script_table[script] then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_scr_code, {script, code}); -- language code OK, invalid script, don't know about the others (don't care?)
end
end
if suppressed_table[script] then -- ensure that code-script does not use a suppressed script
if in_array (code, suppressed_table[script]) then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.script_code, {script, code}); -- language code OK, script is suppressed for this code
end
end
if is_set (region) then
if is_set (args_region) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_reg; -- both code with region and |region= not allowed
end
else
region = args_region or ''; -- use args.region if provided
end
if is_set (region) then
region = region:lower(); -- ensure that we use and return lower case version of this
if not region_table[region] then
return code, script, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_reg_code, {region, code});
end
end
if is_set (variant) then
if is_set (args_variant) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_var; -- both code with variant and |variant= not allowed
end
else
variant = args_variant or ''; -- use args.variant if provided
end
if is_set (variant) then
variant = variant:lower(); -- ensure that we use and return lower case version of this
if not variant_table[variant] then -- make sure variant is valid
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var, {variant});
end -- does this duplicate/replace tests in lang() and lang_xx()?
if is_set (script) then -- if script set it must be part of the 'prefix'
if not in_array (table.concat ({code, '-', script}), variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_scr, {variant, code, script});
end
elseif is_set (region) then -- if region set, there are some prefixes that require lang code and region (en-CA-newfound)
if not in_array (code, variant_table[variant]['prefixes']) then -- first see if lang code is all that's required (en-oxendict though en-GB-oxendict is preferred)
if not in_array (table.concat ({code, '-', region}), variant_table[variant]['prefixes']) then -- now try for lang code and region (en-CA-newfound)
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_reg, {variant, code, region});
end
end
else -- cheap way to determine if there are prefixes; fonipa and others don't have prefixes; # operator always returns 0
if variant_table[variant]['prefixes'][1] and not in_array (code, variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code, {variant, code});
end
end
end
if is_set (private) then
private = private:lower(); -- ensure that we use and return lower case version of this
if not override_table[table.concat ({code, '-x-', private})] then -- make sure private tag is valid; note that index
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_pri, {private});
end
end
return code, script, region, variant, private, nil; -- return the good bits; make sure that msg is nil
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, 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 is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< D I V _ M A R K U P _ A D D >--------------------------------------------------
Adds <i> and </i> tags to list-item text or to implied <p>..</p> text. Mixed not supported.
]]
local function div_markup_add (text, style)
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text
if 'italic' == style then
return text:gsub ('(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item
else
return text;
end
end
if text:find ('\n+') then -- look for any number of \n characters in text
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics MediaWiki
if 'italic' == style then
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each implied p (two or more consecutive '\n\n' sequences)
else
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each implied p
text = text:gsub ('\n', ''); -- strip newline characters
end
end
return text;
end
--[[--------------------------< T I T L E _ W R A P P E R _ M A K E >------------------------------------------
Makes a <span title="<title text>"><content_text></span> or <div title="<title text>"><content_text></div> where
<title text> is in the tool-tip in the wiki's local language and <content_text> is non-local-language text in
HTML markup. This because the lang= attribute applies to the content of its enclosing tag.
<tag> holds a string 'div' or 'span' used to choose the correct wrapping tag.
]]
local function title_wrapper_make (title_text, content_text, tag)
local wrapper_t = {};
table.insert (wrapper_t, table.concat ({'<', tag})); -- open opening wrapper tag
table.insert (wrapper_t, ' title=\"'); -- begin title attribute
table.insert (wrapper_t, title_text); -- add <title_text>
table.insert (wrapper_t, '\">'); -- end title attribute and close opening wrapper tag
table.insert (wrapper_t, content_text); -- add <content_text>
table.insert (wrapper_t, table.concat ({'</', tag, '>'})); -- add closing wrapper tag
return table.concat (wrapper_t); -- make a big string and done
end
--[[--------------------------< M A K E _ T E X T _ H T M L >--------------------------------------------------
Add the HTML markup to text according to the type of content that it is: <span> or <i> tags for inline content or
<div> tags for block content
The lang= attribute also applies to the content of the tag where it is placed so this is wrong because 'Spanish
language text' is English:
<i lang="es" title="Spanish language text">casa</i>
should be:
<span title="Spanish language text"><i lang="es">casa</i></span>
or for <div>...</div>:
<div title="Spanish language text"><div lang="es"><spanish-language-text></div></div>
]]
local function make_text_html (code, text, tag, rtl, style, size, language)
local html_t = {};
local style_added = '';
local wrapper_tag = tag; -- <tag> gets modified so save a copy for use when/if we create a wrapper span or div
if text:match ('^%*') then
table.insert (html_t, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plain splat confuses MediaWiki
text = text:gsub ('^%*', ''); -- remove the splat from the text
end
if 'span' == tag then -- default HTML tag for inline content
if 'italic' == style then -- but if italic
tag = 'i'; -- change to <i> tags
end
else -- must be div so go
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i>
end
table.insert (html_t, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> HTML tag
code = code:gsub ('%-x%-.*', ''); -- strip private use subtag from code tag because meaningless outside of Wikipedia
table.insert (html_t, table.concat ({' lang="', code, '\"'})); -- add language attribute
if (rtl or unicode.is_rtl(text)) and ('ltr' == this_wiki_lang_dir) then -- text is right-to-left on a left-to-right wiki
table.insert (html_t, ' dir="rtl"'); -- add direction attribute for right-to-left languages
elseif not (rtl or unicode.is_rtl(text)) and ('rtl' == this_wiki_lang_dir) then -- text is left-to-right on a right-to-left wiki
table.insert (html_t, ' dir="ltr"'); -- add direction attribute for left-to-right languages
end
if 'normal' == style then -- when |italic=no
table.insert (html_t, ' style=\"font-style: normal;'); -- override external markup, if any
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
if is_set (size) then -- when |size=<something>
if is_set (style_added) then
table.insert (html_t, table.concat ({' font-size: ', size, ';'})); -- add when style attribute already inserted
else
table.insert (html_t, table.concat ({' style=\"font-size: ', size, ';'})); -- create style attribute
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
end
table.insert (html_t, table.concat ({style_added, '>'})); -- close the opening HTML tag
table.insert (html_t, text); -- insert the text
table.insert (html_t, table.concat ({'</', tag, '>'})); -- close the 'text' <i>, <span>, or <div> HTML tag
if is_set (language) then -- create a <title_text> string for the title= attribute in a wrapper span or div
local title_text;
if 'zxx' == code then -- special case for this tag 'no linguistic content'
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.zxx}); -- not a language so don't use 'language' in title text
elseif mw.ustring.find (language, 'languages', 1, true) then
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.collective}); -- for collective languages
else
title_text = substitute ('$1-$2', {language, cfg.make_text_html_t.individual}); -- for individual languages
end
return title_wrapper_make (title_text, table.concat (html_t), wrapper_tag);
else
return table.concat (html_t);
end
end
--[=[-------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
For individual language, <language>, returns:
[[Ronney:Artyn goaill stiagh teks ayns <language>]]
For English:
[[Ronney:Artyn goaill stiagh teks ayns Baarle]]
For ISO 639-2 collective languages (and for 639-1 bh):
[[Ronney:Artyn goaill stiagh teks ayns <language>]]
]=]
local function make_category (code, language_name, nocat, name_get)
if ((0 ~= namespace) or nocat) and not name_get then -- only categorize in article space
return ''; -- return empty string for concatenation
end
if mw.ustring.find (language_name, 'languages', 1, true) then
return substitute ('[[$1 $2]]', {cfg.make_category_t.collective_cat, language_name});
end
if this_wiki_lang_tag == code then
return substitute ('[[$1 $2 $3-$4]]', { -- unique category name for the local language
cfg.make_category_t.cat_prefix,
cfg.make_category_t.explicit_cat,
language_name,
cfg.make_category_t.cat_postfix,
});
else
return substitute ('[[$1 $2-$3]]', { -- category for individual languages
cfg.make_category_t.cat_prefix,
language_name,
cfg.make_category_t.cat_postfix,
});
end
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
Return translit <i lang=xx-Latn>...</i> where xx is the language code; else return empty string.
The value |script= is not used in {{transliteration}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transliteration}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
To avoid confusion, in this module and the templates that use it, the transliteration script parameter is renamed
to be |translit-script= (in this function, tscript).
This function is used by both lang_xx() and xlit()
lang_xx() always provides code, language_name, and translit; may provide tscript; never provides style
xlit() always provides language_name, translit, and one of code or tscript, never both; always provides style
For {{transliteration}}, style only applies when a language code is provided.
]]
local function make_translit (code, language_name, translit, std, tscript, style, engvar)
local title_t = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local title_text = ''; -- tool tip text for title= attribute
std = std and std:lower(); -- lower case for table indexing
if not is_set (std) and not is_set (tscript) then -- when neither standard nor script specified
title_text = language_name; -- write a generic tool tip
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', {title_text, cfg.misc_text_t.language}); -- skip this text (individual and macro languages only)
end
title_text = substitute ('$1 $2', {title_text, mw.ustring.lower (cfg.engvar_t[engvar]['romanisz_lc'])}); -- finish the tool tip; use romanization when neither script nor standard supplied
elseif is_set (std) and is_set (tscript) then -- when both are specified
if title_t[std] then -- and if standard is legitimate
if title_t[std][tscript] then -- and if script for that standard is legitimate
if script_table[tscript] then
title_text = substitute ('$1$2 ($3 $4) $5', { -- add the appropriate text to the tool tip
title_text,
title_t[std][tscript:lower()],
script_table[tscript],
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
return ''; -- invalid standard, setup for error message
end
elseif is_set (std) then -- translit-script not set, use language code
if not title_t[std] then return ''; end -- invalid standard, setup for error message
if title_t[std][code] then -- if language code is in the table (xlit may not provide a language code)
local fmt_str = '$1$2 ($3 $4) $5'; -- generic format string for tool tip
if language_name:match ('languages') then
fmt_str = '$1$2 ($3) $5'; -- format string for collective languages tool tip
end
title_text = substitute (fmt_str, { -- add the appropriate text to the tool tip
title_text,
title_t[std][code:lower()],
language_name,
cfg.misc_text_t.language,
cfg.make_translit_t.transliteration,
});
else -- code doesn't match
title_text = title_text .. title_t[std]['default']; -- so use the standard's default
end
else -- here if translit-script set but translit-std not set
if title_t['no_std'][tscript] then
title_text = title_text .. title_t['no_std'][tscript]; -- use translit-script if set
elseif title_t['no_std'][code] then
title_text = title_text .. title_t['no_std'][code]; -- use language code
else
if is_set (tscript) then
title_text = substitute ('$1$2-$3 $4', { -- write a script tool tip
title_text,
language_name,
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
elseif is_set (code) then
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end
local tag
if is_set (code) then -- when a language code is provided (always with {{lang-??}} templates, not always with {{transliteration}})
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span style="font-style: %s" lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ({{transliteration}} only)
end
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end
--[[--------------------------< V A L I D A T E _ T E X T >----------------------------------------------------
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an
error message. The tests are for empty or missing text and for improper or disallowed use of apostrophe markup.
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert.
]]
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end
local style = args.italic;
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end
--[[--------------------------< R E N D E R _ M A I N T >------------------------------------------------------
Render mainenance messages and categories.
]]
local function render_maint (nocat)
local maint = {};
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span class="lang-comment" style="font-style: normal; display: none; color: #33aa33; margin-left: 0.3em;">'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({'[[Category:', cat, ']]'})); -- format and add the categories
end
end
return table.concat (maint);
end
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.
]]
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------
Looks for a poem strip marker in text; returns true when found; false else.
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.
]]
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------
Inspects content of and selectively trims text. Returns text and the name of an appropriate HTML tag for text.
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.
]]
local function html_tag_select (text)
local tag;
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end
return text, tag;
end
--[[--------------------------< V A L I D A T E _ P R O T O >--------------------------------------------------
Validates value assigned to |proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.
]]
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end
--[[--------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------
Common function to return language name from the data set according to IETF tag.
Returns language name if found in data tables; nil else.
]]
local function language_name_get (ietf, code, cat)
ietf = ietf:lower(); -- ietf:lower() because format_ietf_tag() returns mixed case
local name; -- remains nil if not found
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to IANA active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the IANA deprecated tag/name table
name = lang_dep_table[code];
end
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end
return name; -- name from data tables or nil
end
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.
Returns an error message when mismatch detected; nil else.
]]
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower(); -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end
--[[--------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------
conducts a binary search of <ranges_t> for a sub-range that holds <target>.
returns boolean true if a sub-range holding <target> is found; boolean false else.
]]
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end
if flag then
break; -- here when we just evaluated the last range and <target> not found
end
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end
--[[--------------------------< I S _ L A T I N >--------------------------------------------------------------
compare <text> as codepoints to lists of known codepoints accepted as Latn script
returns boolean true and modified <text> when <text> is wrapped in accept-as-written markup
returns boolean true and <text> when codepoint is known
returns boolean false, <text>, non-Latn codepoint position in <text> (left to right), and the codepoint character
when codepoint is not known
TODO: when text has accept-as-written markup, return a non-boolean value to indicate that <text> is not wholly
latn script? Use that return value to create non-Latn HTML lang= attribute because <text> isn't really
latn so lang=und (undetermined)? or instead, omit the -Latn subtag? (without -Latn need to force |italic=yes)
]]
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end
--[[--------------------------< _ L A N G >--------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or cfg.templates_t.lang;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
validate_cat_args (args); -- determine if categorization should be suppressed
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code ({{{1}}} in {{lang}})
if msg then
return make_error_msg (msg, args, template);
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
if is_set (subtags.script) then -- if script set, override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if cfg.keywords_t.invert == args.italic and 'span' == tag then -- invert only supported for in-line content
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name));
table.insert (out, make_category (code, language_name, args.nocat));
table.insert (out, render_maint (args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function lang (frame)
local args_t = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text
valueFunc = function (key, value)
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space
return value; -- return untrimmed 'text'
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
args_t.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang|...}}
local msg = parameter_validate (args_t, cfg.templates_t.lang); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.lang); -- when template has unsupported params, abandon with error message
end
return _lang (args_t);
end
--[[--------------------------< T R A N S L A T I O N _ M A K E >----------------------------------------------
Stand-alone function to create literal translation of main text.
Also used by {{lang-x2}}.
]]
local function translation_make (args_t)
local translation_t = {', '}; -- initialize output
if 'none' ~= args_t.label then -- if we want a label
table.insert (translation_t, '<small>'); -- open the <small> HTML tag
if cfg.keywords_t.negative == args_t.link then
table.insert (translation_t, substitute ('<abbr title="$1">$2</abbr>', {cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr})); -- unlinked form
else
table.insert (translation_t, make_wikilink (cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr)); -- linked form
end
table.insert (translation_t, " </small>"); -- close the <small> HTML tag
end
table.insert (translation_t, table.concat ({ -- user styling spans match spand from {{gloss}}
'<span class="gloss-quot">\'</span>', -- user styling span for quote marks; use HTML entities to avoid wiki markup confusion
'<span class="gloss-text">', -- open user styling span for the translation
args_t.translation, -- the translation
'</span>', -- close user styling span for the translation
'<span class="gloss-quot">\'</span>' -- user styling span for quote marks
}));
return table.concat (translation_t); -- make a big string and done
end
--[[--------------------------< _ L A N G _ X X >--------------------------------------------------------------
For the {{lang-??}} templates, the only parameter required to be set in the template is the language code. All
other parameters can, usually should, be written in the template call. For {{lang-??}} templates for languages
that can have multiple writing systems, it may be appropriate to set |script= as well.
For each {{lang-??}} template choose the appropriate entry-point function so that this function knows the default
styling that should be applied to text.
For normal, upright style:
<includeonly>{{#invoke:lang|lang_xx_inherit|code=xx}}</includeonly>
For italic style:
<includeonly>{{#invoke:lang|lang_xx_italic|code=xx}}</includeonly>
All other parameters should be received from the template's frame (parent frame)
Supported parameters are:
|code = (required) the IANA language code
|script = IANA script code; especially for use with languages that use multiple writing systems
|region = IANA region code
|variant = IANA variant code
|text = (required) the displayed text in language specified by code
|link = boolean false ('no') does not link code-spcified language name to associated language article
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected
|cat = boolian false ('no') opposite form of |nocat=
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state
|lit = text that is a literal translation of text
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.')
any other text replaces language-name label - automatic wikilinking disabled
for those {{lang-??}} templates that support transliteration (those templates where |text= is not entirely latn script):
|translit = text that is a transliteration of text
|translit-std = the standard that applies to the transliteration
|translit-script = ISO 15924 script name; falls back to code
For {{lang-??}}, the positional parameters are:
{{{1}}} text
{{{2}}} transliterated text
{{{3}}} literal translation text
no other positional parameters are allowed
]]
local function _lang_xx (args, base_template) -- base_template will be either of 'langx' or 'lang-xx'
local out = {};
local language_name; -- used to make display text, article links
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, and variant
local code; -- the language code
local translit_script_name; -- name associated with IANA (ISO 15924) script code
local translit;
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or base_template;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
local text_idx = (cfg.templates_t.langx == base_template) and 2 or 1; -- for {{langx}} 'text' positional parameter is '2'
local translit_idx = (cfg.templates_t.langx == base_template) and 3 or 2;
local xlate_idx = (cfg.templates_t.langx == base_template) and 4 or 3;
if args[text_idx] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {text_idx, cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[text_idx] or args.text; -- prefer positional 'text' parameter
end
msg = validate_text (template, args); -- ensure that |text= is set, does not contain italic markup and is protected from improper bolding
if is_set (msg) then
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
if args[translit_idx] and args.translit then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {translit_idx, cfg.lang_t.conflict_n_param_types.translit}), args, template);
else
args.translit = args[translit_idx] or args.translit -- prefer positional 'translit' parameter
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if args[xlate_idx] and (args.translation or args.lit) then
return make_error_msg (substitute (cfg.lang_xx_t.conflict_n_lit, {xlate_idx}), args, template);
elseif args.translation and args.lit then
return make_error_msg (cfg.lang_xx_t.conflict_lit, args, template);
else
args.translation = args[xlate_idx] or args.translation or args.lit; -- prefer positional 'translation' parameter
end
if args.links and args.link then
return make_error_msg (cfg.lang_xx_t.conflict_link, args, template);
else
args.link = args.link or args.links; -- prefer args.link
end
validate_cat_args (args); -- determine if categorization should be suppressed
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code, args.script, args.region, args.variant); -- private omitted because private
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
if args.translit then
local latn, pos, char;
latn, args.translit, pos, char = is_latin (args.translit, (('' ~= subtags.private) and (code .. '-x-' .. subtags.private)) or code);
if not latn then
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template);
end
end
local is_latn_text, text, pos, char = is_latin (args.text, code); -- make a boolean
args.text = text; -- may have been modified (accept-as-written markup removed)
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if cfg.templates_t.langx == base_template then -- auto-italics for {{langx}} templates; adapted from {{lang}} (no support for poem tag)
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and is_latn_text) then -- text is not this wiki's language, no script specified and is wholly latn script (auto-italics)
args.italic = 'italic'; -- set font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
else -- {{lang-xx}} does not do auto italics; retained for those wikis that don't support {{langx}}
if nil == args.italic then -- args.italic controls
if is_set (subtags.script) then
if 'latn' == subtags.script then
args.italic = 'italic'; -- |script=Latn; set for font-style:italic
else
args.italic = initial_style_state; -- italic not set; script is not latn; set for font-style:<initial_style_state>
end
else
args.italic = initial_style_state; -- here when |italic= and |script= not set; set for font-style:<initial_style_state>
end
end
end
if is_set (subtags.script) then -- if script set override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {args.proto}), args, template);
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = language_name; -- category names retain IANA parenthetical diambiguators (if any)
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
if args.label then
if 'none' ~= args.label then
table.insert (out, table.concat ({args.label, ': '})); -- custom label
end
else
if cfg.keywords_t.negative == args.link then
table.insert (out, language_name); -- language name without wikilink
else
if mw.ustring.find (language_name, 'languages', 1, true) then
table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink
elseif lang_data.article_name[args.code:lower()] then -- is IETF tag in article name over ride?
table.insert (out, make_wikilink (lang_data.article_name[args.code:lower()], language_name)); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article override
table.insert (out, make_wikilink (lang_data.article_name[code], language_name)); -- language name with wikilink from override data
else
table.insert (out, make_wikilink (language_name, language_name)); -- Manx language name with wikilink
end
end
table.insert (out, ': '); -- separator
end
if cfg.keywords_t.invert == args.italic then
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, ('none' == args.label) and language_name or nil))
if is_set (args.translit) and not is_latn_text then -- transliteration; not supported when args.text is wholly latn text (this is an imperfect test)
table.insert (out, ', '); -- comma to separate text from translit
if 'none' ~= args.label then
table.insert (out, '<small>');
if script_table[args['translit-script']] then -- when |translit-script= is set, try to use the script's name
translit_script_name = script_table[args['translit-script']];
else
translit_script_name = language_name; -- fall back on language name
end
local translit_title_obj = mw.title.makeTitle (0, substitute ('$1 $2',{cfg.lang_xx_t.romanization, translit_script_name})); -- make a title object; no engvar, article titles use US spelling
if translit_title_obj.exists and (cfg.keywords_t.negative ~= args.link) then
table.insert (out, make_wikilink (substitute ('$1 $2', {cfg.lang_xx_t.romanization, translit_script_name or language_name}),
substitute ('$1', {cfg.engvar_t[args.engvar]['romanisz_pt']})) .. ':'); -- make a wikilink if there is an article to link to; engvar the display text
else
table.insert (out, substitute ('$1:', {cfg.engvar_t[args.engvar]['romanisz_pt']})); -- else plain text per engvar
end
table.insert (out, ' </small>'); -- close the small tag
end
translit = make_translit (args.code, language_name, args.translit, args['translit-std'], args['translit-script'], nil, args.engvar)
if is_set (translit) then
table.insert (out, translit);
else
return make_error_msg (substitute ('$1: $2', {cfg.lang_xx_t.invalid_xlit_std, args['translit-std'] or '[missing]'}), args, template);
end
elseif is_set (args.translit) and is_latn_text then -- when creating a transliteration of Latn script <text>
return make_error_msg (cfg.lang_xx_t.xlit_of_latn, args, template); -- emit error message and abandon
end
if is_set (args.translation) then -- translation (not supported in {{lang}})
table.insert (out, translation_make (args));
end
table.insert (out, make_category (code, category_name, args.nocat));
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X _ A R G S _ G E T >----------------------------------------------
Common function to get args table from {{lang-??}} templates.
Returns table of args.
Text positional parameters are not trimmed here but are selectively trimmed at html_tag_select().
]]
local function lang_xx_args_get (frame, base_template)
local args_t = getArgs(frame,
{
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}}
valueFunc = function (key, value)
if ((cfg.templates_t.langx == base_template) and 2 or 1) == key then -- the 'text' positional parameter; 1 for {{lang-??}}, 2 for {{langx}}; do not trim wite space
return value; -- return untrimmed 'text' positional parameter
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
return args_t;
end
--[[--------------------------< L A N G _ X X _ I T A L I C >--------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_italic(). Sets the initial style state to italic.
]]
local function lang_xx_italic (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_italic|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I T A L I C >------------------------------------------------
Entry point from another module. Sets the initial style state to italic.
]]
local function _lang_xx_italic (args)
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< L A N G _ X X _ I N H E R I T >------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_inherit(). Sets the initial style state to inherit.
]]
local function lang_xx_inherit (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_inherit|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I N H E R I T >----------------------------------------------
Entry point from another module. Sets the initial style state to inherit.
]]
local function _lang_xx_inherit (args)
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< _ L A N G X >------------------------------------------------------------------
Entry point from another module.
]]
local function _langx (args_t)
local langx_data = mw.loadData ('Module:Lang/langx'); -- get necessary data
local rtl_t = langx_data.rtl_t; -- get list of language tags for languages that are rendered right-to-left
local link_t = langx_data.link_t; -- get list of language tags for {{lang-??}} templates that set |link=<something>
local size_t = langx_data.size_t; -- get list of language tags for {{lang-??}} templates that set |size=<something>
local msg = parameter_validate (args_t, cfg.templates_t.langx);
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.langx);
end
args_t.code = args_t[1] or args_t.code; -- get the language tag; must be {{{1}}} or |code=
if not args_t.code then
return make_error_msg (cfg.get_ietf_parts_t.missing_lang_tag, args_t, cfg.templates_t.langx);
end
args_t.rtl = args_t.rtl or (rtl_t[args_t.code] and cfg.keywords_t.affirmative); -- prefer |rtl= in template call, use rtl_t else
args_t.link = args_t.link or link_t[args_t.code]; -- prefer |link= in template call, use link_t felse
args_t.size = args_t.size or size_t[args_t.code]; -- prefer |size= in template call, use size_t else
args_t[1] = nil; -- unset to mimic {{lang-??}} templates which set |code=xx
local lang_subtag = args_t.code; -- use only the base language subtag for unsupported tag test; some args_t.code are modified by |script= etc
return _lang_xx (args_t, cfg.templates_t.langx);
end
--[[--------------------------< L A N G X >--------------------------------------------------------------------
Entry point for {{langx}}.
this function calls _lang_xx() to render non-English text. The {{lang-??}} templates have three positional paramters
but {{langx}} has four:
| 1 | 2 | 3 | 4
{{lang-xx |<text> |<xlit> |<xlat> }}
{{langx |<tag> |<text> |<xlit> |<xlat> }}
The calls to lang_xx_args_get() and _lang_xx() use 'langx' as a flag for those functions to select the proper
positional parameters.
{{lang-??}} depends on the calling template to select 'inherit' or 'italic' to establish the default rendering.
{{langx}} can't do that. The initial version of {{langx}} relied on a list of language tags (inherit_t in ~/langx)
scraped from those {{lang-??}} templates that call lang_xx_inherit() to render text in upright font. langx() now
uses auto-italics code adapted from {{lang}} (doesn't support poem tags).
]]
local function langx (frame)
local args_t = lang_xx_args_get (frame, cfg.templates_t.langx); -- get the arguments; 'langx' is the <base_template> used to decide which positional param is 'text', 'translit', 'lit'
return _langx (args_t);
end
--[[--------------------------< _ I S _ I E T F _ T A G >------------------------------------------------------
Returns true when a language name associated with IETF language tag exists; nil else. IETF language tag must be valid.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _is_ietf_tag (tag) -- entry point when this module is require()d into another
local c, s, r, v, p, err; -- code, script, region, variant, private, error message
c, s, r, v, p, err = get_ietf_parts (tag); -- disassemble tag into constituent part and validate
return ((c and not err) and true) or nil; -- return true when code portion has a value without error message; nil else
end
--[[--------------------------< I S _ I E T F _ T A G >--------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_ietf_tag (frame)
return _is_ietf_tag (getArgs (frame)[1]); -- args[1] is the IETF language tag to be tested; also get parent frame
end
--[[--------------------------< I S _ I E T F _ T A G _ F R A M E >--------------------------------------------
Module entry point from an {{#invoke:}}; same as is_ietf_tag() except does not get parameters from the parent
(template) frame. This function not useful when called by {{lang|fn=is_ietf_tag_frame|<tag>}} because <tag>
is in the parent frame.
]]
local function is_ietf_tag_frame (frame)
return _is_ietf_tag (getArgs (frame, {frameOnly = true,})[1]); -- args[1] is the IETF language tag to be tested; do not get parent frame
end
--[[--------------------------< _ N A M E _ F R O M _ T A G >--------------------------------------------------
Returns language name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Set invoke's |link= parameter to yes to get wikilinked version of the language name.
Module entry point from another module.
]]
local function _name_from_tag (args)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args['link']; -- make a boolean
local label = args.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local language_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args['template'] and table.concat ({'{{', args['template'], '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
language_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if 'yes' ~= args.raw then
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
end
if link then -- when |link=yes, wikilink the language name
if mw.ustring.find (language_name, 'languages', 1, true) then
language_name = make_wikilink (language_name, label); -- collective language name uses simple wikilink
elseif lang_data.article_name[raw_code:lower()] then -- is IETF tag in article name override?
language_name = make_wikilink (lang_data.article_name[raw_code:lower()], label or language_name); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article name override?
language_name = make_wikilink (lang_data.article_name[code], label or language_name); -- language name with wikilink from override data
else
language_name = make_wikilink (language_name, label or language_name); -- Manx language name with wikilink
end
end
return language_name;
end
--[[--------------------------< N A M E _ F R O M _ T A G >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function name_from_tag (frame) -- entry point from an {{#invoke:lang|name_from_tag|<IETF tag>|link=<yes>|template=<template name>}}
return _name_from_tag (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< _ T A G _ F R O M _ N A M E >--------------------------------------------------
Returns the IETF language tag associated with the language name. Spelling of language name must be correct
according to the spelling in the source tables. When a standard language name has a parenthetical disambiguator,
that disambiguator must be omitted (they are not present in the data name-to-tag tables).
Module entry point from another module.
]]
local function _tag_from_name (args) -- entry point from another module
local msg;
if args[1] and '' ~= args[1] then
local data = mw.loadData ('Module:Lang/tag from name'); -- get the reversed data tables TODO: change when going live
local lang = args[1]:lower(); -- allow any-case for the language name (speeling must till be correct)
local tag = data.rev_override_table[lang] or data.rev_lang_table[lang] or data.rev_lang_dep_table[lang]; -- get the code; look first in the override then in the standard
if tag then
return tag, true; -- language name found so return tag and done; second return used by is_lang_name()
else
msg = substitute (cfg.tag_from_name_t.lang_not_found, {args[1]}); -- language name not found, error message
end
else
msg = cfg.tag_from_name_t.missing_lang_name; -- language name not found, error message
end
local template = '';
if args.template and '' ~= args.template then
template = table.concat ({'{{', args['template'], '}}: '}); -- make template name (if provided by the template)
end
return make_error_span (template, msg);
end
--[[--------------------------< T A G _ F R O M _ N A M E >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function tag_from_name (frame) -- entry point from an {{#invoke:lang|tag_from_name|<language name>|link=<yes>|template=<template name>}}
local result, _ = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by is_lang_name()
return result;
end
--[[--------------------------< I S _ L A N G _ N A M E >------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_lang_name (frame)
local _, result = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by tag_from_name()
return result and true or nil;
end
--[[--------------------------< _ X L I T >--------------------------------------------------------------------
Module entry point from another module.
]]
local function _xlit (args)
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local language_name; -- language name that matches language code; used for tool tip
local translit; -- transliterated text to display
local script; -- IANA script
local msg; -- for when called functions return an error message
local template = args.template or cfg.templates_t.transliteration;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
if is_set (args[3]) then -- [3] set when {{transliteration|code|standard|text}}
args.text = args[3]; -- get the transliterated text
args.translit_std = args[2] and args[2]:lower(); -- get the standard; lower case for table indexing
if not title_table[args.translit_std] then
return make_error_msg (substitute (cfg.transl_t.unrecog_xlit_std, {args.translit_std}), args, template);
end
else
if is_set (args[2]) then -- [2] set when {{transliteration|code|text}}
args.text = args[2]; -- get the transliterated text
else
if args[1] and (args[1]:match ('^%a%a%a?%a?$') or -- args[2] missing; is args[1] a language or script tag or is it the transliterated text?
args[1]:match ('^%a%a%a?%-x%-')) then -- or is args[1] a private-use tag
return make_error_msg (cfg.transl_t.no_text, args, template); -- args[1] is a code so we're missing text
else
args.text = args[1]; -- args[1] is not a code so we're missing that; assign args.text for error message
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template);
end
end
end
if is_set (args[1]) then -- IANA language code used for HTML lang= attribute; or ISO 15924 script code
if args[1]:match ('^%a%a%a?%a?$') or args[1]:match ('^%a%a%a?%-x%-') then -- args[1] has correct form?
args.code = args[1]:lower(); -- use the language/script code; only (2, 3, or 4 alpha characters) or private-use; lower case because table indexes are lower case
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args[1]}), args, template); -- invalid language / script code
end
else
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template); -- missing language / script code so quit
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, args.code); -- is latn text? strip accept-as-written markup
if not is_latn_text then -- when text is not latn
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template); -- abandon with error message
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if 'italic' == args.italic then -- 'italic' when |italic=yes; because that is same as absent or not set and |italic=default
args.italic = nil; -- set to nil;
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if override_table[args.code] then -- is code a language code defined in the override table?
language_name = override_table[args.code];
args.code = args.code:match ('^%a%a%a?'); -- if private use, strip all but language subtag
elseif lang_table[args.code] then -- is code a language code defined in the standard language code tables?
language_name = lang_table[args.code];
elseif lang_dep_table[args.code] then -- is code a language code defined in the deprecated language code tables?
language_name = lang_dep_table[args.code];
elseif script_table[args.code] then -- if here, code is not a language code; is it a script code?
language_name = script_table[args.code];
script = args.code; -- code was an ISO 15924 script so use that instead
args.code = ''; -- unset because not a language code
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args.code}), args, template); -- invalid language / script code
end
-- here only when all parameters passed to make_translit() are valid
return make_translit (args.code, language_name, args.text, args.translit_std, script, args.italic, args.engvar);
end
--[[--------------------------< X L I T >----------------------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function xlit (frame)
return _xlit (getArgs(frame));
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Returns category name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _category_from_tag (args_t)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args_t[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args_t.link; -- make a boolean
local label = args_t.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local category_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args_t.template and table.concat ({'{{', args_t.template, '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
category_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = make_category (code, category_name, nil, true):gsub ('[%[%]]', '');
if link then
return table.concat ({'[[:', category_name, ']]'});
else
return category_name;
end
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function category_from_tag (frame) -- entry point from an {{#invoke:lang|category_from_tag|<IETF tag>|template=<template name>}}
return _category_from_tag (getArgs (frame)); -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
category_from_tag = category_from_tag, -- frame entry points when this module is #invoke:ed into templates/wikitext
lang = lang, -- entry point for {{lang}}
langx = langx, -- entry point for {{langx}}
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}}
lang_xx_italic = lang_xx_italic,
is_ietf_tag = is_ietf_tag,
is_ietf_tag_frame = is_ietf_tag_frame,
is_lang_name = is_lang_name,
tag_from_name = tag_from_name, -- returns IETF tag associated with language name
name_from_tag = name_from_tag, -- used for template documentation; possible use in ISO 639 name from code templates
xlit = xlit, -- entry point for {{transliteration}}
_category_from_tag = _category_from_tag, -- API entry points when this module is require()d into other modules
_lang = _lang,
_langx = _langx,
_lang_xx_inherit = _lang_xx_inherit,
_lang_xx_italic = _lang_xx_italic,
_is_ietf_tag = _is_ietf_tag,
get_ietf_parts = get_ietf_parts,
_tag_from_name = _tag_from_name,
_name_from_tag = _name_from_tag,
_xlit = _xlit,
_translation_make = translation_make,
};
qfv7mr0m63iik6qgcc09s8d090yg50z
392728
392725
2026-09-02T03:05:24Z
MacTire02
219
++
392728
Scribunto
text/plain
--[=[
Lua support for the {{lang}}, {{langx}}, {{lang-??}}, and {{transliteration}} templates and replacement of various supporting templates.
]=]
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local unicode = require ("Module:Unicode data"); -- for is_Latin() and is_rtl()
local yesno = require ('Module:Yesno');
local sandbox = (mw.getCurrentFrame():getTitle():match ('/sandbox') or ''); -- when called from a sandbox template or module load sandbox data and sandbox configuration
local lang_data = mw.loadData ('Module:Lang/data' .. sandbox); -- language name override and transliteration tool-tip tables
local lang_name_table = lang_data.lang_name_table; -- language codes, names, regions, scripts, suppressed scripts
local lang_table = lang_data.lang_name_table.lang;
local lang_dep_table = lang_data.lang_name_table.lang_dep;
local script_table = lang_data.lang_name_table.script;
local region_table = lang_data.lang_name_table.region;
local variant_table = lang_data.lang_name_table.variant;
local suppressed_table = lang_data.lang_name_table.suppressed;
local override_table = lang_data.override;
local synonym_table = mw.loadData ('Module:Lang/ISO 639 synonyms'); -- ISO 639-2/639-2T code translation to 639-1 code
local cfg = mw.loadData ('Module:Lang/configuration' .. sandbox); -- for internationalization
local is_latn_data = mw.loadData ('Module:Lang/data/is latn data');
local sizeof_ranges_t = is_latn_data.sizeof_ranges_t;
local namespace = mw.title.getCurrentTitle().namespace; -- used for categorization
local content_lang = mw.language.getContentLanguage();
local this_wiki_lang_tag = content_lang.code; -- get this wiki's language tag
local this_wiki_lang_dir = content_lang:getDir(); -- get this wiki's language direction
local initial_style_state; -- set by lang_xx_normal() and lang_xx_italic()
local maint_cats = {}; -- maintenance categories go here
local maint_msgs = {}; -- and their messages go here
--[[--------------------------< M A K E _ E R R O R _ S P A N >--------------------------------------------------
]]
local function make_error_span (template, msg)
return table.concat ({'<span style="color:var(--color-error,#d33)">', cfg.misc_text_t.error, ': ', template, msg, '</span>'})
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Substitutes $1, $2, etc in <message> with data from <data_t>. Returns plain-text substituted string when
<data_t> not nil; returns <message> else.
]]
local function substitute (message, data_t)
return data_t and mw.message.newRawMessage (message, data_t):plain() or message;
end
--[[--------------------------< M A K E _ E R R O R _ M S G >--------------------------------------------------
Assembles an error message from template name, message text, help link, and error category.
]]
local function make_error_msg (msg, args_t, template)
local category;
local text; -- handle the oddity that is {{langx}}
if cfg.templates_t.langxx == template then
text = args_t.text or args_t[1]; -- for {{lang-xx}}
else
text = args_t.text or args_t[2]; -- for {{lang}}, {{langx}}, and {{transliteration}}
end
if cfg.templates_t.transliteration == template then
category = cfg.make_error_msg_t.xlit_err_cat;
else
category = cfg.make_error_msg_t.lang_err_cat;
end
local category_link = ((0 == namespace or 10 == namespace) and not args_t.nocat) and substitute ('[[Category:$1]]', {category}) or '';
return substitute ('[$1] <span style="color:var(--color-error,#d33)">$2: {{$3}}: $4 ([[:Category:$5|$6]])</span>$7', -- { prevents template name from being treated as a template call in certain situations
{
text or cfg.make_error_msg_t.undefined,
cfg.misc_text_t.error,
template,
msg,
category,
cfg.misc_text_t.help,
category_link
})
end
--[[--------------------------< P A R A M E T E R _ V A L I D A T E >------------------------------------------
]]
local function parameter_validate (args_t, template)
local err_msg = cfg.parameter_validate_t.invalid_param;
if cfg.templates_t.lang == template then -- for {{lang}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_t[param] and -- unique {{lang}} parameters
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langx == template then -- for {{langx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_langx_t[param] and -- unique {{langx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
elseif cfg.templates_t.langxx == template then -- for {{lang-xx}}
for param, _ in pairs (args_t) do
if not cfg.known_params_t.params_lang_xx_t[param] and -- unique {{lang-xx}} parameters
not cfg.known_params_t.params_x_t[param] and -- common to {{langx}} and {{lang-xx}}
not cfg.known_params_t.common_params_all_t[param] then -- common to all
return substitute (err_msg, {param}); -- <param> not found so abandon
end
end
end
end
--[[--------------------------< 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 V E R T _ I T A L I C S >-------------------------------------------------
This function attempts to invert the italic markup a args.text by adding/removing leading/trailing italic markup
in args.text. Like |italic=unset, |italic=invert disables automatic italic markup. Individual leading/trailing
apostrophes are converted to their HTML numeric entity equivalent so that the new italic markup doesn't become
bold markup inadvertently.
Leading and trailing wiki markup is extracted from args.text into separate table elements. Addition, removal,
replacement of wiki markup is handled by a string.gsub() replacement table operating only on these separate elements.
In the string.gsub() matching pattern, '.*' matches empty string as well as the three expected wiki markup patterns.
This function expects that markup in args.text is complete and correct; if it is not, oddness may result.
]]
local function invert_italics (source)
local invert_pattern_table = { -- leading/trailing markup add/remove/replace patterns
[""]="\'\'", -- empty string becomes italic markup
["\'\'"]="", -- italic markup becomes empty string
["\'\'\'"]="\'\'\'\'\'", -- bold becomes bold italic
["\'\'\'\'\'"]="\'\'\'", -- bold italic become bold
};
local seg = {};
source = source:gsub ("%f[\']\'%f[^\']", '''); -- protect single quote marks from being interpreted as bold markup
seg[1] = source:match ('^(\'\'+%f[^\']).+') or ''; -- get leading markup, if any; ignore single quote
seg[3] = source:match ('.+(%f[\']\'\'+)$') or ''; -- get trailing markup, if any; ignore single quote
if '' ~= seg[1] and '' ~= seg[3] then -- extract the 'text'
seg[2] = source:match ('^\'\'+%f[^\'](.+)%f[\']\'\'+$') -- from between leading and trailing markup
elseif '' ~= seg[1] then
seg[2] = source:match ('^\'\'+%f[^\'](.+)') -- following leading markup
elseif '' ~= seg[3] then
seg[2] = source:match ('(.+)%f[\']\'\'+$') -- preceding trailing markup
else
seg[2] = source -- when there is no markup
end
seg[1] = invert_pattern_table[seg[1]] or seg[1]; -- replace leading markup according to pattern table
seg[3] = invert_pattern_table[seg[3]] or seg[3]; -- replace leading markup according to pattern table
return table.concat (seg); -- put it all back together and done
end
--[[--------------------------< V A L I D A T E _ I T A L I C >------------------------------------------------
Validates |italic= or |italics= assigned values.
When |italic= is set and has an acceptable assigned value, return the matching CSS font-style property value or,
for the special case 'default', return nil.
When |italic= is not set, or has an unacceptable assigned value, return nil and a nil error message.
When both |italic= and |italics= are set, returns nil and a 'conflicting' error message.
The return value nil causes the calling lang, lang_xx, or xlit function to set args.italic according to the template's
defined default ('inherit' for {{lang}}, 'inherit' or 'italic' for {{lang-??}} depending on
the individual template's requirements, 'italic' for {{transliteration}}) or to the value appropriate to |script=, if set ({{lang}}
and {{lang-??}} only).
Accepted values and the values that this function returns are are:
nil - when |italic= absent or not set; returns nil
default - for completeness, should rarely if ever be used; returns nil
yes - force args.text to be rendered in italic font; returns 'italic'
no - force args.text to be rendered in normal font; returns 'normal'
unset - disables font control so that font-style applied to text is dictated by markup inside or outside the template; returns 'inherit'
invert - disables font control so that font-style applied to text is dictated by markup outside or inverted inside the template; returns 'invert'
]]
local function validate_italic (args)
local properties = {[cfg.keywords_t.affirmative] = 'italic', [cfg.keywords_t.negative] = 'normal', [cfg.keywords_t.unset] = 'inherit', [cfg.keywords_t.invert] = 'invert', [cfg.keywords_t.default] = nil};
local count = 0
for _, arg in pairs {'italic', 'italics', 'i'} do
if args[arg] then
count = count + 1
end
end
if count > 1 then -- return nil and an error message if more than one is set
return nil, cfg.validate_italic_t.multi_italic;
end
return properties[args.italic or args.italics or args.i], nil; -- return an appropriate value and a nil error message
end
--[=[--------------------------< V A L I D A T E _ C A T _ A R G S >----------------------------------------------------------
Default behavior of the {{lang}} and {{lang-??}} templates is to add categorization when the templates are used in main space.
This default functionality may be suppressed by setting |nocat=yes or |cat=no. This function selects one of these two parameters
to control categorization.
Because having two parameters with 'opposite' names and 'opposite' values is confusing, this function accepts only affirmative
values for |nocat= and only negative values for |cat=; in both cases the 'other' sense (and non-sense) is not accepted and the
parameter is treated as if it were not set in the template.
Sets args.nocat to true if categorization is to be turned off; to nil if the default behavior should apply.
Accepted values for |nocat= are the text strings:
'yes', 'y', 'true', 't', on, '1' -- [[Module:Yesno]] returns logical true for all of these; false or nil else
for |cat=
'no', 'n', 'false', 'f', 'off', '0' -- [[Module:Yesno]] returns logical false for all of these; true or nil else
]=]
local function validate_cat_args (args)
if not (args.nocat or args.cat) then -- both are nil, so categorize
return;
end
if false == yesno (args.cat) or true == yesno (args.nocat) then
args.nocat = true; -- set to true when args.nocat is affirmative; nil else (as if the parameter were not set in the template)
else -- args.nocat is the parameter actually used.
args.nocat = nil;
end
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
--[[--------------------------< F O R M A T _ I E T F _ T A G >------------------------------------------------
Prettify IETF tags to use recommended subtag formats:
code: lower case
script: sentence case
region: upper case
variant: lower case
private: lower case prefixed with -x-
]]
local function format_ietf_tag (code, script, region, variant, private)
local out = {};
if is_set (private) then
return table.concat ({code:lower(), 'x', private:lower()}, '-'); -- if private, all other tags ignored
end
table.insert (out, code:lower());
if is_set (script) then
script = script:lower():gsub ('^%a', string.upper);
table.insert (out, script);
end
if is_set (region) then
table.insert (out, region:upper());
end
if is_set (variant) then
table.insert (out, variant:lower());
end
return table.concat (out, '-');
end
--[[--------------------------< G E T _ I E T F _ P A R T S >--------------------------------------------------
Extracts and returns IETF language tag parts:
primary language subtag (required) - 2 or 3 character IANA language code
script subtag - four character IANA script code
region subtag - two-letter or three digit IANA region code
variant subtag - four digit or 5-8 alnum variant code; only one variant subtag supported
private subtag - x- followed by 1-8 alnum private code; only supported with the primary language tag
in any one of these forms
lang lang-variant
lang-script lang-script-variant
lang-region lang-region-variant
lang-script-region lang-script-region-variant
lang-x-private
each of lang, script, region, variant, and private, when used, must be valid.
Languages with both two- and three-character code synonyms are promoted to the two-character synonym because
the IANA registry file omits the synonymous three-character code; we cannot depend on browsers understanding
the synonymous three-character codes in the lang= attribute.
For {{lang-??}} templates, the parameters |script=, |region=, and |variant= are supported (not supported in {{lang}}
because those parameters are superfluous to the IETF subtags in |code=).
Returns six values; all lower case. Valid parts are returned as themselves; omitted parts are returned as empty strings, invalid
parts are returned as nil; the sixth returned item is an error message (if an error detected) or nil.
See http://www.rfc-editor.org/rfc/bcp/bcp47.txt section 2.1.
]]
local function get_ietf_parts (source, args_script, args_region, args_variant)
local code, script, region, variant, private; -- IETF tag parts
if not is_set (source) then
return nil, nil, nil, nil, nil, cfg.get_ietf_parts_t.missing_lang_tag;
end
local pattern = { -- table of tables holding acceptable IETF tag patterns and short names of the IETF part captured by the pattern
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 1 - ll-Ssss-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%d%d%d%d)$', 's', 'r', 'v'}, -- 2 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 3 - ll-Ssss-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'r', 'v'}, -- 4 - ll-Ssss-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d%d)$', 's', 'v'}, -- 5 - ll-Ssss-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 's', 'v'}, -- 6 - ll-Ssss-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a)%-(%d%d%d%d)$', 'r', 'v'}, -- 7 - ll-RR-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%d%d%d)%-(%d%d%d%d)$', 'r', 'v'}, -- 8 - ll-DDD-variant (where region is 3 digits; variant is 4 digits)
{'^(%a%a%a?)%-(%a%a)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 9 - ll-RR-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d)%-(%w%w%w%w%w%w?%w?%w?)$', 'r', 'v'}, -- 10 - ll-DDD-variant (where region is 3 digits; variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%d%d%d%d)$', 'v'}, -- 11 - ll-variant (where variant is 4 digits)
{'^(%a%a%a?)%-(%w%w%w%w%w%w?%w?%w?)$', 'v'}, -- 12 - ll-variant (where variant is 5-8 alnum characters)
{'^(%a%a%a?)%-(%a%a%a%a)%-(%a%a)$', 's', 'r'}, -- 13 - ll-Ssss-RR
{'^(%a%a%a?)%-(%a%a%a%a)%-(%d%d%d)$', 's', 'r'}, -- 14 - ll-Ssss-DDD (region is 3 digits)
{'^(%a%a%a?)%-(%a%a%a%a)$', 's'}, -- 15 - ll-Ssss
{'^(%a%a%a?)%-(%a%a)$', 'r'}, -- 16 - ll-RR
{'^(%a%a%a?)%-(%d%d%d)$', 'r'}, -- 17 - ll-DDD (region is 3 digits)
{'^(%a%a%a?)$'}, -- 18 - ll
{'^(%a%a%a?)%-x%-(%w%w?%w?%w?%w?%w?%w?%w?)$', 'p'}, -- 19 - ll-x-pppppppp (private is 1-8 alnum characters)
}
local t = {}; -- table of captures; serves as a translator between captured IETF tag parts and named variables
for i, v in ipairs (pattern) do -- spin through the pattern table looking for a match
local c1, c2, c3, c4; -- captures in the 'pattern' from the pattern table go here
c1, c2, c3, c4 = source:match (pattern[i][1]); -- one or more captures set if source matches pattern[i])
if c1 then -- c1 always set on match
code = c1; -- first capture is always code
t = {
[pattern[i][2] or 'x'] = c2, -- fill the table of captures with the rest of the captures
[pattern[i][3] or 'x'] = c3, -- take index names from pattern table and assign sequential captures
[pattern[i][4] or 'x'] = c4, -- index name may be nil in pattern[i] table so "or 'x'" spoofs a name for this index in this table
};
script = t.s or ''; -- translate table contents to named variables;
region = t.r or ''; -- absent table entries are nil so set named IETF parts to empty string for concatenation
variant= t.v or '';
private = t.p or '';
break; -- and done
end
end
if not code then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_tag, {source}); -- don't know what we got but it is malformed
end
code = code:lower(); -- ensure that we use and return lower case version of this
if not (override_table[code] or lang_table[code] or synonym_table[code] or lang_dep_table[code]) then
return nil, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_code, {code}); -- invalid language code, don't know about the others (don't care?)
end
if synonym_table[code] then -- if 639-2/639-2T code has a 639-1 synonym
table.insert (maint_cats, substitute (cfg.get_ietf_parts_t.maint_promo_cat, {code}));
table.insert (maint_msgs, substitute (cfg.get_ietf_parts_t.maint_promo_msg, {code, synonym_table[code]}));
code = synonym_table[code]; -- use the synonym
end
if is_set (script) then
if is_set (args_script) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_scr; -- both code with script and |script= not allowed
end
else
script = args_script or ''; -- use args.script if provided
end
if is_set (script) then
script = script:lower(); -- ensure that we use and return lower case version of this
if not script_table[script] then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_scr_code, {script, code}); -- language code OK, invalid script, don't know about the others (don't care?)
end
end
if suppressed_table[script] then -- ensure that code-script does not use a suppressed script
if in_array (code, suppressed_table[script]) then
return code, nil, nil, nil, nil, substitute (cfg.get_ietf_parts_t.script_code, {script, code}); -- language code OK, script is suppressed for this code
end
end
if is_set (region) then
if is_set (args_region) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_reg; -- both code with region and |region= not allowed
end
else
region = args_region or ''; -- use args.region if provided
end
if is_set (region) then
region = region:lower(); -- ensure that we use and return lower case version of this
if not region_table[region] then
return code, script, nil, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_reg_code, {region, code});
end
end
if is_set (variant) then
if is_set (args_variant) then
return code, nil, nil, nil, nil, cfg.get_ietf_parts_t.redundant_var; -- both code with variant and |variant= not allowed
end
else
variant = args_variant or ''; -- use args.variant if provided
end
if is_set (variant) then
variant = variant:lower(); -- ensure that we use and return lower case version of this
if not variant_table[variant] then -- make sure variant is valid
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var, {variant});
end -- does this duplicate/replace tests in lang() and lang_xx()?
if is_set (script) then -- if script set it must be part of the 'prefix'
if not in_array (table.concat ({code, '-', script}), variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_scr, {variant, code, script});
end
elseif is_set (region) then -- if region set, there are some prefixes that require lang code and region (en-CA-newfound)
if not in_array (code, variant_table[variant]['prefixes']) then -- first see if lang code is all that's required (en-oxendict though en-GB-oxendict is preferred)
if not in_array (table.concat ({code, '-', region}), variant_table[variant]['prefixes']) then -- now try for lang code and region (en-CA-newfound)
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code_reg, {variant, code, region});
end
end
else -- cheap way to determine if there are prefixes; fonipa and others don't have prefixes; # operator always returns 0
if variant_table[variant]['prefixes'][1] and not in_array (code, variant_table[variant]['prefixes']) then
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_var_code, {variant, code});
end
end
end
if is_set (private) then
private = private:lower(); -- ensure that we use and return lower case version of this
if not override_table[table.concat ({code, '-x-', private})] then -- make sure private tag is valid; note that index
return code, script, region, nil, nil, substitute (cfg.get_ietf_parts_t.unrecog_pri, {private});
end
end
return code, script, region, variant, private, nil; -- return the good bits; make sure that msg is nil
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, 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 is_set (link) then
if is_set (display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
else
return '';
end
end
--[[--------------------------< D I V _ M A R K U P _ A D D >--------------------------------------------------
Adds <i> and </i> tags to list-item text or to implied <p>..</p> text. Mixed not supported.
]]
local function div_markup_add (text, style)
if text:find ('^\n[%*:;#]') then -- look for list markup; list markup must begin at start of text
if 'italic' == style then
return text:gsub ('(\n[%*:;#]+)([^\n]+)', '%1<i>%2</i>'); -- insert italic markup at each list item
else
return text;
end
end
if text:find ('\n+') then -- look for any number of \n characters in text
text = text:gsub ('([^\n])\n([^\n])', '%1 %2'); -- replace single newline characters with a space character which mimics MediaWiki
if 'italic' == style then
text = text:gsub('[^\n]+', '<p><i>%1</i></p>'); -- insert p and italic markup tags at each implied p (two or more consecutive '\n\n' sequences)
else
text = text:gsub ('[^\n]+', '<p>%1</p>'); -- insert p markup at each implied p
text = text:gsub ('\n', ''); -- strip newline characters
end
end
return text;
end
--[[--------------------------< T I T L E _ W R A P P E R _ M A K E >------------------------------------------
Makes a <span title="<title text>"><content_text></span> or <div title="<title text>"><content_text></div> where
<title text> is in the tool-tip in the wiki's local language and <content_text> is non-local-language text in
HTML markup. This because the lang= attribute applies to the content of its enclosing tag.
<tag> holds a string 'div' or 'span' used to choose the correct wrapping tag.
]]
local function title_wrapper_make (title_text, content_text, tag)
local wrapper_t = {};
table.insert (wrapper_t, table.concat ({'<', tag})); -- open opening wrapper tag
table.insert (wrapper_t, ' title=\"'); -- begin title attribute
table.insert (wrapper_t, title_text); -- add <title_text>
table.insert (wrapper_t, '\">'); -- end title attribute and close opening wrapper tag
table.insert (wrapper_t, content_text); -- add <content_text>
table.insert (wrapper_t, table.concat ({'</', tag, '>'})); -- add closing wrapper tag
return table.concat (wrapper_t); -- make a big string and done
end
--[[--------------------------< M A K E _ T E X T _ H T M L >--------------------------------------------------
Add the HTML markup to text according to the type of content that it is: <span> or <i> tags for inline content or
<div> tags for block content
The lang= attribute also applies to the content of the tag where it is placed so this is wrong because 'Spanish
language text' is English:
<i lang="es" title="Spanish language text">casa</i>
should be:
<span title="Spanish language text"><i lang="es">casa</i></span>
or for <div>...</div>:
<div title="Spanish language text"><div lang="es"><spanish-language-text></div></div>
]]
local function make_text_html (code, text, tag, rtl, style, size, language)
local html_t = {};
local style_added = '';
local wrapper_tag = tag; -- <tag> gets modified so save a copy for use when/if we create a wrapper span or div
if text:match ('^%*') then
table.insert (html_t, '*'); -- move proto language text prefix outside of italic markup if any; use numeric entity because plain splat confuses MediaWiki
text = text:gsub ('^%*', ''); -- remove the splat from the text
end
if 'span' == tag then -- default HTML tag for inline content
if 'italic' == style then -- but if italic
tag = 'i'; -- change to <i> tags
end
else -- must be div so go
text = div_markup_add (text, style); -- handle implied <p>, implied <p> with <i>, and list markup (*;:#) with <i>
end
table.insert (html_t, table.concat ({'<', tag})); -- open the <i>, <span>, or <div> HTML tag
code = code:gsub ('%-x%-.*', ''); -- strip private use subtag from code tag because meaningless outside of Wikipedia
table.insert (html_t, table.concat ({' lang="', code, '\"'})); -- add language attribute
if (rtl or unicode.is_rtl(text)) and ('ltr' == this_wiki_lang_dir) then -- text is right-to-left on a left-to-right wiki
table.insert (html_t, ' dir="rtl"'); -- add direction attribute for right-to-left languages
elseif not (rtl or unicode.is_rtl(text)) and ('rtl' == this_wiki_lang_dir) then -- text is left-to-right on a right-to-left wiki
table.insert (html_t, ' dir="ltr"'); -- add direction attribute for left-to-right languages
end
if 'normal' == style then -- when |italic=no
table.insert (html_t, ' style=\"font-style: normal;'); -- override external markup, if any
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
if is_set (size) then -- when |size=<something>
if is_set (style_added) then
table.insert (html_t, table.concat ({' font-size: ', size, ';'})); -- add when style attribute already inserted
else
table.insert (html_t, table.concat ({' style=\"font-size: ', size, ';'})); -- create style attribute
style_added = '\"'; -- remember that style attribute added and is not yet closed
end
end
table.insert (html_t, table.concat ({style_added, '>'})); -- close the opening HTML tag
table.insert (html_t, text); -- insert the text
table.insert (html_t, table.concat ({'</', tag, '>'})); -- close the 'text' <i>, <span>, or <div> HTML tag
if is_set (language) then -- create a <title_text> string for the title= attribute in a wrapper span or div
local title_text;
if 'zxx' == code then -- special case for this tag 'no linguistic content'
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.zxx}); -- not a language so don't use 'language' in title text
elseif mw.ustring.find (language, 'languages', 1, true) then
title_text = substitute ('$1 $2', {language, cfg.make_text_html_t.collective}); -- for collective languages
else
title_text = substitute ('$1-$2', {language, cfg.make_text_html_t.individual}); -- for individual languages
end
return title_wrapper_make (title_text, table.concat (html_t), wrapper_tag);
else
return table.concat (html_t);
end
end
--[=[-------------------------< M A K E _ C A T E G O R Y >----------------------------------------------------
For individual language, <language>, returns:
[[Ronney:Artyn goaill stiagh teks ayns <language>]]
For English:
[[Ronney:Artyn goaill stiagh teks ayns Baarle]]
For ISO 639-2 collective languages (and for 639-1 bh):
[[Ronney:Artyn goaill stiagh teks ayns <language>]]
]=]
local function make_category (code, language_name, nocat, name_get)
if ((0 ~= namespace) or nocat) and not name_get then -- only categorize in article space
return ''; -- return empty string for concatenation
end
if mw.ustring.find (language_name, 'languages', 1, true) then
return substitute ('[[$1 $2]]', {cfg.make_category_t.collective_cat, language_name});
end
if this_wiki_lang_tag == code then
return substitute ('[[$1 $2 $3-$4]]', { -- unique category name for the local language
cfg.make_category_t.cat_prefix,
cfg.make_category_t.explicit_cat,
language_name,
cfg.make_category_t.cat_postfix,
});
else
return substitute ('[[$1 $2$3]]', {
cfg.make_category_t.cat_prefix,
language_name,
cfg.make_category_t.cat_postfix
});
end
end
--[[--------------------------< M A K E _ T R A N S L I T >----------------------------------------------------
Return translit <i lang=xx-Latn>...</i> where xx is the language code; else return empty string.
The value |script= is not used in {{transliteration}} for this purpose; instead it uses |code. Because language scripts
are listed in the {{transliteration}} switches they are included in the data tables. The script parameter is introduced
at {{Language with name and transliteration}}. If |script= is set, this function uses it in preference to code.
To avoid confusion, in this module and the templates that use it, the transliteration script parameter is renamed
to be |translit-script= (in this function, tscript).
This function is used by both lang_xx() and xlit()
lang_xx() always provides code, language_name, and translit; may provide tscript; never provides style
xlit() always provides language_name, translit, and one of code or tscript, never both; always provides style
For {{transliteration}}, style only applies when a language code is provided.
]]
local function make_translit (code, language_name, translit, std, tscript, style, engvar)
local title_t = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local title_text = ''; -- tool tip text for title= attribute
std = std and std:lower(); -- lower case for table indexing
if not is_set (std) and not is_set (tscript) then -- when neither standard nor script specified
title_text = language_name; -- write a generic tool tip
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', {title_text, cfg.misc_text_t.language}); -- skip this text (individual and macro languages only)
end
title_text = substitute ('$1 $2', {title_text, mw.ustring.lower (cfg.engvar_t[engvar]['romanisz_lc'])}); -- finish the tool tip; use romanization when neither script nor standard supplied
elseif is_set (std) and is_set (tscript) then -- when both are specified
if title_t[std] then -- and if standard is legitimate
if title_t[std][tscript] then -- and if script for that standard is legitimate
if script_table[tscript] then
title_text = substitute ('$1$2 ($3 $4) $5', { -- add the appropriate text to the tool tip
title_text,
title_t[std][tscript:lower()],
script_table[tscript],
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
title_text = title_text .. title_t[std]['default']; -- use the default if script not in std table; TODO: maint cat? error message because script not found for this standard?
end
else
return ''; -- invalid standard, setup for error message
end
elseif is_set (std) then -- translit-script not set, use language code
if not title_t[std] then return ''; end -- invalid standard, setup for error message
if title_t[std][code] then -- if language code is in the table (xlit may not provide a language code)
local fmt_str = '$1$2 ($3 $4) $5'; -- generic format string for tool tip
if language_name:match ('languages') then
fmt_str = '$1$2 ($3) $5'; -- format string for collective languages tool tip
end
title_text = substitute (fmt_str, { -- add the appropriate text to the tool tip
title_text,
title_t[std][code:lower()],
language_name,
cfg.misc_text_t.language,
cfg.make_translit_t.transliteration,
});
else -- code doesn't match
title_text = title_text .. title_t[std]['default']; -- so use the standard's default
end
else -- here if translit-script set but translit-std not set
if title_t['no_std'][tscript] then
title_text = title_text .. title_t['no_std'][tscript]; -- use translit-script if set
elseif title_t['no_std'][code] then
title_text = title_text .. title_t['no_std'][code]; -- use language code
else
if is_set (tscript) then
title_text = substitute ('$1$2-$3 $4', { -- write a script tool tip
title_text,
language_name,
cfg.make_translit_t.script,
cfg.make_translit_t.transliteration,
});
elseif is_set (code) then
if not mw.ustring.find (language_name, 'languages', 1, true) then -- collective language names (plural 'languages' is part of the name)
title_text = substitute ('$1-$2', { -- skip this text (individual and macro languages only)
title_text,
cfg.misc_text_t.language,
});
end
title_text = substitute ('$1 $2', { -- finish the tool tip
title_text,
cfg.make_translit_t.transliteration,
});
else
title_text = substitute ('$1 $2', { -- generic tool tip (can we ever get here?)
title_text,
cfg.make_translit_t.transliteration,
});
end
end
end
local tag
if is_set (code) then -- when a language code is provided (always with {{lang-??}} templates, not always with {{transliteration}})
code = code:match ('^(%a%a%a?)'); -- strip all subtags leaving only the language subtag
if not style then -- nil for the default italic style
tag = '<i lang="%s-Latn">%s</i>'
else
tag = '<span style="font-style: %s" lang="%s-Latn">%s</span>' -- non-standard style, construct a span tag for it
tag = string.format(tag, style, "%s", "%s")
end
tag = string.format(tag, code, "%s")
else
tag = '<span>%s</span>' -- when no language code: no lang= attribute, not italic ({{transliteration}} only)
end
tag = string.format(tag, translit) -- add the translit text
if '' == title_text then -- when there is no need for a tool-tip
return tag; -- done
else
title_text = cfg.engvar_sel_t.gb == engvar and title_text:gsub ('([Rr]omani)z', '%1s') or title_text; -- gb eng when engvar specifies gb eng; us eng else
return title_wrapper_make (title_text, tag, 'span'); -- wrap with a tool-tip span and done
end
end
--[[--------------------------< V A L I D A T E _ T E X T >----------------------------------------------------
This function checks the content of args.text and returns empty string if nothing is amiss else it returns an
error message. The tests are for empty or missing text and for improper or disallowed use of apostrophe markup.
Italic rendering is controlled by the |italic= template parameter so italic markup should never appear in args.text
either as ''itself'' or as '''''bold italic''''' unless |italic=unset or |italic=invert.
]]
local function validate_text (template, args)
if not is_set (args.text) then
return make_error_msg (cfg.validate_text_t.no_text, args, template);
end
if args.text:find ("%f[\']\'\'\'\'%f[^\']") or args.text:find ("\'\'\'\'\'[\']+") then -- because we're looking, look for 4 appostrophes or 6+ appostrophes
return make_error_msg (cfg.validate_text_t.malformed_markup, args, template);
end
local style = args.italic;
if (cfg.keywords_t.unset ~= style) and (cfg.keywords_t.invert ~=style) then
if args.text:find ("%f[\']\'\'%f[^\']") or args.text:find ("%f[\']\'\'\'\'\'%f[^\']") then -- italic but not bold, or bold italic
return make_error_msg (cfg.validate_text_t.italic_markup, args, template);
end
end
end
--[[--------------------------< R E N D E R _ M A I N T >------------------------------------------------------
Render mainenance messages and categories.
]]
local function render_maint (nocat)
local maint = {};
if 0 < #maint_msgs then -- when there are maintenance messages
table.insert (maint, table.concat ({'<span class="lang-comment" style="font-style: normal; display: none; color: #33aa33; margin-left: 0.3em;">'})); -- opening <span> tag
for _, msg in ipairs (maint_msgs) do
table.insert (maint, table.concat ({msg, ' '})); -- add message strings
end
table.insert (maint, '</span>'); -- close the span
end
if (0 < #maint_cats) and (0 == namespace) and not nocat then -- when there are maintenance categories; article namespace only
for _, cat in ipairs (maint_cats) do
table.insert (maint, table.concat ({'[[Category:', cat, ']]'})); -- format and add the categories
end
end
return table.concat (maint);
end
--[[--------------------------< P R O T O _ P R E F I X >------------------------------------------------------
For proto languages, text is prefixed with a splat. We do that here as a flag for make_text_html() so that a splat
will be rendered outside of italic markup (if used). If the first character in text here is already a splat, we
do nothing.
proto_param is boolean or nil; true adds splat prefix regardless of language name; false removes and inhibits
regardless of language name; nil does nothing; presumes that the value in text is correct but removes extra splac.
]]
local function proto_prefix (text, language_name, proto_param)
if false == proto_param then -- when forced by |proto=no
return text:gsub ('^%**', ''); -- return text without splat prefix regardless of language name or existing splat prefix in text
elseif (language_name:find ('^Proto%-') or (true == proto_param)) then -- language is a proto or forced by |proto=yes
return text:gsub ('^%**', '*'); -- prefix proto-language text with a splat; also removes duplicate prefixing splats
end
return text:gsub ('^%*+', '*'); -- return text unmolested except multiple splats reduced to one splat
end
--[[--------------------------< H A S _ P O E M _ T A G >------------------------------------------------------
Looks for a poem strip marker in text; returns true when found; false else.
Auto-italic detection disabled when text has poem stripmarker because it is not possible for this code to know
the content that will replace the stripmarker.
]]
local function has_poem_tag (text)
return text:find ('\127[^\127]*UNIQ%-%-poem%-[%a%d]+%-QINU[^\127]*\127') and true or false;
end
--[[--------------------------< H T M L _ T A G _ S E L E C T >------------------------------------------------
Inspects content of and selectively trims text. Returns text and the name of an appropriate HTML tag for text.
If text contains:
\n\n text has implied <p>..</p> tags - trim leading and trailing whitespace and return
If text begins with list markup:
\n* unordered
\n; definition
\n: definition
\n# ordered
trim all leading whitespace except \n and trim all trailing whitespace
If text contains <poem>...</poem> stripmarker, return text unmodified and choose <div>..</div> tags because
the stripmarker is replaced with text wrapped in <div>..</div> tags.
If the text contains any actual <div>...</div> tags, then it's again returned unmodified and <div>...</div>
tags are used to wrap it, to prevent div/span inversion.
]]
local function html_tag_select (text)
local tag;
if has_poem_tag (text) then -- contains poem stripmarker (we can't know the content of that)
tag = 'div'; -- poem replacement is in div tags so lang must use div tags
elseif text:find ('<div') then -- reductive; if the text contains a div tag, we must use div tags
tag = 'div';
elseif mw.text.trim (text):find ('\n\n+') then -- contains implied p tags
text = mw.text.trim (text); -- trim leading and trailing whitespace characters
tag = 'div'; -- must be div because span may not contain p tags (added later by MediaWiki); poem replacement is in div tags
elseif text:find ('\n[%*:;%#]') then -- if text has list markup
text = text:gsub ('^[\t\r\f ]*', ''):gsub ('%s*$', ''); -- trim all whitespace except leading newline character '\n'
tag = 'div'; -- must be div because span may not contain ul, dd, dl, ol tags (added later by MediaWiki)
else
text = mw.text.trim (text); -- plain text
tag = 'span'; -- so span is fine
end
return text, tag;
end
--[[--------------------------< V A L I D A T E _ P R O T O >--------------------------------------------------
Validates value assigned to |proto=; permitted values are yes and no; yes returns as true, no returns as false,
empty string (or parameter omitted) returns as nil; any other value returns nil with <proto_param> as second
return value for use in error message.
]]
local function validate_proto (proto_param)
if cfg.keywords_t.affirmative == proto_param then
return true;
elseif cfg.keywords_t.negative == proto_param then
return false;
elseif is_set (proto_param) then
return nil, proto_param; -- |proto= something other than 'yes' or 'no'
else
return nil; -- missing or empty
end
end
--[[--------------------------< L A N G U A G E _ N A M E _ G E T >--------------------------------------------
Common function to return language name from the data set according to IETF tag.
Returns language name if found in data tables; nil else.
]]
local function language_name_get (ietf, code, cat)
ietf = ietf:lower(); -- ietf:lower() because format_ietf_tag() returns mixed case
local name; -- remains nil if not found
if override_table[ietf] then -- look for whole IETF tag in override table
name = override_table[ietf];
elseif override_table[code] then -- not there so try basic language tag
name = override_table[code];
elseif lang_table[code] then -- shift to IANA active tag/name table
name = lang_table[code];
elseif lang_dep_table[code] then -- try the IANA deprecated tag/name table
name = lang_dep_table[code];
end
if lang_dep_table[code] and cat then -- because deprecated code may have been overridden to en.wiki preferred name
table.insert (maint_cats, substitute (cfg.language_name_get_t.deprecated_cat, {code}));
table.insert (maint_msgs, substitute (cfg.language_name_get_t.deprecated_msg, {code}));
end
return name; -- name from data tables or nil
end
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T >----------------------------------
IETF script subtag should match the script of the <text>. This module does not attempt to know all scripts and
what they look like. It does know what Latn script looks like so when <text> is written using other than the Latn
script, the IETF script subtag, if present, should not be Latn.
Conversely, when <text> is written using the Latn script, the IETF script subtag, if present, should be Latn.
For the purposes of this test, Latf (Fraktur) and Latg (Gaelic) are considered to be equivalent to Latn because
unicode treats these two scripts as font-specific variants of Latn.
Returns an error message when mismatch detected; nil else.
]]
local function text_script_match_test (script, is_latn_text, pos, char)
local scripts_t = {['latf'] = true, ['latg'] = true, ['latn'] = true}; -- unicode 'latn' scripts; 'latf' and 'latg' are font variants so there are no Fraktur or Gaelic codepoints
if is_set (script) then -- don't bother with the rest of this if <script> is nil or empty string
script = script:lower(); -- lower case to index into <scripts_t>
if is_latn_text then -- when text is wholly Latn script
if not scripts_t[script] then -- but a non-Latn script is specified
return cfg.text_script_match_test_t.latn_txt_mismatch; -- emit an error message
end
else -- when text is not wholly Latn script
if scripts_t[script] then -- but a Latn script is specified
return substitute (cfg.text_script_match_test_t.latn_scr_mismatch, {pos, char}); -- emit an error message with position of first offending character
end
end
end
end
--[[--------------------------< B I N A R Y _ S E A R C H >---------------------------------------------------
conducts a binary search of <ranges_t> for a sub-range that holds <target>.
returns boolean true if a sub-range holding <target> is found; boolean false else.
]]
local function binary_search (target, ranges_t)
local idx_bot = 1; -- initialize to index of first key
local idx_top = sizeof_ranges_t; -- initialize to index of last key (number of keys)
if (target < ranges_t[idx_bot][1]) or (target > ranges_t[idx_top][2]) then -- invalid; target out of range
return; -- abandon
end
local idx_mid; -- calculated index of range midway between top index and bottom index
local flag = false; -- flag to tell us when we've evaluated last (highest) range in <ranges_t>
while 1 do
idx_mid = math.ceil ((idx_bot + idx_top) / 2); -- get the mid-point in the <ranges_t> sequence
if (target >= ranges_t[idx_mid][1]) and (target <= ranges_t[idx_mid][2]) then -- indexed range low value <= target <= indexed range high value
return true; -- we found the range that holds the <target> character; return true
elseif (target > ranges_t[idx_mid][2]) then -- is <target> > indexed range high value?
idx_bot = idx_mid; -- adjust <idx_bot> up
else -- here when <target> less than indexed range low value
idx_top = idx_mid - 1; -- adjust <idx_top> down
end
if flag then
break; -- here when we just evaluated the last range and <target> not found
end
if not flag and (idx_bot == idx_top) then -- set true just before we evaluate the last (highest) range in <ranges_t>
flag = true;
end
end
end
--[[--------------------------< I S _ L A T I N >--------------------------------------------------------------
compare <text> as codepoints to lists of known codepoints accepted as Latn script
returns boolean true and modified <text> when <text> is wrapped in accept-as-written markup
returns boolean true and <text> when codepoint is known
returns boolean false, <text>, non-Latn codepoint position in <text> (left to right), and the codepoint character
when codepoint is not known
TODO: when text has accept-as-written markup, return a non-boolean value to indicate that <text> is not wholly
latn script? Use that return value to create non-Latn HTML lang= attribute because <text> isn't really
latn so lang=und (undetermined)? or instead, omit the -Latn subtag? (without -Latn need to force |italic=yes)
]]
local function is_latin (text, tag)
local count;
text, count = text:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-as-written markup if present
if 0 ~= count then
return true, text; -- markup present so assume that <text> is Latn-script
end
local pos = 0; -- position counter for error messaging
for codepoint in mw.ustring.gcodepoint (text) do -- fetch each code point
pos = pos + 1; -- bump the position counter
if not is_latn_data.singles_t[codepoint] and -- codepoint not found in the singles list?
not binary_search (codepoint, is_latn_data.ranges_t) and -- codepoint not a member of a listed range?
not (tag and is_latn_data.specials_t[codepoint] and is_latn_data.specials_t[codepoint][tag]) then -- not a language-specific codepoint?
return false, text, pos, mw.ustring.char (codepoint); -- codepoint not known; return false with codepoint position and character representation
end
end
return true, text; -- is known; return <text>
end
--[[--------------------------< _ L A N G >--------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function _lang (args)
local out = {};
local language_name; -- used to make category names
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, variant, and private
local code; -- the language code
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or cfg.templates_t.lang;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
validate_cat_args (args); -- determine if categorization should be suppressed
if args[1] and args.code then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'1', cfg.lang_t.conflict_n_param_types.code}), args, template);
else
args.code = args[1] or args.code; -- prefer args.code
end
if args[2] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {'2', cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[2] or args.text; -- prefer args.text
end
msg = validate_text (template, args); -- ensure that |text= is set
if is_set (msg) then -- msg is an already-formatted error message
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {msg}), args, template);
end
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code); -- |script=, |region=, |variant= not supported because they should be part of args.code ({{{1}}} in {{lang}})
if msg then
return make_error_msg (msg, args, template);
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, code); -- make a boolean
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and not has_poem_tag (args.text) and is_latn_text) then -- text not this wiki's language, no script specified and not in poem markup but is wholly latn script (auto-italics)
args.italic = 'italic'; -- DEFAULT for {{lang}} templates is upright; but if latn script set for font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
if is_set (subtags.script) then -- if script set, override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if cfg.keywords_t.invert == args.italic and 'span' == tag then -- invert only supported for in-line content
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, language_name));
table.insert (out, make_category (code, language_name, args.nocat));
table.insert (out, render_maint (args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G >----------------------------------------------------------------------
Entry point for {{lang}}.
There should be no reason to set parameters in the {{lang}} {{#invoke:}}
<includeonly>{{#invoke:lang|lang}}</includeonly>
Parameters are received from the template's frame (parent frame).
]]
local function lang (frame)
local args_t = getArgs (frame, { -- this code so that we can detect and handle wiki list markup in text
valueFunc = function (key, value)
if 2 == key or 'text' == key then -- the 'text' parameter; do not trim wite space
return value; -- return untrimmed 'text'
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
args_t.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang|...}}
local msg = parameter_validate (args_t, cfg.templates_t.lang); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.lang); -- when template has unsupported params, abandon with error message
end
return _lang (args_t);
end
--[[--------------------------< T R A N S L A T I O N _ M A K E >----------------------------------------------
Stand-alone function to create literal translation of main text.
Also used by {{lang-x2}}.
]]
local function translation_make (args_t)
local translation_t = {', '}; -- initialize output
if 'none' ~= args_t.label then -- if we want a label
table.insert (translation_t, '<small>'); -- open the <small> HTML tag
if cfg.keywords_t.negative == args_t.link then
table.insert (translation_t, substitute ('<abbr title="$1">$2</abbr>', {cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr})); -- unlinked form
else
table.insert (translation_t, make_wikilink (cfg.translation_make_t.lit_xlation, cfg.translation_make_t.lit_abbr)); -- linked form
end
table.insert (translation_t, " </small>"); -- close the <small> HTML tag
end
table.insert (translation_t, table.concat ({ -- user styling spans match spand from {{gloss}}
'<span class="gloss-quot">\'</span>', -- user styling span for quote marks; use HTML entities to avoid wiki markup confusion
'<span class="gloss-text">', -- open user styling span for the translation
args_t.translation, -- the translation
'</span>', -- close user styling span for the translation
'<span class="gloss-quot">\'</span>' -- user styling span for quote marks
}));
return table.concat (translation_t); -- make a big string and done
end
--[[--------------------------< _ L A N G _ X X >--------------------------------------------------------------
For the {{lang-??}} templates, the only parameter required to be set in the template is the language code. All
other parameters can, usually should, be written in the template call. For {{lang-??}} templates for languages
that can have multiple writing systems, it may be appropriate to set |script= as well.
For each {{lang-??}} template choose the appropriate entry-point function so that this function knows the default
styling that should be applied to text.
For normal, upright style:
<includeonly>{{#invoke:lang|lang_xx_inherit|code=xx}}</includeonly>
For italic style:
<includeonly>{{#invoke:lang|lang_xx_italic|code=xx}}</includeonly>
All other parameters should be received from the template's frame (parent frame)
Supported parameters are:
|code = (required) the IANA language code
|script = IANA script code; especially for use with languages that use multiple writing systems
|region = IANA region code
|variant = IANA variant code
|text = (required) the displayed text in language specified by code
|link = boolean false ('no') does not link code-spcified language name to associated language article
|rtl = boolean true ('yes') identifies the language specified by code as a right-to-left language
|nocat = boolean true ('yes') inhibits normal categorization; error categories are not affected
|cat = boolian false ('no') opposite form of |nocat=
|italic = boolean true ('yes') renders displayed text in italic font; boolean false ('no') renders displayed text in normal font; not set renders according to initial_style_state
|lit = text that is a literal translation of text
|label = 'none' to suppress all labeling (language name, 'translit.', 'lit.')
any other text replaces language-name label - automatic wikilinking disabled
for those {{lang-??}} templates that support transliteration (those templates where |text= is not entirely latn script):
|translit = text that is a transliteration of text
|translit-std = the standard that applies to the transliteration
|translit-script = ISO 15924 script name; falls back to code
For {{lang-??}}, the positional parameters are:
{{{1}}} text
{{{2}}} transliterated text
{{{3}}} literal translation text
no other positional parameters are allowed
]]
local function _lang_xx (args, base_template) -- base_template will be either of 'langx' or 'lang-xx'
local out = {};
local language_name; -- used to make display text, article links
local category_name; -- same as language_name except that it retains any parenthetical disambiguators (if any) from the data set
local subtags = {}; -- IETF subtags script, region, and variant
local code; -- the language code
local translit_script_name; -- name associated with IANA (ISO 15924) script code
local translit;
local msg; -- for error messages
local tag = 'span'; -- initial value for make_text_html()
local template = args.template or base_template;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
local text_idx = (cfg.templates_t.langx == base_template) and 2 or 1; -- for {{langx}} 'text' positional parameter is '2'
local translit_idx = (cfg.templates_t.langx == base_template) and 3 or 2;
local xlate_idx = (cfg.templates_t.langx == base_template) and 4 or 3;
if args[text_idx] and args.text then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {text_idx, cfg.lang_t.conflict_n_param_types.text}), args, template);
else
args.text = args[text_idx] or args.text; -- prefer positional 'text' parameter
end
msg = validate_text (template, args); -- ensure that |text= is set, does not contain italic markup and is protected from improper bolding
if is_set (msg) then
return msg;
end
args.text, tag = html_tag_select (args.text); -- inspects text; returns appropriate HTML tag with text trimmed accordingly
if args[translit_idx] and args.translit then
return make_error_msg (substitute (cfg.lang_t.conflict_n_param, {translit_idx, cfg.lang_t.conflict_n_param_types.translit}), args, template);
else
args.translit = args[translit_idx] or args.translit -- prefer positional 'translit' parameter
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if args[xlate_idx] and (args.translation or args.lit) then
return make_error_msg (substitute (cfg.lang_xx_t.conflict_n_lit, {xlate_idx}), args, template);
elseif args.translation and args.lit then
return make_error_msg (cfg.lang_xx_t.conflict_lit, args, template);
else
args.translation = args[xlate_idx] or args.translation or args.lit; -- prefer positional 'translation' parameter
end
if args.links and args.link then
return make_error_msg (cfg.lang_xx_t.conflict_link, args, template);
else
args.link = args.link or args.links; -- prefer args.link
end
validate_cat_args (args); -- determine if categorization should be suppressed
args.rtl = args.rtl == cfg.keywords_t.affirmative; -- convert to boolean: 'yes' -> true, other values -> false
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (args.code, args.script, args.region, args.variant); -- private omitted because private
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
if args.translit then
local latn, pos, char;
latn, args.translit, pos, char = is_latin (args.translit, (('' ~= subtags.private) and (code .. '-x-' .. subtags.private)) or code);
if not latn then
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template);
end
end
local is_latn_text, text, pos, char = is_latin (args.text, code); -- make a boolean
args.text = text; -- may have been modified (accept-as-written markup removed)
msg = text_script_match_test (subtags.script, is_latn_text, pos, char)
if msg then -- if an error detected then there is an error message
return make_error_msg (msg, args, template);
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if cfg.templates_t.langx == base_template then -- auto-italics for {{langx}} templates; adapted from {{lang}} (no support for poem tag)
if nil == args.italic then -- nil when |italic= absent or not set or |italic=default; args.italic controls
if ('latn' == subtags.script) or -- script is latn
(this_wiki_lang_tag ~= code and not is_set (subtags.script) and is_latn_text) then -- text is not this wiki's language, no script specified and is wholly latn script (auto-italics)
args.italic = 'italic'; -- set font-style:italic
else
args.italic = 'inherit'; -- italic not set; script not latn; inherit current style
end
end
else -- {{lang-xx}} does not do auto italics; retained for those wikis that don't support {{langx}}
if nil == args.italic then -- args.italic controls
if is_set (subtags.script) then
if 'latn' == subtags.script then
args.italic = 'italic'; -- |script=Latn; set for font-style:italic
else
args.italic = initial_style_state; -- italic not set; script is not latn; set for font-style:<initial_style_state>
end
else
args.italic = initial_style_state; -- here when |italic= and |script= not set; set for font-style:<initial_style_state>
end
end
end
if is_set (subtags.script) then -- if script set override rtl setting
if in_array (subtags.script, lang_data.rtl_scripts) then
args.rtl = true; -- script is an rtl script
else
args.rtl = false; -- script is not an rtl script
end
end
args.proto, msg = validate_proto (args.proto); -- return boolean, or nil, or nil and error message flag
if msg then
return make_error_msg (substitute (cfg.lang_t.invalid_proto, {args.proto}), args, template);
end
args.code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles
language_name = language_name_get (args.code, code, true); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = language_name; -- category names retain IANA parenthetical diambiguators (if any)
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
if args.label then
if 'none' ~= args.label then
table.insert (out, table.concat ({args.label, ': '})); -- custom label
end
else
if cfg.keywords_t.negative == args.link then
table.insert (out, language_name); -- language name without wikilink
else
if mw.ustring.find (language_name, 'languages', 1, true) then
table.insert (out, make_wikilink (language_name)); -- collective language name uses simple wikilink
elseif lang_data.article_name[args.code:lower()] then -- is IETF tag in article name over ride?
table.insert (out, make_wikilink (lang_data.article_name[args.code:lower()], language_name)); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article override
table.insert (out, make_wikilink (lang_data.article_name[code], language_name)); -- language name with wikilink from override data
else
table.insert (out, make_wikilink (language_name, language_name)); -- Manx language name with wikilink
end
end
table.insert (out, ': '); -- separator
end
if cfg.keywords_t.invert == args.italic then
args.text = invert_italics (args.text)
end
args.text = proto_prefix (args.text, language_name, args.proto); -- prefix proto-language text with a splat
table.insert (out, make_text_html (args.code, args.text, tag, args.rtl, args.italic, args.size, ('none' == args.label) and language_name or nil))
if is_set (args.translit) and not is_latn_text then -- transliteration; not supported when args.text is wholly latn text (this is an imperfect test)
table.insert (out, ', '); -- comma to separate text from translit
if 'none' ~= args.label then
table.insert (out, '<small>');
if script_table[args['translit-script']] then -- when |translit-script= is set, try to use the script's name
translit_script_name = script_table[args['translit-script']];
else
translit_script_name = language_name; -- fall back on language name
end
local translit_title_obj = mw.title.makeTitle (0, substitute ('$1 $2',{cfg.lang_xx_t.romanization, translit_script_name})); -- make a title object; no engvar, article titles use US spelling
if translit_title_obj.exists and (cfg.keywords_t.negative ~= args.link) then
table.insert (out, make_wikilink (substitute ('$1 $2', {cfg.lang_xx_t.romanization, translit_script_name or language_name}),
substitute ('$1', {cfg.engvar_t[args.engvar]['romanisz_pt']})) .. ':'); -- make a wikilink if there is an article to link to; engvar the display text
else
table.insert (out, substitute ('$1:', {cfg.engvar_t[args.engvar]['romanisz_pt']})); -- else plain text per engvar
end
table.insert (out, ' </small>'); -- close the small tag
end
translit = make_translit (args.code, language_name, args.translit, args['translit-std'], args['translit-script'], nil, args.engvar)
if is_set (translit) then
table.insert (out, translit);
else
return make_error_msg (substitute ('$1: $2', {cfg.lang_xx_t.invalid_xlit_std, args['translit-std'] or '[missing]'}), args, template);
end
elseif is_set (args.translit) and is_latn_text then -- when creating a transliteration of Latn script <text>
return make_error_msg (cfg.lang_xx_t.xlit_of_latn, args, template); -- emit error message and abandon
end
if is_set (args.translation) then -- translation (not supported in {{lang}})
table.insert (out, translation_make (args));
end
table.insert (out, make_category (code, category_name, args.nocat));
table.insert (out, render_maint(args.nocat)); -- maintenance messages and categories
return table.concat (out); -- put it all together and done
end
--[[--------------------------< L A N G _ X X _ A R G S _ G E T >----------------------------------------------
Common function to get args table from {{lang-??}} templates.
Returns table of args.
Text positional parameters are not trimmed here but are selectively trimmed at html_tag_select().
]]
local function lang_xx_args_get (frame, base_template)
local args_t = getArgs(frame,
{
parentFirst= true, -- parameters in the template override parameters set in the {{#invoke:}}
valueFunc = function (key, value)
if ((cfg.templates_t.langx == base_template) and 2 or 1) == key then -- the 'text' positional parameter; 1 for {{lang-??}}, 2 for {{langx}}; do not trim wite space
return value; -- return untrimmed 'text' positional parameter
elseif value then -- all other values: if the value is not nil
value = mw.text.trim (value); -- trim whitespace
if '' ~= value then -- empty string when value was only whitespace
return value;
end
end
return nil; -- value was empty or contained only whitespace
end -- end of valueFunc
});
return args_t;
end
--[[--------------------------< L A N G _ X X _ I T A L I C >--------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_italic(). Sets the initial style state to italic.
]]
local function lang_xx_italic (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_italic|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I T A L I C >------------------------------------------------
Entry point from another module. Sets the initial style state to italic.
]]
local function _lang_xx_italic (args)
initial_style_state = 'italic';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< L A N G _ X X _ I N H E R I T >------------------------------------------------
Entry point for those {{lang-??}} templates that call lang_xx_inherit(). Sets the initial style state to inherit.
]]
local function lang_xx_inherit (frame)
local args = lang_xx_args_get (frame, cfg.templates_t.langxx);
args.fn = nil; -- unset because not supported but this function might have been called by {{lang|fn=lang_xx_inherit|...}}
local msg = parameter_validate (args, cfg.templates_t.langxx); -- verify that all supplied parameters are supported by {{lang-??}}
if msg then
return make_error_msg (msg, args, cfg.templates_t.langxx); -- when template has unsupported params, abandon with error message
end
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx) .. '[[Category:Pages using Lang-xx templates]]'; -- temporary category
end
--[[--------------------------< _ L A N G _ X X _ I N H E R I T >----------------------------------------------
Entry point from another module. Sets the initial style state to inherit.
]]
local function _lang_xx_inherit (args)
initial_style_state = 'inherit';
return _lang_xx (args, cfg.templates_t.langxx);
end
--[[--------------------------< _ L A N G X >------------------------------------------------------------------
Entry point from another module.
]]
local function _langx (args_t)
local langx_data = mw.loadData ('Module:Lang/langx'); -- get necessary data
local rtl_t = langx_data.rtl_t; -- get list of language tags for languages that are rendered right-to-left
local link_t = langx_data.link_t; -- get list of language tags for {{lang-??}} templates that set |link=<something>
local size_t = langx_data.size_t; -- get list of language tags for {{lang-??}} templates that set |size=<something>
local msg = parameter_validate (args_t, cfg.templates_t.langx);
if msg then
return make_error_msg (msg, args_t, cfg.templates_t.langx);
end
args_t.code = args_t[1] or args_t.code; -- get the language tag; must be {{{1}}} or |code=
if not args_t.code then
return make_error_msg (cfg.get_ietf_parts_t.missing_lang_tag, args_t, cfg.templates_t.langx);
end
args_t.rtl = args_t.rtl or (rtl_t[args_t.code] and cfg.keywords_t.affirmative); -- prefer |rtl= in template call, use rtl_t else
args_t.link = args_t.link or link_t[args_t.code]; -- prefer |link= in template call, use link_t felse
args_t.size = args_t.size or size_t[args_t.code]; -- prefer |size= in template call, use size_t else
args_t[1] = nil; -- unset to mimic {{lang-??}} templates which set |code=xx
local lang_subtag = args_t.code; -- use only the base language subtag for unsupported tag test; some args_t.code are modified by |script= etc
return _lang_xx (args_t, cfg.templates_t.langx);
end
--[[--------------------------< L A N G X >--------------------------------------------------------------------
Entry point for {{langx}}.
this function calls _lang_xx() to render non-English text. The {{lang-??}} templates have three positional paramters
but {{langx}} has four:
| 1 | 2 | 3 | 4
{{lang-xx |<text> |<xlit> |<xlat> }}
{{langx |<tag> |<text> |<xlit> |<xlat> }}
The calls to lang_xx_args_get() and _lang_xx() use 'langx' as a flag for those functions to select the proper
positional parameters.
{{lang-??}} depends on the calling template to select 'inherit' or 'italic' to establish the default rendering.
{{langx}} can't do that. The initial version of {{langx}} relied on a list of language tags (inherit_t in ~/langx)
scraped from those {{lang-??}} templates that call lang_xx_inherit() to render text in upright font. langx() now
uses auto-italics code adapted from {{lang}} (doesn't support poem tags).
]]
local function langx (frame)
local args_t = lang_xx_args_get (frame, cfg.templates_t.langx); -- get the arguments; 'langx' is the <base_template> used to decide which positional param is 'text', 'translit', 'lit'
return _langx (args_t);
end
--[[--------------------------< _ I S _ I E T F _ T A G >------------------------------------------------------
Returns true when a language name associated with IETF language tag exists; nil else. IETF language tag must be valid.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _is_ietf_tag (tag) -- entry point when this module is require()d into another
local c, s, r, v, p, err; -- code, script, region, variant, private, error message
c, s, r, v, p, err = get_ietf_parts (tag); -- disassemble tag into constituent part and validate
return ((c and not err) and true) or nil; -- return true when code portion has a value without error message; nil else
end
--[[--------------------------< I S _ I E T F _ T A G >--------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_ietf_tag (frame)
return _is_ietf_tag (getArgs (frame)[1]); -- args[1] is the IETF language tag to be tested; also get parent frame
end
--[[--------------------------< I S _ I E T F _ T A G _ F R A M E >--------------------------------------------
Module entry point from an {{#invoke:}}; same as is_ietf_tag() except does not get parameters from the parent
(template) frame. This function not useful when called by {{lang|fn=is_ietf_tag_frame|<tag>}} because <tag>
is in the parent frame.
]]
local function is_ietf_tag_frame (frame)
return _is_ietf_tag (getArgs (frame, {frameOnly = true,})[1]); -- args[1] is the IETF language tag to be tested; do not get parent frame
end
--[[--------------------------< _ N A M E _ F R O M _ T A G >--------------------------------------------------
Returns language name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Set invoke's |link= parameter to yes to get wikilinked version of the language name.
Module entry point from another module.
]]
local function _name_from_tag (args)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args['link']; -- make a boolean
local label = args.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local language_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args['template'] and table.concat ({'{{', args['template'], '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
language_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
if 'yes' ~= args.raw then
language_name = language_name:gsub ('%s+%b()', ''); -- remove IANA parenthetical disambiguators or qualifiers from names that have them
end
if link then -- when |link=yes, wikilink the language name
if mw.ustring.find (language_name, 'languages', 1, true) then
language_name = make_wikilink (language_name, label); -- collective language name uses simple wikilink
elseif lang_data.article_name[raw_code:lower()] then -- is IETF tag in article name override?
language_name = make_wikilink (lang_data.article_name[raw_code:lower()], label or language_name); -- language name with wikilink from override data
elseif lang_data.article_name[code] then -- is language tag in article name override?
language_name = make_wikilink (lang_data.article_name[code], label or language_name); -- language name with wikilink from override data
else
language_name = make_wikilink (language_name, label or language_name); -- Manx language name with wikilink
end
end
return language_name;
end
--[[--------------------------< N A M E _ F R O M _ T A G >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function name_from_tag (frame) -- entry point from an {{#invoke:lang|name_from_tag|<IETF tag>|link=<yes>|template=<template name>}}
return _name_from_tag (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< _ T A G _ F R O M _ N A M E >--------------------------------------------------
Returns the IETF language tag associated with the language name. Spelling of language name must be correct
according to the spelling in the source tables. When a standard language name has a parenthetical disambiguator,
that disambiguator must be omitted (they are not present in the data name-to-tag tables).
Module entry point from another module.
]]
local function _tag_from_name (args) -- entry point from another module
local msg;
if args[1] and '' ~= args[1] then
local data = mw.loadData ('Module:Lang/tag from name'); -- get the reversed data tables TODO: change when going live
local lang = args[1]:lower(); -- allow any-case for the language name (speeling must till be correct)
local tag = data.rev_override_table[lang] or data.rev_lang_table[lang] or data.rev_lang_dep_table[lang]; -- get the code; look first in the override then in the standard
if tag then
return tag, true; -- language name found so return tag and done; second return used by is_lang_name()
else
msg = substitute (cfg.tag_from_name_t.lang_not_found, {args[1]}); -- language name not found, error message
end
else
msg = cfg.tag_from_name_t.missing_lang_name; -- language name not found, error message
end
local template = '';
if args.template and '' ~= args.template then
template = table.concat ({'{{', args['template'], '}}: '}); -- make template name (if provided by the template)
end
return make_error_span (template, msg);
end
--[[--------------------------< T A G _ F R O M _ N A M E >----------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function tag_from_name (frame) -- entry point from an {{#invoke:lang|tag_from_name|<language name>|link=<yes>|template=<template name>}}
local result, _ = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by is_lang_name()
return result;
end
--[[--------------------------< I S _ L A N G _ N A M E >------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function is_lang_name (frame)
local _, result = _tag_from_name (getArgs(frame)) -- pass-on the args table, nothing else; getArgs() so we also get parent frame; supress second return used by tag_from_name()
return result and true or nil;
end
--[[--------------------------< _ X L I T >--------------------------------------------------------------------
Module entry point from another module.
]]
local function _xlit (args)
local title_table = lang_data.translit_title_table; -- table of transliteration standards and the language codes and scripts that apply to those standards
local language_name; -- language name that matches language code; used for tool tip
local translit; -- transliterated text to display
local script; -- IANA script
local msg; -- for when called functions return an error message
local template = args.template or cfg.templates_t.transliteration;
maint_cats = {}; -- initialize because when this module required into another module, these only declared once so only initialzed once
maint_msgs = {};
if is_set (args[3]) then -- [3] set when {{transliteration|code|standard|text}}
args.text = args[3]; -- get the transliterated text
args.translit_std = args[2] and args[2]:lower(); -- get the standard; lower case for table indexing
if not title_table[args.translit_std] then
return make_error_msg (substitute (cfg.transl_t.unrecog_xlit_std, {args.translit_std}), args, template);
end
else
if is_set (args[2]) then -- [2] set when {{transliteration|code|text}}
args.text = args[2]; -- get the transliterated text
else
if args[1] and (args[1]:match ('^%a%a%a?%a?$') or -- args[2] missing; is args[1] a language or script tag or is it the transliterated text?
args[1]:match ('^%a%a%a?%-x%-')) then -- or is args[1] a private-use tag
return make_error_msg (cfg.transl_t.no_text, args, template); -- args[1] is a code so we're missing text
else
args.text = args[1]; -- args[1] is not a code so we're missing that; assign args.text for error message
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template);
end
end
end
if is_set (args[1]) then -- IANA language code used for HTML lang= attribute; or ISO 15924 script code
if args[1]:match ('^%a%a%a?%a?$') or args[1]:match ('^%a%a%a?%-x%-') then -- args[1] has correct form?
args.code = args[1]:lower(); -- use the language/script code; only (2, 3, or 4 alpha characters) or private-use; lower case because table indexes are lower case
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args[1]}), args, template); -- invalid language / script code
end
else
return make_error_msg (cfg.transl_t.missing_lang_scr, args, template); -- missing language / script code so quit
end
local is_latn_text, pos, char;
is_latn_text, args.text, pos, char= is_latin (args.text, args.code); -- is latn text? strip accept-as-written markup
if not is_latn_text then -- when text is not latn
return make_error_msg (substitute (cfg.lang_xx_t.translit_nonlatn, {pos, char}), args, template); -- abandon with error message
end
args.italic, msg = validate_italic (args);
if msg then
return make_error_msg (msg, args, template);
end
if 'italic' == args.italic then -- 'italic' when |italic=yes; because that is same as absent or not set and |italic=default
args.italic = nil; -- set to nil;
end
args.engvar = cfg.engvar_sel_t[args.engvar] or cfg.default_engvar; -- |engvar= when valid; cfg.default_engvar else
if override_table[args.code] then -- is code a language code defined in the override table?
language_name = override_table[args.code];
args.code = args.code:match ('^%a%a%a?'); -- if private use, strip all but language subtag
elseif lang_table[args.code] then -- is code a language code defined in the standard language code tables?
language_name = lang_table[args.code];
elseif lang_dep_table[args.code] then -- is code a language code defined in the deprecated language code tables?
language_name = lang_dep_table[args.code];
elseif script_table[args.code] then -- if here, code is not a language code; is it a script code?
language_name = script_table[args.code];
script = args.code; -- code was an ISO 15924 script so use that instead
args.code = ''; -- unset because not a language code
else
return make_error_msg (substitute (cfg.transl_t.unrecog_lang_scr, {args.code}), args, template); -- invalid language / script code
end
-- here only when all parameters passed to make_translit() are valid
return make_translit (args.code, language_name, args.text, args.translit_std, script, args.italic, args.engvar);
end
--[[--------------------------< X L I T >----------------------------------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function xlit (frame)
return _xlit (getArgs(frame));
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Returns category name associated with IETF language tag if valid; error message else.
All code combinations supported by {{lang}} and the {{lang-??}} templates are supported by this function.
Module entry point from another module.
]]
local function _category_from_tag (args_t)
local subtags = {}; -- IETF subtags script, region, variant, and private
local raw_code = args_t[1]; -- save a copy of the input IETF subtag
local link = cfg.keywords_t.affirmative == args_t.link; -- make a boolean
local label = args_t.label;
local code; -- the language code
local msg; -- gets an error message if IETF language tag is malformed or invalid
local category_name = '';
code, subtags.script, subtags.region, subtags.variant, subtags.private, msg = get_ietf_parts (raw_code);
if msg then
local template = (args_t.template and table.concat ({'{{', args_t.template, '}}: '})) or ''; -- make template name (if provided by the template)
return make_error_span (template, msg);
end
raw_code = format_ietf_tag (code, subtags.script, subtags.region, subtags.variant, subtags.private); -- format to recommended subtag styles; private omitted because private
category_name = language_name_get (raw_code, code); -- get language name; try IETF tag first, then code w/o variant then code w/ variant
category_name = make_category (code, category_name, nil, true):gsub ('[%[%]]', '');
if link then
return table.concat ({'[[:', category_name, ']]'});
else
return category_name;
end
end
--[[--------------------------< C A T E G O R Y _ F R O M _ T A G >--------------------------------------------
Module entry point from an {{#invoke:}}.
]]
local function category_from_tag (frame) -- entry point from an {{#invoke:lang|category_from_tag|<IETF tag>|template=<template name>}}
return _category_from_tag (getArgs (frame)); -- pass-on the args table, nothing else; getArgs() so we also get parent frame
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
category_from_tag = category_from_tag, -- frame entry points when this module is #invoke:ed into templates/wikitext
lang = lang, -- entry point for {{lang}}
langx = langx, -- entry point for {{langx}}
lang_xx_inherit = lang_xx_inherit, -- entry points for {{lang-??}}
lang_xx_italic = lang_xx_italic,
is_ietf_tag = is_ietf_tag,
is_ietf_tag_frame = is_ietf_tag_frame,
is_lang_name = is_lang_name,
tag_from_name = tag_from_name, -- returns IETF tag associated with language name
name_from_tag = name_from_tag, -- used for template documentation; possible use in ISO 639 name from code templates
xlit = xlit, -- entry point for {{transliteration}}
_category_from_tag = _category_from_tag, -- API entry points when this module is require()d into other modules
_lang = _lang,
_langx = _langx,
_lang_xx_inherit = _lang_xx_inherit,
_lang_xx_italic = _lang_xx_italic,
_is_ietf_tag = _is_ietf_tag,
get_ietf_parts = get_ietf_parts,
_tag_from_name = _tag_from_name,
_name_from_tag = _name_from_tag,
_xlit = _xlit,
_translation_make = translation_make,
};
0tp4mdd1rlozmx6bbax1v2ibeakuanq
Module:Infobox mapframe
828
34022
392643
337450
2026-09-01T13:31:21Z
MacTire02
219
++
392643
Scribunto
text/plain
local mf = require('Module:Mapframe')
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local infoboxImage = require('Module:InfoboxImage').InfoboxImage
-- Defaults
local DEFAULT_FRAME_WIDTH = "270"
local DEFAULT_FRAME_HEIGHT = "200"
local DEFAULT_ZOOM = 10
local DEFAULT_GEOMASK_STROKE_WIDTH = "1"
local DEFAULT_GEOMASK_STROKE_COLOR = "#777777"
local DEFAULT_GEOMASK_FILL = "#888888"
local DEFAULT_GEOMASK_FILL_OPACITY = "0.25"
local DEFAULT_SHAPE_STROKE_WIDTH = "2"
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000"
local DEFAULT_SHAPE_FILL = "#606060"
local DEFAULT_SHAPE_FILL_OPACITY = "0.1"
local DEFAULT_LINE_STROKE_WIDTH = "5"
local DEFAULT_LINE_STROKE_COLOR = "#FF0000"
local DEFAULT_MARKER_COLOR = "#5E74F3"
local util = {}
function util.noop(info)
local DEFAULT_NOOP_OUTPUT = ""
-- uncomment this when debugging
-- DEFAULT_NOOP_OUTPUT = "debug: mapframe no-op: " .. info
-- mw.log(DEFAULT_NOOP_OUTPUT)
return DEFAULT_NOOP_OUTPUT
end
-- Trim whitespace from args, and remove empty args
function util.trimArgs(argsTable)
local cleanArgs = {}
for key, val in pairs(argsTable) do
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val ~= '' then
cleanArgs[key] = val
end
else
cleanArgs[key] = val
end
end
return cleanArgs
end
function util.getBestStatement(item_id, property_id)
if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then
return false
end
local statements = mw.wikibase.getBestStatements(item_id, property_id)
if not statements or #statements == 0 then
return false
end
local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )
if hasNoValue then
return false
end
return statements[1]
end
function util.hasWikidataProperty(item_id, property_id)
return util.getBestStatement(item_id, property_id) and true or false
end
function util.getStatementValue(statement)
return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil
end
function util.relatedEntity(item_id, property_id)
local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )
return value and value.id or false
end
function util.idType(id)
if not id then
return nil
elseif mw.ustring.match(id, "[Pp]%d+") then
return "property"
elseif mw.ustring.match(id, "[Qq]%d+") then
return "item"
else
return nil
end
end
function util.shouldAutoRun(frame)
-- Check if should be running
local pargs = frame.getParent(frame).args
local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or "")) -- true of false or nil
if pargs.coordinates == "{{{coordinates}}}" then explicitlyOn = false end
if type(pargs.coordinates) == 'string' and string.match(pargs.coordinates, 'coord.missing') then explicitlyOn = false end
local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false
return explicitlyOn or onByDefault
end
function util.argsFromAuto(frame)
-- Get args from the frame (invoke call) and the parent (template call).
-- Frame arguments are default values which are overridden by parent values
-- when both are present
local args = getArgs(frame, {parentFirst = true})
-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain
local fixedArgs = {}
for name, val in pairs(args) do
local fixedName = string.match(name, "^mapframe%-(.+)$" )
if fixedName then
fixedArgs[fixedName] = val
-- allow coord, coordinates, etc to be unprefixed
elseif name == "coordinates" or name == "coord" or name == "coordinate" and not fixedArgs.coord then
fixedArgs.coord = val
-- allow id, qid to be unprefixed, map to id (if not already present)
elseif name == "id" or name == "qid" and not fixedArgs.id then
fixedArgs.id = val
-- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]
elseif name == "captionstyle" and not fixedArgs.captionstyle then
fixedArgs.captionstyle = val
end
end
return fixedArgs
end
function util.parseCustomWikitext(customWikitext)
-- infoboxImage will format an image if given wikitext containing an
-- image, or else pass through the wikitext unmodified
return infoboxImage({
args = {
image = customWikitext
}
})
end
function util.trackAndWarn(trackingCat, warning)
local title = mw.title.getCurrentTitle()
local results = title and title.namespace == 0 and trackingCat and '[[Category:'..trackingCat..']]' or ''
if warning then
local warn = require('Module:If preview')._warning
results = results..warn({warning})
end
return results
end
function util.ternary(flag, other)
other = other or 'other'
flag = flag == 'none' and 'no' or flag
local yesNoOut = yesno(flag,other)
local yes = (yesNoOut == true)
local no = (yesNoOut == false)
return yes, no
end
local p = {}
p._caption = function(args)
if args.caption then
return args.caption
elseif args.switcher then
return util.noop("no caption or switcher")
end
local maskItem
local maskType = util.idType(args.geomask)
if maskType == 'item' then
maskItem = args.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)
end
local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )
return maskItemLabel and "Location in "..maskItemLabel
or util.noop("missing maskItemLabel with type " .. (maskType or "nil") .. " and item " .. (maskItem or "nil"))
end
--A list of types for objects that are too small to allow Kartographer to take over zoom
local tinyType = {
landmark=true,
railwaystation=true,
edu=true,
pass=true,
camera=true
}
p._main = function(_config)
-- accumulate tracking cats
local tracking = ''
-- `config` is the args passed to this module
local config = util.trimArgs(_config)
-- allow alias for config.coord
config.coord = config.coord or config.coordinates
-- Require wikidata item, or specified coords
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
if not(wikidataId) and not(config.coord) then
return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
end
-- Require coords (specified or from wikidata), so that map will be centred somewhere
-- (P625 = coordinate location)
local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, 'P625'))
if not (config.coord or wdCoordinates) then
return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
end
-- `args` is the arguments which will be passed to the mapframe module
local args = {}
-- Some defaults/overrides for infobox presentation
args.display = "inline"
args.frame = "yes"
args.plain = "yes"
args["frame-width"] = config["frame-width"] or config.width or DEFAULT_FRAME_WIDTH
args["frame-height"] = config["frame-height"] or config.height or DEFAULT_FRAME_HEIGHT
args["frame-align"] = "center"
args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"]
-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )
-- deprecated lat and long parameters
args["frame-lat"] = config["frame-lat"] or config["frame-latitude"]
args["frame-long"] = config["frame-long"] or config["frame-longitude"]
-- if zoom isn't specified from config, first check wikidata
local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, 'P6592'))
if not zoom then
-- Calculate zoom from length or area (converted to km or km2)
-- Zoom so that length or area is completely included in mapframe
local getZoom = require('Module:Infobox dim')._zoom
zoom = getZoom({length_km=config.length_km, length_mi=config.length_mi,
width_km=config.width_km, width_mi=config.width_mi,
area_km2=config.area_km2, area_mi2=config.area_mi2,
area_ha=config.area_ha, area_acre=config.area_acre,
type=config.type, population=config.population,
viewport_px=math.min(args["frame-width"],args["frame-height"]),
latitude=wdCoordinates and wdCoordinates.latitude})
end
args.zoom = zoom or DEFAULT_ZOOM
-- Use OSM relation ID if available; otherwise use geoshape if that is available
-- (geoshape is required for defunct entities, which are outside OSM's scope)
local hasOsmRelationId = util.hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local hasGeoshape = util.hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape
-- determine marker argument value, determine whether to show marker
local forcePoint, suppressPoint = util.ternary(config.point)
local forceMarker, suppressMarker = util.ternary(config.marker,true)
forcePoint = forcePoint or forceMarker
suppressPoint = suppressPoint or suppressMarker
local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)
-- wikidata = "yes" turns on both shape and line
-- wikidata = "no" turns off both shape and line
-- otherwise show both if wikidata provides geo
local forceWikidata, suppressWikidata = util.ternary(config.wikidata)
local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)
local showLine = showShape
-- determine shape parameter value, determine whether to show or suppress shape
-- also determine whether to invert shape
local forceShape, suppressShape = util.ternary(config.shape)
showShape = wikidataId and not suppressShape and (forceShape or showShape)
local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'
-- determine line parameter value, determine whether to show or suppress line
local forceLine, suppressLine = util.ternary(config.line)
showLine = wikidataId and not suppressLine and (forceLine or showLine)
local maskItem
-- Switcher
if config.switcher == "zooms" then
-- switching between zoom levels
local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)
local minZoom = 1 -- completely zoomed out
local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min
args.switch = "zoomed in, zoomed midway, zoomed out"
args.zoom = string.format("SWITCH:%d,%d,%d", maxZoom, midZoom, minZoom)
elseif config.switcher == "auto" then
-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,
-- that city's state, and that state's country
args.zoom = nil -- let kartographer determine the zoom
local maskLabels = {}
local maskItems = {}
local maskItemId = util.relatedEntity(wikidataId, "P276") or util.relatedEntity(wikidataId, "P131")
local maskLabel = mw.wikibase.getLabel(maskItemId)
while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do
table.insert(maskLabels, maskLabel)
table.insert(maskItems, maskItemId)
maskItemId = maskItemId and util.relatedEntity(maskItemId, "P131")
maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)
end
if #maskLabels > 1 then
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
elseif #maskLabels == 1 then
maskItem = maskItemId[1]
end
elseif config.switcher == "geomasks" and config.geomask then
-- switching between items in geomask parameter
args.zoom = nil -- let kartographer determine the zoom
local separator = (mw.ustring.find(config.geomask, "###", 0, true ) and "###") or
(mw.ustring.find(config.geomask, ";", 0, true ) and ";") or ","
local pattern = "%s*"..separator.."%s*"
local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, "SWITCH:", ""), pattern)
local maskLabels = {}
if #maskItems > 1 then
for i, item in ipairs(maskItems) do
table.insert(maskLabels, mw.wikibase.getLabel(item))
end
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
end
end
-- resolve geomask item id (if not using geomask switcher)
if not maskItem then --
local maskType = util.idType(config.geomask)
if maskType == 'item' then
maskItem = config.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(wikidataId, config.geomask)
end
end
-- if asking for shape or line from Wikidata
-- and if Wikidata actually has shape/line data (wikidataProvidesGeo=true)
-- and if no geomask
-- and if zoom not explicitly set
-- and if the object size inferred from its type is not too small
-- then let Kartographer "take over" zoom
if (showLine or showShape) and wikidataProvidesGeo and not maskItem
and not config.zoom and not (config.type and tinyType[config.type]) then
args.zoom = nil
end
if not maskItem and not showShape and not showLine and not showMarker then
return false, util.trackAndWarn('Pages using infobox mapframe with no geometry','No geometry specified for mapframe')
end
-- Keep track of arg numbering
local argNumber = ''
local function incrementArgNumber()
if argNumber == '' then
argNumber = 2
else
argNumber = argNumber + 1
end
end
-- Geomask
if maskItem then
args["type"..argNumber] = "shape-inverse"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = config["geomask-stroke-width"] or DEFAULT_GEOMASK_STROKE_WIDTH
args["stroke-color"..argNumber] = config["geomask-stroke-color"] or config["geomask-stroke-colour"] or DEFAULT_GEOMASK_STROKE_COLOR
args["fill"..argNumber] = config["geomask-fill"] or DEFAULT_GEOMASK_FILL
args["fill-opacity"..argNumber] = config["geomask-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
-- Let kartographer determine zoom and position, unless it is explicitly set in config
if not config.zoom and not config.switcher then
args.zoom = nil
args["frame-coord"] = nil
args["frame-lat"] = nil
args["frame-long"] = nil
local maskArea = util.getStatementValue( util.getBestStatement(maskItem, 'P2046') )
end
incrementArgNumber()
-- Hack to fix phab:T255932
if not args.zoom then
args["type"..argNumber] = "line"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = 0
incrementArgNumber()
end
end
-- Shape (or shape-inverse)
if showShape then
args["type"..argNumber] = shapeType
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["shape-stroke-width"] or config["stroke-width"] or DEFAULT_SHAPE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_SHAPE_STROKE_COLOR
args["fill"..argNumber] = config["shape-fill"] or DEFAULT_SHAPE_FILL
args["fill-opacity"..argNumber] = config["shape-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
incrementArgNumber()
end
-- Line
if showLine then
args["type"..argNumber] = "line"
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["line-stroke-width"] or config["stroke-width"] or DEFAULT_LINE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_LINE_STROKE_COLOR
incrementArgNumber()
end
-- Point marker
if showMarker then
args["type"..argNumber] = "point"
if config.id then args["id"..argNumber] = config.id end
if config.coord then args["coord"..argNumber] = config.coord end
if config.marker then args["marker"..argNumber] = config.marker end
args["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or DEFAULT_MARKER_COLOR
incrementArgNumber()
end
-- if Wikidata doesn't link to OSM and the map has no mask or point,
-- then center the map on the coordinates either from the infobox or from wikidata
if not maskItem and not showMarker and not wikidataProvidesGeo then
if config.coord then
args["frame-coord"] = args["frame-coord"] or config.coord
else
args["frame-lat"] = args["frame-lat"] or wdCoordinates.latitude
args["frame-long"] = args["frame-long"] or wdCoordinates.longitude
end
tracking = tracking..util.trackAndWarn('Pages using infobox mapframe with forced centering')
end
-- protect against nil frame arguments
args["frame-coord"] = args["frame-coord"] or ""
args["frame-lat"] = args["frame-lat"] or ""
args["frame-long"] = args["frame-long"] or ""
local mapframe = args.switch and mf.multi(args) or mf._main(args)
tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo
and util.trackAndWarn('Pages using infobox mapframe without shape links in Wikidata')
or '')
return true, mapframe.. tracking
end
-- Entry points
p.main = function(frame)
local parent = frame.getParent(frame)
local parentArgs = parent.args
local _, mapframe = p._main(parentArgs)
return frame:preprocess(mapframe)
end
p.auto = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("auto should not autorun")
end
local args = util.argsFromAuto(frame)
if args.custom then
return frame:preprocess(util.parseCustomWikitext(args.custom))
end
local _, mapframe = p._main(args)
return frame:preprocess(mapframe)
end
p.autocaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autocaption should not autorun")
end
local args = util.argsFromAuto(frame)
local caption = p._caption(args)
return caption
end
p.autoWithCaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autoWithCaption should not autorun")
end
local args = util.argsFromAuto(frame)
local wikitext
local caption
local ok
if args.custom then
ok = true
wikitext = util.parseCustomWikitext(args.custom)
else
ok, wikitext = p._main(args)
end
if not ok then return wikitext end
wikitext = frame:preprocess(wikitext)
caption = p._caption(args)
local data = mw.html.create():wikitext(wikitext)
data:tag('div')
:addClass('infobox-caption')
:cssText(args.captionstyle)
:wikitext(caption)
return tostring(data)
end
return p
j3zvodfabfeomv2k16qsy32uujgrrlu
392649
392643
2026-09-01T14:10:41Z
MacTire02
219
Gaelg
392649
Scribunto
text/plain
local mf = require('Module:Mapframe')
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local infoboxImage = require('Module:InfoboxImage').InfoboxImage
-- Defaults
local DEFAULT_FRAME_WIDTH = "270"
local DEFAULT_FRAME_HEIGHT = "200"
local DEFAULT_ZOOM = 10
local DEFAULT_GEOMASK_STROKE_WIDTH = "1"
local DEFAULT_GEOMASK_STROKE_COLOR = "#777777"
local DEFAULT_GEOMASK_FILL = "#888888"
local DEFAULT_GEOMASK_FILL_OPACITY = "0.25"
local DEFAULT_SHAPE_STROKE_WIDTH = "2"
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000"
local DEFAULT_SHAPE_FILL = "#606060"
local DEFAULT_SHAPE_FILL_OPACITY = "0.1"
local DEFAULT_LINE_STROKE_WIDTH = "5"
local DEFAULT_LINE_STROKE_COLOR = "#FF0000"
local DEFAULT_MARKER_COLOR = "#5E74F3"
local util = {}
function util.noop(info)
local DEFAULT_NOOP_OUTPUT = ""
-- uncomment this when debugging
-- DEFAULT_NOOP_OUTPUT = "debug: mapframe no-op: " .. info
-- mw.log(DEFAULT_NOOP_OUTPUT)
return DEFAULT_NOOP_OUTPUT
end
-- Trim whitespace from args, and remove empty args
function util.trimArgs(argsTable)
local cleanArgs = {}
for key, val in pairs(argsTable) do
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val ~= '' then
cleanArgs[key] = val
end
else
cleanArgs[key] = val
end
end
return cleanArgs
end
function util.getBestStatement(item_id, property_id)
if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then
return false
end
local statements = mw.wikibase.getBestStatements(item_id, property_id)
if not statements or #statements == 0 then
return false
end
local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )
if hasNoValue then
return false
end
return statements[1]
end
function util.hasWikidataProperty(item_id, property_id)
return util.getBestStatement(item_id, property_id) and true or false
end
function util.getStatementValue(statement)
return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil
end
function util.relatedEntity(item_id, property_id)
local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )
return value and value.id or false
end
function util.idType(id)
if not id then
return nil
elseif mw.ustring.match(id, "[Pp]%d+") then
return "property"
elseif mw.ustring.match(id, "[Qq]%d+") then
return "item"
else
return nil
end
end
function util.shouldAutoRun(frame)
-- Check if should be running
local pargs = frame.getParent(frame).args
local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or "")) -- true of false or nil
if pargs.coordinates == "{{{coordinates}}}" then explicitlyOn = false end
if type(pargs.coordinates) == 'string' and string.match(pargs.coordinates, 'coord.missing') then explicitlyOn = false end
local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false
return explicitlyOn or onByDefault
end
function util.argsFromAuto(frame)
-- Get args from the frame (invoke call) and the parent (template call).
-- Frame arguments are default values which are overridden by parent values
-- when both are present
local args = getArgs(frame, {parentFirst = true})
-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain
local fixedArgs = {}
for name, val in pairs(args) do
local fixedName = string.match(name, "^mapframe%-(.+)$" )
if fixedName then
fixedArgs[fixedName] = val
-- allow coord, coordinates, etc to be unprefixed
elseif name == "coordinates" or name == "coord" or name == "coordinate" and not fixedArgs.coord then
fixedArgs.coord = val
-- allow id, qid to be unprefixed, map to id (if not already present)
elseif name == "id" or name == "qid" and not fixedArgs.id then
fixedArgs.id = val
-- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]
elseif name == "captionstyle" and not fixedArgs.captionstyle then
fixedArgs.captionstyle = val
end
end
return fixedArgs
end
function util.parseCustomWikitext(customWikitext)
-- infoboxImage will format an image if given wikitext containing an
-- image, or else pass through the wikitext unmodified
return infoboxImage({
args = {
image = customWikitext
}
})
end
function util.trackAndWarn(trackingCat, warning)
local title = mw.title.getCurrentTitle()
local results = title and title.namespace == 0 and trackingCat and '[[Category:'..trackingCat..']]' or ''
if warning then
local warn = require('Module:If preview')._warning
results = results..warn({warning})
end
return results
end
function util.ternary(flag, other)
other = other or 'other'
flag = flag == 'none' and 'no' or flag
local yesNoOut = yesno(flag,other)
local yes = (yesNoOut == true)
local no = (yesNoOut == false)
return yes, no
end
local p = {}
p._caption = function(args)
if args.caption then
return args.caption
elseif args.switcher then
return util.noop("no caption or switcher")
end
local maskItem
local maskType = util.idType(args.geomask)
if maskType == 'item' then
maskItem = args.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)
end
local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )
return maskItemLabel and "Location in "..maskItemLabel
or util.noop("missing maskItemLabel with type " .. (maskType or "nil") .. " and item " .. (maskItem or "nil"))
end
--A list of types for objects that are too small to allow Kartographer to take over zoom
local tinyType = {
landmark=true,
railwaystation=true,
edu=true,
pass=true,
camera=true
}
p._main = function(_config)
-- accumulate tracking cats
local tracking = ''
-- `config` is the args passed to this module
local config = util.trimArgs(_config)
-- allow alias for config.coord
config.coord = config.coord or config.coordinates
-- Require wikidata item, or specified coords
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
if not(wikidataId) and not(config.coord) then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn co-ordnaidyn assaaragh')
end
-- Require coords (specified or from wikidata), so that map will be centred somewhere
-- (P625 = coordinate location)
local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, 'P625'))
if not (config.coord or wdCoordinates) then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn co-ordnaidyn assaaragh')
end
-- `args` is the arguments which will be passed to the mapframe module
local args = {}
-- Some defaults/overrides for infobox presentation
args.display = "inline"
args.frame = "yes"
args.plain = "yes"
args["frame-width"] = config["frame-width"] or config.width or DEFAULT_FRAME_WIDTH
args["frame-height"] = config["frame-height"] or config.height or DEFAULT_FRAME_HEIGHT
args["frame-align"] = "center"
args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"]
-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )
-- deprecated lat and long parameters
args["frame-lat"] = config["frame-lat"] or config["frame-latitude"]
args["frame-long"] = config["frame-long"] or config["frame-longitude"]
-- if zoom isn't specified from config, first check wikidata
local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, 'P6592'))
if not zoom then
-- Calculate zoom from length or area (converted to km or km2)
-- Zoom so that length or area is completely included in mapframe
local getZoom = require('Module:Infobox dim')._zoom
zoom = getZoom({length_km=config.length_km, length_mi=config.length_mi,
width_km=config.width_km, width_mi=config.width_mi,
area_km2=config.area_km2, area_mi2=config.area_mi2,
area_ha=config.area_ha, area_acre=config.area_acre,
type=config.type, population=config.population,
viewport_px=math.min(args["frame-width"],args["frame-height"]),
latitude=wdCoordinates and wdCoordinates.latitude})
end
args.zoom = zoom or DEFAULT_ZOOM
-- Use OSM relation ID if available; otherwise use geoshape if that is available
-- (geoshape is required for defunct entities, which are outside OSM's scope)
local hasOsmRelationId = util.hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local hasGeoshape = util.hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape
-- determine marker argument value, determine whether to show marker
local forcePoint, suppressPoint = util.ternary(config.point)
local forceMarker, suppressMarker = util.ternary(config.marker,true)
forcePoint = forcePoint or forceMarker
suppressPoint = suppressPoint or suppressMarker
local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)
-- wikidata = "yes" turns on both shape and line
-- wikidata = "no" turns off both shape and line
-- otherwise show both if wikidata provides geo
local forceWikidata, suppressWikidata = util.ternary(config.wikidata)
local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)
local showLine = showShape
-- determine shape parameter value, determine whether to show or suppress shape
-- also determine whether to invert shape
local forceShape, suppressShape = util.ternary(config.shape)
showShape = wikidataId and not suppressShape and (forceShape or showShape)
local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'
-- determine line parameter value, determine whether to show or suppress line
local forceLine, suppressLine = util.ternary(config.line)
showLine = wikidataId and not suppressLine and (forceLine or showLine)
local maskItem
-- Switcher
if config.switcher == "zooms" then
-- switching between zoom levels
local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)
local minZoom = 1 -- completely zoomed out
local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min
args.switch = "zoomed in, zoomed midway, zoomed out"
args.zoom = string.format("SWITCH:%d,%d,%d", maxZoom, midZoom, minZoom)
elseif config.switcher == "auto" then
-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,
-- that city's state, and that state's country
args.zoom = nil -- let kartographer determine the zoom
local maskLabels = {}
local maskItems = {}
local maskItemId = util.relatedEntity(wikidataId, "P276") or util.relatedEntity(wikidataId, "P131")
local maskLabel = mw.wikibase.getLabel(maskItemId)
while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do
table.insert(maskLabels, maskLabel)
table.insert(maskItems, maskItemId)
maskItemId = maskItemId and util.relatedEntity(maskItemId, "P131")
maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)
end
if #maskLabels > 1 then
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
elseif #maskLabels == 1 then
maskItem = maskItemId[1]
end
elseif config.switcher == "geomasks" and config.geomask then
-- switching between items in geomask parameter
args.zoom = nil -- let kartographer determine the zoom
local separator = (mw.ustring.find(config.geomask, "###", 0, true ) and "###") or
(mw.ustring.find(config.geomask, ";", 0, true ) and ";") or ","
local pattern = "%s*"..separator.."%s*"
local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, "SWITCH:", ""), pattern)
local maskLabels = {}
if #maskItems > 1 then
for i, item in ipairs(maskItems) do
table.insert(maskLabels, mw.wikibase.getLabel(item))
end
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
end
end
-- resolve geomask item id (if not using geomask switcher)
if not maskItem then --
local maskType = util.idType(config.geomask)
if maskType == 'item' then
maskItem = config.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(wikidataId, config.geomask)
end
end
-- if asking for shape or line from Wikidata
-- and if Wikidata actually has shape/line data (wikidataProvidesGeo=true)
-- and if no geomask
-- and if zoom not explicitly set
-- and if the object size inferred from its type is not too small
-- then let Kartographer "take over" zoom
if (showLine or showShape) and wikidataProvidesGeo and not maskItem
and not config.zoom and not (config.type and tinyType[config.type]) then
args.zoom = nil
end
if not maskItem and not showShape and not showLine and not showMarker then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn towse-oaylleeaght','Cha nel towse-oaylleeaght sonrit da mapframe')
end
-- Keep track of arg numbering
local argNumber = ''
local function incrementArgNumber()
if argNumber == '' then
argNumber = 2
else
argNumber = argNumber + 1
end
end
-- Geomask
if maskItem then
args["type"..argNumber] = "shape-inverse"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = config["geomask-stroke-width"] or DEFAULT_GEOMASK_STROKE_WIDTH
args["stroke-color"..argNumber] = config["geomask-stroke-color"] or config["geomask-stroke-colour"] or DEFAULT_GEOMASK_STROKE_COLOR
args["fill"..argNumber] = config["geomask-fill"] or DEFAULT_GEOMASK_FILL
args["fill-opacity"..argNumber] = config["geomask-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
-- Let cartographer determine zoom and position, unless it is explicitly set in config
if not config.zoom and not config.switcher then
args.zoom = nil
args["frame-coord"] = nil
args["frame-lat"] = nil
args["frame-long"] = nil
local maskArea = util.getStatementValue( util.getBestStatement(maskItem, 'P2046') )
end
incrementArgNumber()
-- Hack to fix phab:T255932
if not args.zoom then
args["type"..argNumber] = "line"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = 0
incrementArgNumber()
end
end
-- Shape (or shape-inverse)
if showShape then
args["type"..argNumber] = shapeType
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["shape-stroke-width"] or config["stroke-width"] or DEFAULT_SHAPE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_SHAPE_STROKE_COLOR
args["fill"..argNumber] = config["shape-fill"] or DEFAULT_SHAPE_FILL
args["fill-opacity"..argNumber] = config["shape-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
incrementArgNumber()
end
-- Line
if showLine then
args["type"..argNumber] = "line"
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["line-stroke-width"] or config["stroke-width"] or DEFAULT_LINE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_LINE_STROKE_COLOR
incrementArgNumber()
end
-- Point marker
if showMarker then
args["type"..argNumber] = "point"
if config.id then args["id"..argNumber] = config.id end
if config.coord then args["coord"..argNumber] = config.coord end
if config.marker then args["marker"..argNumber] = config.marker end
args["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or DEFAULT_MARKER_COLOR
incrementArgNumber()
end
-- if Wikidata doesn't link to OSM and the map has no mask or point,
-- then center the map on the coordinates either from the infobox or from wikidata
if not maskItem and not showMarker and not wikidataProvidesGeo then
if config.coord then
args["frame-coord"] = args["frame-coord"] or config.coord
else
args["frame-lat"] = args["frame-lat"] or wdCoordinates.latitude
args["frame-long"] = args["frame-long"] or wdCoordinates.longitude
end
tracking = tracking..util.trackAndWarn('Duillagyn gymmydey infobox mapframe lesh laaraghey eignit')
end
-- protect against nil frame arguments
args["frame-coord"] = args["frame-coord"] or ""
args["frame-lat"] = args["frame-lat"] or ""
args["frame-long"] = args["frame-long"] or ""
local mapframe = args.switch and mf.multi(args) or mf._main(args)
tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo
and util.trackAndWarn('Duillagyn gymmydey infobox mapframe lesh laaraghey eignit')
or '')
return true, mapframe.. tracking
end
-- Entry points
p.main = function(frame)
local parent = frame.getParent(frame)
local parentArgs = parent.args
local _, mapframe = p._main(parentArgs)
return frame:preprocess(mapframe)
end
p.auto = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("auto should not autorun")
end
local args = util.argsFromAuto(frame)
if args.custom then
return frame:preprocess(util.parseCustomWikitext(args.custom))
end
local _, mapframe = p._main(args)
return frame:preprocess(mapframe)
end
p.autocaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autocaption should not autorun")
end
local args = util.argsFromAuto(frame)
local caption = p._caption(args)
return caption
end
p.autoWithCaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autoWithCaption should not autorun")
end
local args = util.argsFromAuto(frame)
local wikitext
local caption
local ok
if args.custom then
ok = true
wikitext = util.parseCustomWikitext(args.custom)
else
ok, wikitext = p._main(args)
end
if not ok then return wikitext end
wikitext = frame:preprocess(wikitext)
caption = p._caption(args)
local data = mw.html.create():wikitext(wikitext)
data:tag('div')
:addClass('infobox-caption')
:cssText(args.captionstyle)
:wikitext(caption)
return tostring(data)
end
return p
4msiznhlm4mvzg5e8o90zd78pxi58jg
392650
392649
2026-09-01T14:14:44Z
MacTire02
219
-assaaragh
392650
Scribunto
text/plain
local mf = require('Module:Mapframe')
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local infoboxImage = require('Module:InfoboxImage').InfoboxImage
-- Defaults
local DEFAULT_FRAME_WIDTH = "270"
local DEFAULT_FRAME_HEIGHT = "200"
local DEFAULT_ZOOM = 10
local DEFAULT_GEOMASK_STROKE_WIDTH = "1"
local DEFAULT_GEOMASK_STROKE_COLOR = "#777777"
local DEFAULT_GEOMASK_FILL = "#888888"
local DEFAULT_GEOMASK_FILL_OPACITY = "0.25"
local DEFAULT_SHAPE_STROKE_WIDTH = "2"
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000"
local DEFAULT_SHAPE_FILL = "#606060"
local DEFAULT_SHAPE_FILL_OPACITY = "0.1"
local DEFAULT_LINE_STROKE_WIDTH = "5"
local DEFAULT_LINE_STROKE_COLOR = "#FF0000"
local DEFAULT_MARKER_COLOR = "#5E74F3"
local util = {}
function util.noop(info)
local DEFAULT_NOOP_OUTPUT = ""
-- uncomment this when debugging
-- DEFAULT_NOOP_OUTPUT = "debug: mapframe no-op: " .. info
-- mw.log(DEFAULT_NOOP_OUTPUT)
return DEFAULT_NOOP_OUTPUT
end
-- Trim whitespace from args, and remove empty args
function util.trimArgs(argsTable)
local cleanArgs = {}
for key, val in pairs(argsTable) do
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val ~= '' then
cleanArgs[key] = val
end
else
cleanArgs[key] = val
end
end
return cleanArgs
end
function util.getBestStatement(item_id, property_id)
if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then
return false
end
local statements = mw.wikibase.getBestStatements(item_id, property_id)
if not statements or #statements == 0 then
return false
end
local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )
if hasNoValue then
return false
end
return statements[1]
end
function util.hasWikidataProperty(item_id, property_id)
return util.getBestStatement(item_id, property_id) and true or false
end
function util.getStatementValue(statement)
return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil
end
function util.relatedEntity(item_id, property_id)
local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )
return value and value.id or false
end
function util.idType(id)
if not id then
return nil
elseif mw.ustring.match(id, "[Pp]%d+") then
return "property"
elseif mw.ustring.match(id, "[Qq]%d+") then
return "item"
else
return nil
end
end
function util.shouldAutoRun(frame)
-- Check if should be running
local pargs = frame.getParent(frame).args
local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or "")) -- true of false or nil
if pargs.coordinates == "{{{coordinates}}}" then explicitlyOn = false end
if type(pargs.coordinates) == 'string' and string.match(pargs.coordinates, 'coord.missing') then explicitlyOn = false end
local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false
return explicitlyOn or onByDefault
end
function util.argsFromAuto(frame)
-- Get args from the frame (invoke call) and the parent (template call).
-- Frame arguments are default values which are overridden by parent values
-- when both are present
local args = getArgs(frame, {parentFirst = true})
-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain
local fixedArgs = {}
for name, val in pairs(args) do
local fixedName = string.match(name, "^mapframe%-(.+)$" )
if fixedName then
fixedArgs[fixedName] = val
-- allow coord, coordinates, etc to be unprefixed
elseif name == "coordinates" or name == "coord" or name == "coordinate" and not fixedArgs.coord then
fixedArgs.coord = val
-- allow id, qid to be unprefixed, map to id (if not already present)
elseif name == "id" or name == "qid" and not fixedArgs.id then
fixedArgs.id = val
-- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]
elseif name == "captionstyle" and not fixedArgs.captionstyle then
fixedArgs.captionstyle = val
end
end
return fixedArgs
end
function util.parseCustomWikitext(customWikitext)
-- infoboxImage will format an image if given wikitext containing an
-- image, or else pass through the wikitext unmodified
return infoboxImage({
args = {
image = customWikitext
}
})
end
function util.trackAndWarn(trackingCat, warning)
local title = mw.title.getCurrentTitle()
local results = title and title.namespace == 0 and trackingCat and '[[Category:'..trackingCat..']]' or ''
if warning then
local warn = require('Module:If preview')._warning
results = results..warn({warning})
end
return results
end
function util.ternary(flag, other)
other = other or 'other'
flag = flag == 'none' and 'no' or flag
local yesNoOut = yesno(flag,other)
local yes = (yesNoOut == true)
local no = (yesNoOut == false)
return yes, no
end
local p = {}
p._caption = function(args)
if args.caption then
return args.caption
elseif args.switcher then
return util.noop("no caption or switcher")
end
local maskItem
local maskType = util.idType(args.geomask)
if maskType == 'item' then
maskItem = args.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)
end
local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )
return maskItemLabel and "Location in "..maskItemLabel
or util.noop("missing maskItemLabel with type " .. (maskType or "nil") .. " and item " .. (maskItem or "nil"))
end
--A list of types for objects that are too small to allow Kartographer to take over zoom
local tinyType = {
landmark=true,
railwaystation=true,
edu=true,
pass=true,
camera=true
}
p._main = function(_config)
-- accumulate tracking cats
local tracking = ''
-- `config` is the args passed to this module
local config = util.trimArgs(_config)
-- allow alias for config.coord
config.coord = config.coord or config.coordinates
-- Require wikidata item, or specified coords
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
if not(wikidataId) and not(config.coord) then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn co-ordnaidyn')
end
-- Require coords (specified or from wikidata), so that map will be centred somewhere
-- (P625 = coordinate location)
local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, 'P625'))
if not (config.coord or wdCoordinates) then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn co-ordnaidyn')
end
-- `args` is the arguments which will be passed to the mapframe module
local args = {}
-- Some defaults/overrides for infobox presentation
args.display = "inline"
args.frame = "yes"
args.plain = "yes"
args["frame-width"] = config["frame-width"] or config.width or DEFAULT_FRAME_WIDTH
args["frame-height"] = config["frame-height"] or config.height or DEFAULT_FRAME_HEIGHT
args["frame-align"] = "center"
args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"]
-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )
-- deprecated lat and long parameters
args["frame-lat"] = config["frame-lat"] or config["frame-latitude"]
args["frame-long"] = config["frame-long"] or config["frame-longitude"]
-- if zoom isn't specified from config, first check wikidata
local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, 'P6592'))
if not zoom then
-- Calculate zoom from length or area (converted to km or km2)
-- Zoom so that length or area is completely included in mapframe
local getZoom = require('Module:Infobox dim')._zoom
zoom = getZoom({length_km=config.length_km, length_mi=config.length_mi,
width_km=config.width_km, width_mi=config.width_mi,
area_km2=config.area_km2, area_mi2=config.area_mi2,
area_ha=config.area_ha, area_acre=config.area_acre,
type=config.type, population=config.population,
viewport_px=math.min(args["frame-width"],args["frame-height"]),
latitude=wdCoordinates and wdCoordinates.latitude})
end
args.zoom = zoom or DEFAULT_ZOOM
-- Use OSM relation ID if available; otherwise use geoshape if that is available
-- (geoshape is required for defunct entities, which are outside OSM's scope)
local hasOsmRelationId = util.hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local hasGeoshape = util.hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape
-- determine marker argument value, determine whether to show marker
local forcePoint, suppressPoint = util.ternary(config.point)
local forceMarker, suppressMarker = util.ternary(config.marker,true)
forcePoint = forcePoint or forceMarker
suppressPoint = suppressPoint or suppressMarker
local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)
-- wikidata = "yes" turns on both shape and line
-- wikidata = "no" turns off both shape and line
-- otherwise show both if wikidata provides geo
local forceWikidata, suppressWikidata = util.ternary(config.wikidata)
local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)
local showLine = showShape
-- determine shape parameter value, determine whether to show or suppress shape
-- also determine whether to invert shape
local forceShape, suppressShape = util.ternary(config.shape)
showShape = wikidataId and not suppressShape and (forceShape or showShape)
local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'
-- determine line parameter value, determine whether to show or suppress line
local forceLine, suppressLine = util.ternary(config.line)
showLine = wikidataId and not suppressLine and (forceLine or showLine)
local maskItem
-- Switcher
if config.switcher == "zooms" then
-- switching between zoom levels
local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)
local minZoom = 1 -- completely zoomed out
local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min
args.switch = "zoomed in, zoomed midway, zoomed out"
args.zoom = string.format("SWITCH:%d,%d,%d", maxZoom, midZoom, minZoom)
elseif config.switcher == "auto" then
-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,
-- that city's state, and that state's country
args.zoom = nil -- let kartographer determine the zoom
local maskLabels = {}
local maskItems = {}
local maskItemId = util.relatedEntity(wikidataId, "P276") or util.relatedEntity(wikidataId, "P131")
local maskLabel = mw.wikibase.getLabel(maskItemId)
while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do
table.insert(maskLabels, maskLabel)
table.insert(maskItems, maskItemId)
maskItemId = maskItemId and util.relatedEntity(maskItemId, "P131")
maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)
end
if #maskLabels > 1 then
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
elseif #maskLabels == 1 then
maskItem = maskItemId[1]
end
elseif config.switcher == "geomasks" and config.geomask then
-- switching between items in geomask parameter
args.zoom = nil -- let kartographer determine the zoom
local separator = (mw.ustring.find(config.geomask, "###", 0, true ) and "###") or
(mw.ustring.find(config.geomask, ";", 0, true ) and ";") or ","
local pattern = "%s*"..separator.."%s*"
local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, "SWITCH:", ""), pattern)
local maskLabels = {}
if #maskItems > 1 then
for i, item in ipairs(maskItems) do
table.insert(maskLabels, mw.wikibase.getLabel(item))
end
args.switch = table.concat(maskLabels, "###")
maskItem = "SWITCH:" .. table.concat(maskItems, ",")
end
end
-- resolve geomask item id (if not using geomask switcher)
if not maskItem then --
local maskType = util.idType(config.geomask)
if maskType == 'item' then
maskItem = config.geomask
elseif maskType == "property" then
maskItem = util.relatedEntity(wikidataId, config.geomask)
end
end
-- if asking for shape or line from Wikidata
-- and if Wikidata actually has shape/line data (wikidataProvidesGeo=true)
-- and if no geomask
-- and if zoom not explicitly set
-- and if the object size inferred from its type is not too small
-- then let Kartographer "take over" zoom
if (showLine or showShape) and wikidataProvidesGeo and not maskItem
and not config.zoom and not (config.type and tinyType[config.type]) then
args.zoom = nil
end
if not maskItem and not showShape and not showLine and not showMarker then
return false, util.trackAndWarn('Duillagyn gymmydey infobox mapframe gyn towse-oaylleeaght','Cha nel towse-oaylleeaght sonrit da mapframe')
end
-- Keep track of arg numbering
local argNumber = ''
local function incrementArgNumber()
if argNumber == '' then
argNumber = 2
else
argNumber = argNumber + 1
end
end
-- Geomask
if maskItem then
args["type"..argNumber] = "shape-inverse"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = config["geomask-stroke-width"] or DEFAULT_GEOMASK_STROKE_WIDTH
args["stroke-color"..argNumber] = config["geomask-stroke-color"] or config["geomask-stroke-colour"] or DEFAULT_GEOMASK_STROKE_COLOR
args["fill"..argNumber] = config["geomask-fill"] or DEFAULT_GEOMASK_FILL
args["fill-opacity"..argNumber] = config["geomask-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
-- Let cartographer determine zoom and position, unless it is explicitly set in config
if not config.zoom and not config.switcher then
args.zoom = nil
args["frame-coord"] = nil
args["frame-lat"] = nil
args["frame-long"] = nil
local maskArea = util.getStatementValue( util.getBestStatement(maskItem, 'P2046') )
end
incrementArgNumber()
-- Hack to fix phab:T255932
if not args.zoom then
args["type"..argNumber] = "line"
args["id"..argNumber] = maskItem
args["stroke-width"..argNumber] = 0
incrementArgNumber()
end
end
-- Shape (or shape-inverse)
if showShape then
args["type"..argNumber] = shapeType
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["shape-stroke-width"] or config["stroke-width"] or DEFAULT_SHAPE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_SHAPE_STROKE_COLOR
args["fill"..argNumber] = config["shape-fill"] or DEFAULT_SHAPE_FILL
args["fill-opacity"..argNumber] = config["shape-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY
incrementArgNumber()
end
-- Line
if showLine then
args["type"..argNumber] = "line"
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
args["id"..argNumber] = config.id
end
args["stroke-width"..argNumber] = config["line-stroke-width"] or config["stroke-width"] or DEFAULT_LINE_STROKE_WIDTH
args["stroke-color"..argNumber] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_LINE_STROKE_COLOR
incrementArgNumber()
end
-- Point marker
if showMarker then
args["type"..argNumber] = "point"
if config.id then args["id"..argNumber] = config.id end
if config.coord then args["coord"..argNumber] = config.coord end
if config.marker then args["marker"..argNumber] = config.marker end
args["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or DEFAULT_MARKER_COLOR
incrementArgNumber()
end
-- if Wikidata doesn't link to OSM and the map has no mask or point,
-- then center the map on the coordinates either from the infobox or from wikidata
if not maskItem and not showMarker and not wikidataProvidesGeo then
if config.coord then
args["frame-coord"] = args["frame-coord"] or config.coord
else
args["frame-lat"] = args["frame-lat"] or wdCoordinates.latitude
args["frame-long"] = args["frame-long"] or wdCoordinates.longitude
end
tracking = tracking..util.trackAndWarn('Duillagyn gymmydey infobox mapframe lesh laaraghey eignit')
end
-- protect against nil frame arguments
args["frame-coord"] = args["frame-coord"] or ""
args["frame-lat"] = args["frame-lat"] or ""
args["frame-long"] = args["frame-long"] or ""
local mapframe = args.switch and mf.multi(args) or mf._main(args)
tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo
and util.trackAndWarn('Duillagyn gymmydey infobox mapframe lesh laaraghey eignit')
or '')
return true, mapframe.. tracking
end
-- Entry points
p.main = function(frame)
local parent = frame.getParent(frame)
local parentArgs = parent.args
local _, mapframe = p._main(parentArgs)
return frame:preprocess(mapframe)
end
p.auto = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("auto should not autorun")
end
local args = util.argsFromAuto(frame)
if args.custom then
return frame:preprocess(util.parseCustomWikitext(args.custom))
end
local _, mapframe = p._main(args)
return frame:preprocess(mapframe)
end
p.autocaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autocaption should not autorun")
end
local args = util.argsFromAuto(frame)
local caption = p._caption(args)
return caption
end
p.autoWithCaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autoWithCaption should not autorun")
end
local args = util.argsFromAuto(frame)
local wikitext
local caption
local ok
if args.custom then
ok = true
wikitext = util.parseCustomWikitext(args.custom)
else
ok, wikitext = p._main(args)
end
if not ok then return wikitext end
wikitext = frame:preprocess(wikitext)
caption = p._caption(args)
local data = mw.html.create():wikitext(wikitext)
data:tag('div')
:addClass('infobox-caption')
:cssText(args.captionstyle)
:wikitext(caption)
return tostring(data)
end
return p
9dhs9ojwbai2jluuc775pb0ggjq7dt0
Clowan:Native name checker
10
34027
392645
337456
2026-09-01T13:33:17Z
MacTire02
219
MacTire02 moved page [[Clowan:Scruteyr ennym dooghyssagh]] to [[Clowan:Native name checker]]
337456
wikitext
text/x-wiki
<includeonly>{{#invoke:native name|native_name_checker}}</includeonly><noinclude>{{documentation}}</noinclude>
ngh8pjh6mh5hws7dm7zaxylonxycbv5
Module:Location map
828
34040
392642
337498
2026-09-01T13:28:43Z
MacTire02
219
++
392642
Scribunto
text/plain
require('strict')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local function round(n, decimals)
local pow = 10^(decimals or 0)
return math.floor(n * pow + 0.5) / pow
end
function p.getMapParams(map, frame)
if not map then
error('The name of the location map definition to use must be specified', 2)
end
local moduletitle = mw.title.new('Module:Location map/data/' .. map)
if not moduletitle then
error(string.format('%q is not a valid name for a location map definition', map), 2)
elseif moduletitle.exists then
local mapData = mw.loadData('Module:Location map/data/' .. map)
return function(name, params)
if name == nil then
return 'Module:Location map/data/' .. map
elseif mapData[name] == nil then
return ''
elseif params then
return mw.message.newRawMessage(tostring(mapData[name]), unpack(params)):plain()
else
return mapData[name]
end
end
else
error('Unable to find the specified location map definition: "Module:Location map/data/' .. map .. '" does not exist', 2)
end
end
function p.data(frame, args, map)
if not args then
args = getArgs(frame, {frameOnly = true})
end
if not map then
map = p.getMapParams(args[1], frame)
end
local params = {}
for k,v in ipairs(args) do
if k > 2 then
params[k-2] = v
end
end
return map(args[2], #params ~= 0 and params)
end
local hemisphereMultipliers = {
longitude = { W = -1, w = -1, E = 1, e = 1 },
latitude = { S = -1, s = -1, N = 1, n = 1 }
}
local function decdeg(degrees, minutes, seconds, hemisphere, decimal, direction)
if decimal then
if degrees then
error('Decimal and DMS degrees cannot both be provided for ' .. direction, 2)
elseif minutes then
error('Minutes can only be provided with DMS degrees for ' .. direction, 2)
elseif seconds then
error('Seconds can only be provided with DMS degrees for ' .. direction, 2)
elseif hemisphere then
error('A hemisphere can only be provided with DMS degrees for ' .. direction, 2)
end
local retval = tonumber(decimal)
if retval then
return retval
end
error('The value "' .. decimal .. '" provided for ' .. direction .. ' is not valid', 2)
elseif seconds and not minutes then
error('Seconds were provided for ' .. direction .. ' without minutes also being provided', 2)
elseif not degrees then
if minutes then
error('Minutes were provided for ' .. direction .. ' without degrees also being provided', 2)
elseif hemisphere then
error('A hemisphere was provided for ' .. direction .. ' without degrees also being provided', 2)
end
return nil
end
decimal = tonumber(degrees)
if not decimal then
error('The degree value "' .. degrees .. '" provided for ' .. direction .. ' is not valid', 2)
elseif minutes and not tonumber(minutes) then
error('The minute value "' .. minutes .. '" provided for ' .. direction .. ' is not valid', 2)
elseif seconds and not tonumber(seconds) then
error('The second value "' .. seconds .. '" provided for ' .. direction .. ' is not valid', 2)
end
decimal = decimal + (minutes or 0)/60 + (seconds or 0)/3600
if hemisphere then
local multiplier = hemisphereMultipliers[direction][hemisphere]
if not multiplier then
error('The hemisphere "' .. hemisphere .. '" provided for ' .. direction .. ' is not valid', 2)
end
decimal = decimal * multiplier
end
return decimal
end
-- Finds a parameter in a transclusion of {{Coord}}.
local function coord2text(para,coord) -- this should be changed for languages which do not use Arabic numerals or the degree sign
local lat, long = mw.ustring.match(coord,'<span class="p%-latitude latitude">([^<]+)</span><span class="p%-longitude longitude">([^<]+)</span>')
if lat then
return tonumber(para == 'longitude' and long or lat)
end
local result = mw.text.split(mw.ustring.match(coord,'%-?[%.%d]+°[NS] %-?[%.%d]+°[EW]') or '', '[ °]')
if para == 'longitude' then result = {result[3], result[4]} end
if not tonumber(result[1]) or not result[2] then
mw.log('Malformed coordinates value')
mw.logObject(para, 'para')
mw.logObject(coord, 'coord')
return error('Malformed coordinates value', 2)
end
return tonumber(result[1]) * hemisphereMultipliers[para][result[2]]
end
-- effectively make removeBlanks false for caption and maplink, and true for everything else
-- if useWikidata is present but blank, convert it to false instead of nil
-- p.top, p.bottom, and their callers need to use this
function p.valueFunc(key, value)
if value then
value = mw.text.trim(value)
end
if value ~= '' or key == 'caption' or key == 'maplink' then
return value
elseif key == 'useWikidata' then
return false
end
end
local function getContainerImage(args, map)
if args.AlternativeMap then
return args.AlternativeMap
elseif args.relief then
local digits = mw.ustring.match(args.relief,'^[1-9][0-9]?$') -- image1 to image99
if digits then
local imageDigits = map('image' .. digits)
if imageDigits ~= '' then return imageDigits end
end
local yesNo = require('Module:Yesno')
if yesNo(args.relief,true) then
local image1 = map('image1')
if image1 ~= '' then return image1 end
end
end
return map('image')
end
function p.top(frame, args, map)
if not args then
args = getArgs(frame, {frameOnly = true, valueFunc = p.valueFunc})
end
if not map then
map = p.getMapParams(args[1], frame)
end
local width
local default_as_number = tonumber(mw.ustring.match(tostring(args.default_width),"%d*"))
if not args.width then
width = round((default_as_number or 240) * (tonumber(map('defaultscale')) or 1))
elseif mw.ustring.sub(args.width, -2) == 'px' then
width = mw.ustring.sub(args.width, 1, -3)
else
width = args.width
end
local width_as_number = tonumber(mw.ustring.match(tostring(width),"%d*")) or 0;
if width_as_number == 0 then
-- check to see if width is junk. If it is, then use default calculation
width = round((default_as_number or 240) * (tonumber(map('defaultscale')) or 1))
width_as_number = tonumber(mw.ustring.match(tostring(width),"%d*")) or 0;
end
if args.max_width ~= "" and args.max_width ~= nil then
-- check to see if width bigger than max_width
local max_as_number = tonumber(mw.ustring.match(args.max_width,"%d*")) or 0;
if width_as_number>max_as_number and max_as_number>0 then
width = args.max_width;
end
end
local retval = frame:extensionTag{name = 'templatestyles', args = {src = 'Module:Location map/styles.css'}}
if args.float == 'center' then
retval = retval .. '<div class="center">'
end
if args.caption and args.caption ~= '' and args.border ~= 'infobox' then
retval = retval .. '<div class="locmap noresize thumb '
if args.float == '"left"' or args.float == 'left' then
retval = retval .. 'floatleft'
elseif args.float == '"center"' or args.float == 'center' or args.float == '"none"' or args.float == 'none' then
retval = retval .. 'tnone'
else
retval = retval .. 'floatright'
end
retval = retval .. '"><div class="thumbinner" style="width:' .. (width + 2) .. 'px'
if args.border == 'none' then
retval = retval .. ';border:none'
elseif args.border then
retval = retval .. ';border-color:' .. args.border
end
retval = retval .. '"><div style="position:relative;width:' .. width .. 'px' .. (args.border ~= 'none' and ';border:1px solid lightgray">' or '">')
else
retval = retval .. '<div class="locmap" style="width:' .. width .. 'px;'
if args.float == '"left"' or args.float == 'left' then
retval = retval .. 'float:left;clear:left'
elseif args.float == '"center"' or args.float == 'center' then
retval = retval .. 'float:none;clear:both;margin-left:auto;margin-right:auto'
elseif args.float == '"none"' or args.float == 'none' then
retval = retval .. 'float:none;clear:none'
else
retval = retval .. 'float:right;clear:right'
end
retval = retval .. '"><div style="width:' .. width .. 'px;padding:0"><div style="position:relative;width:' .. width .. 'px">'
end
local image = getContainerImage(args, map)
local currentTitle = mw.title.getCurrentTitle()
retval = string.format(
'%s[[File:%s|%spx|%s%s|class=notpageimage noviewer]]',
retval,
image,
width,
args.alt or ((args.label or currentTitle.text) .. ' is located in ' .. map('name')),
args.maplink and ('|link=' .. args.maplink) or ''
)
if args.caption and args.caption ~= '' then
if (currentTitle.namespace == 0) and mw.ustring.find(args.caption, '##') then
retval = retval .. '[[Category:Pages using location map with a double number sign in the caption]]'
end
end
if args.overlay_image then
return retval .. '<div style="position:absolute;top:0;left:0">[[File:' .. args.overlay_image .. '|' .. width .. 'px|class=notpageimage noviewer]]</div>'
else
return retval
end
end
function p.bottom(frame, args, map)
if not args then
args = getArgs(frame, {frameOnly = true, valueFunc = p.valueFunc})
end
if not map then
map = p.getMapParams(args[1], frame)
end
local retval = '</div>'
local currentTitle = mw.title.getCurrentTitle()
if not args.caption or args.border == 'infobox' then
if args.border then
retval = retval .. '<div style="padding-top:0.2em">'
else
retval = retval .. '<div style="font-size:91%;padding-top:3px">'
end
retval = retval
.. (args.caption or (args.label or currentTitle.text) .. ' (' .. map('name') .. ')')
.. '</div>'
elseif args.caption ~= '' then
-- This is not the pipe trick. We're creating a link with no text on purpose, so that CSS can give us a nice image
retval = retval .. '<div class="thumbcaption"><div class="magnify">[[:File:' .. getContainerImage(args, map) .. '| ]]</div>' .. args.caption .. '</div>'
end
if args.switcherLabel then
retval = retval .. '<span class="switcher-label" style="display:none">' .. args.switcherLabel .. '</span>'
elseif args.autoSwitcherLabel then
retval = retval .. '<span class="switcher-label" style="display:none">Show map of ' .. map('name') .. '</span>'
end
retval = retval .. '</div></div>'
if args.caption_undefined then
mw.log('Removed parameter caption_undefined used.')
local parent = frame:getParent()
if parent then
mw.log('Parent is ' .. parent:getTitle())
end
mw.logObject(args, 'args')
if currentTitle.namespace == 0 then
retval = retval .. '[[Category:Location maps with removed parameters|caption_undefined]]'
end
end
if map('skew') ~= '' or map('lat_skew') ~= '' or map('crosses180') ~= '' or map('type') ~= '' then
mw.log('Removed parameter used in map definition ' .. map())
if currentTitle.namespace == 0 then
local key = (map('skew') ~= '' and 'skew' or '') ..
(map('lat_skew') ~= '' and 'lat_skew' or '') ..
(map('crosses180') ~= '' and 'crosses180' or '') ..
(map('type') ~= '' and 'type' or '')
retval = retval .. '[[Category:Location maps with removed parameters|' .. key .. ' ]]'
end
end
if string.find(map('name'), '|', 1, true) then
mw.log('Pipe used in name of map definition ' .. map())
if currentTitle.namespace == 0 then
retval = retval .. '[[Category:Location maps with a name containing a pipe]]'
end
end
if args.float == 'center' then
retval = retval .. '</div>'
end
return retval
end
local function markOuterDiv(x, y, imageDiv, labelDiv, label_size)
return mw.html.create('div')
:addClass('od')
:addClass('notheme') -- T236137
:cssText('top:' .. round(y, 3) .. '%;left:' .. round(x, 3) .. '%;font-size:' .. label_size .. '%')
:node(imageDiv)
:node(labelDiv)
end
local function markImageDiv(mark, marksize, label, link, alt, title)
local builder = mw.html.create('div')
:addClass('id')
:cssText('left:-' .. round(marksize / 2) .. 'px;top:-' .. round(marksize / 2) .. 'px')
:attr('title', title)
if marksize ~= 0 then
builder:wikitext(string.format(
'[[File:%s|%dx%dpx|%s|link=%s%s|class=notpageimage noviewer]]',
mark,
marksize,
marksize,
label,
link,
alt and ('|alt=' .. alt) or ''
))
end
return builder
end
local function markLabelDiv(label, label_size, label_width, position, background, x, marksize)
if tonumber(label_size) == 0 then
return mw.html.create('div'):addClass('l0'):wikitext(label)
end
local builder = mw.html.create('div')
:cssText('width:' .. label_width .. 'em')
local distance = round(marksize / 2 + 1)
if position == 'top' then -- specified top
builder:addClass('pv'):cssText('bottom:' .. distance .. 'px;left:' .. (-label_width / 2) .. 'em')
elseif position == 'bottom' then -- specified bottom
builder:addClass('pv'):cssText('top:' .. distance .. 'px;left:' .. (-label_width / 2) .. 'em')
elseif position == 'left' or (tonumber(x) > 70 and position ~= 'right') then -- specified left or autodetected to left
builder:addClass('pl'):cssText('right:' .. distance .. 'px')
else -- specified right or autodetected to right
builder:addClass('pr'):cssText('left:' .. distance .. 'px')
end
builder = builder:tag('div')
:wikitext(label)
if background then
builder:cssText('background-color:' .. background)
end
return builder:done()
end
local function getX(longitude, left, right)
local width = (right - left) % 360
if width == 0 then
width = 360
end
local distanceFromLeft = (longitude - left) % 360
-- the distance needed past the map to the right equals distanceFromLeft - width. the distance needed past the map to the left equals 360 - distanceFromLeft. to minimize page stretching, go whichever way is shorter
if distanceFromLeft - width / 2 >= 180 then
distanceFromLeft = distanceFromLeft - 360
end
return 100 * distanceFromLeft / width
end
local function getY(latitude, top, bottom)
return 100 * (top - latitude) / (top - bottom)
end
function p.mark(frame, args, map)
if not args then
args = getArgs(frame, {wrappers = 'Template:Location map~'})
end
local mapnames = {}
if not map then
if args[1] then
map = {}
for mapname in mw.text.gsplit(args[1], '#', true) do
map[#map + 1] = p.getMapParams(mw.ustring.gsub(mapname, '^%s*(.-)%s*$', '%1'), frame)
mapnames[#mapnames + 1] = mapname
end
if #map == 1 then map = map[1] end
else
map = p.getMapParams('World', frame)
args[1] = 'World'
end
end
if type(map) == 'table' then
local outputs = {}
local oldargs = args[1]
for k,v in ipairs(map) do
args[1] = mapnames[k]
outputs[k] = tostring(p.mark(frame, args, v))
end
args[1] = oldargs
return table.concat(outputs, '#PlaceList#') .. '#PlaceList#'
end
local x, y, longitude, latitude
longitude = decdeg(args.lon_deg, args.lon_min, args.lon_sec, args.lon_dir, args.long, 'longitude')
latitude = decdeg(args.lat_deg, args.lat_min, args.lat_sec, args.lat_dir, args.lat, 'latitude')
if args.excludefrom then
-- If this mark is to be excluded from certain maps entirely (useful in the context of multiple maps)
for exclusionmap in mw.text.gsplit(args.excludefrom, '#', true) do
-- Check if this map is excluded. If so, return an empty string.
if args[1] == exclusionmap then
return ''
end
end
end
local builder = mw.html.create()
local currentTitle = mw.title.getCurrentTitle()
if args.coordinates then
-- Temporarily removed to facilitate infobox conversion. See [[Wikipedia:Coordinates in infoboxes]]
-- if longitude or latitude then
-- error('Coordinates from [[Module:Coordinates]] and individual coordinates cannot both be provided')
-- end
longitude = coord2text('longitude', args.coordinates)
latitude = coord2text('latitude', args.coordinates)
elseif not longitude and not latitude and args.useWikidata then
-- If they didn't provide either coordinate, try Wikidata. If they provided one but not the other, don't.
local entity = mw.wikibase.getEntity()
if entity and entity.claims and entity.claims.P625 and entity.claims.P625[1].mainsnak.snaktype == 'value' then
local value = entity.claims.P625[1].mainsnak.datavalue.value
longitude, latitude = value.longitude, value.latitude
end
if args.link and (currentTitle.namespace == 0) then
builder:wikitext('[[Category:Location maps with linked markers with coordinates from Wikidata]]')
end
end
if not longitude then
error('No value was provided for longitude')
elseif not latitude then
error('No value was provided for latitude')
end
if currentTitle.namespace > 0 then
if (not args.lon_deg) ~= (not args.lat_deg) then
builder:wikitext('[[Category:Location maps with different longitude and latitude precisions|Degrees]]')
elseif (not args.lon_min) ~= (not args.lat_min) then
builder:wikitext('[[Category:Location maps with different longitude and latitude precisions|Minutes]]')
elseif (not args.lon_sec) ~= (not args.lat_sec) then
builder:wikitext('[[Category:Location maps with different longitude and latitude precisions|Seconds]]')
elseif (not args.lon_dir) ~= (not args.lat_dir) then
builder:wikitext('[[Category:Location maps with different longitude and latitude precisions|Hemisphere]]')
elseif (not args.long) ~= (not args.lat) then
builder:wikitext('[[Category:Location maps with different longitude and latitude precisions|Decimal]]')
end
end
if ((tonumber(args.lat_deg) or 0) < 0) and ((tonumber(args.lat_min) or 0) ~= 0 or (tonumber(args.lat_sec) or 0) ~= 0 or (args.lat_dir and args.lat_dir ~='')) then
builder:wikitext('[[Category:Location maps with negative degrees and minutes or seconds]]')
end
if ((tonumber(args.lon_deg) or 0) < 0) and ((tonumber(args.lon_min) or 0) ~= 0 or (tonumber(args.lon_sec) or 0) ~= 0 or (args.lon_dir and args.lon_dir ~= '')) then
builder:wikitext('[[Category:Location maps with negative degrees and minutes or seconds]]')
end
if (((tonumber(args.lat_min) or 0) < 0) or ((tonumber(args.lat_sec) or 0) < 0)) then
builder:wikitext('[[Category:Location maps with negative degrees and minutes or seconds]]')
end
if (((tonumber(args.lon_min) or 0) < 0) or ((tonumber(args.lon_sec) or 0) < 0)) then
builder:wikitext('[[Category:Location maps with negative degrees and minutes or seconds]]')
end
if args.skew or args.lon_shift or args.markhigh then
mw.log('Removed parameter used in invocation.')
local parent = frame:getParent()
if parent then
mw.log('Parent is ' .. parent:getTitle())
end
mw.logObject(args, 'args')
if currentTitle.namespace == 0 then
local key = (args.skew and 'skew' or '') ..
(args.lon_shift and 'lon_shift' or '') ..
(args.markhigh and 'markhigh' or '')
builder:wikitext('[[Category:Location maps with removed parameters|' .. key ..' ]]')
end
end
if map('x') ~= '' then
x = tonumber(mw.ext.ParserFunctions.expr(map('x', { latitude, longitude })))
else
x = tonumber(getX(longitude, map('left'), map('right')))
end
if map('y') ~= '' then
y = tonumber(mw.ext.ParserFunctions.expr(map('y', { latitude, longitude })))
else
y = tonumber(getY(latitude, map('top'), map('bottom')))
end
if (x < 0 or x > 100 or y < 0 or y > 100) and not args.outside then
mw.log('Mark placed outside map boundaries without outside flag set. x = ' .. x .. ', y = ' .. y)
local parent = frame:getParent()
if parent then
mw.log('Parent is ' .. parent:getTitle())
end
mw.logObject(args, 'args')
if currentTitle.namespace == 0 then
local key = currentTitle.prefixedText
builder:wikitext('[[Category:Location maps with marks outside map and outside parameter not set|' .. key .. ' ]]')
end
end
local mark = args.mark or map('mark')
if mark == '' then
mark = 'Red pog.svg'
end
local marksize = tonumber(args.marksize) or tonumber(map('marksize')) or 8
local imageDiv = markImageDiv(mark, marksize, args.label or mw.title.getCurrentTitle().text, args.link or '', args.alt, args[2])
local label_size = args.label_size or 91
local labelDiv
if args.label and args.position ~= 'none' then
labelDiv = markLabelDiv(args.label, label_size, args.label_width or 6, args.position, args.background, x, marksize)
end
return builder:node(markOuterDiv(x, y, imageDiv, labelDiv, label_size))
end
local function switcherSeparate(s)
if s == nil then return {} end
local retval = {}
for i in string.gmatch(s .. '#', '([^#]*)#') do
i = mw.text.trim(i)
retval[#retval + 1] = (i ~= '' and i)
end
return retval
end
function p.infobox_pushpin_map(frame)
--This function is designed to be invoked from an infobox template
--* Some parameters (generally starting with "pushpin_") are meant to be exposed as parameters
-- in the outer infobox, settable by editors
--* Others are meant to be "hidden" (e.g., only set inside the infobox template code)
-- First get the combined arguments from both parent and invocation frame
local raw_args = getArgs(frame,{parentFirst=true})
--If no map is supplied, return.
if not raw_args['pushpin_map'] then
return
end
-- Now get arguments from just the invocation frame
local frame_args = getArgs(frame,{frameOnly=true})
-- parsed_args will have the resulting merged parameters
local parsed_args = {}
-- Default to using wikidata coodinates if no other coordiantes supplied.
if raw_args.useWikidata == nil then
parsed_args.useWikidata = true
else
parsed_args.useWikidata = raw_args.useWikidata
end
-- Parse the arguments
parsed_args[1] = raw_args['pushpin_map']
parsed_args.float = frame_args.float or 'center'
parsed_args.border = frame_args.border or 'infobox'
parsed_args.default_width = frame_args.default_width
parsed_args.max_width = frame_args.max_width
parsed_args.coordinates = raw_args['coordinates']
parsed_args.caption = raw_args['pushpin_caption']
parsed_args.relief = raw_args['pushpin_relief']
parsed_args.label = raw_args['pushpin_label']
parsed_args.label_size = raw_args['pushpin_label_size']
parsed_args.position = raw_args['pushpin_label_position']
parsed_args.mark = raw_args['pushpin_mark']
parsed_args.marksize = raw_args['pushpin_mark_size']
parsed_args.alt = raw_args['pushpin_alt']
parsed_args.background = raw_args['pushpin_background']
parsed_args.width = raw_args['pushpin_map_size']
local map = {}
local caption_list = {}
for mapname in string.gmatch(parsed_args[1], '[^#]+') do
map[#map + 1] = p.getMapParams(mw.ustring.gsub(mapname, '^%s*(.-)%s*$', '%1'), frame)
end
if parsed_args['caption'] then
for caption in mw.text.gsplit(parsed_args['caption'], '##', true) do
caption_list[#caption_list + 1] = caption
end
end
if #map == 1 then
map = map[1]
if not parsed_args.caption then
parsed_args.caption = 'Location within ' .. map('name')
end
end
if type(map) == 'table' then
mw.log('----')
mw.logObject(map)
if #caption_list > #map then
error(string.format('%d captions were provided, but only %d maps were provided', #caption_list, #map))
elseif not parsed_args.caption then
-- Set a default caption for each of the multiple maps
for i=1, #map do
caption_list[#caption_list + 1] = 'Location within '.. map[i]('name')
end
end
local outputs = {}
parsed_args.autoSwitcherLabel = true
for k,v in ipairs(map) do
parsed_args.caption = caption_list[k]
outputs[k] = p.main(frame, parsed_args, v)
end
return '<div class="switcher-container">' .. table.concat(outputs) .. '</div>'
else
return p.top(frame, parsed_args, map) .. tostring( p.mark(frame, parsed_args, map) ) .. p.bottom(frame, parsed_args, map)
end
end
function p.main(frame, args, map)
local caption_list = {}
if not args then
args = getArgs(frame, {wrappers = 'Template:Location map', valueFunc = p.valueFunc})
end
if args.useWikidata == nil then
args.useWikidata = true
end
if not map then
if args[1] then
map = {}
for mapname in string.gmatch(args[1], '[^#]+') do
map[#map + 1] = p.getMapParams(mw.ustring.gsub(mapname, '^%s*(.-)%s*$', '%1'), frame)
end
if args['caption'] then
if args['caption'] == "" then
while #caption_list < #map do
caption_list[#caption_list + 1] = args['caption']
end
else
for caption in mw.text.gsplit(args['caption'], '##', true) do
caption_list[#caption_list + 1] = caption
end
end
end
if #map == 1 then map = map[1] end
else
map = p.getMapParams('World', frame)
end
end
if type(map) == 'table' then
local altmaps = switcherSeparate(args.AlternativeMap)
if #altmaps > #map then
error(string.format('%d AlternativeMaps were provided, but only %d maps were provided', #altmaps, #map))
end
local overlays = switcherSeparate(args.overlay_image)
if #overlays > #map then
error(string.format('%d overlay_images were provided, but only %d maps were provided', #overlays, #map))
end
if #caption_list > #map then
error(string.format('%d captions were provided, but only %d maps were provided', #caption_list, #map))
end
local outputs = {}
args.autoSwitcherLabel = true
for k,v in ipairs(map) do
args.AlternativeMap = altmaps[k]
args.overlay_image = overlays[k]
args.caption = caption_list[k]
outputs[k] = p.main(frame, args, v)
end
return '<div class="switcher-container">' .. table.concat(outputs) .. '</div>'
else
return p.top(frame, args, map) .. tostring( p.mark(frame, args, map) ) .. p.bottom(frame, args, map)
end
end
return p
3pqbnkg8pemwulwnvka0szt6hqc0tii
Clowan:WD Kishtey Fys Dooinney
10
45277
392674
391795
2026-09-01T20:33:36Z
WikiBayer
13794
392674
wikitext
text/x-wiki
<includeonly><templatestyles src="Infobox person/styles.css" /><templatestyles src="Kishtey fys/styles.css" /><templatestyles src="WD Kishtey Fys Dooinney/styles.css" />
<div class="wd-kishtey-fys-dooinney"><!--
-->{{WD Kishtey Fys Dooinney/formatglobal
| wikidata = {{{wikidata|}}}p
| child = {{{child|}}}
|editicon=no
| item = {{{item|}}}
| lang = {{{lang|}}}m_enoriginalcoorse
listp166
| desplega_influencia = {{{v_cllps_influenced_by|premi{{{desptriml20ega_influencia|}}}}}}
| desplega_obres = {{{v_cllps_works|{{{des3373plega_obres|}}}}}} <!-- llargada a partir de la que es fa caixa desplegable -->
| desplega_premis = {{{v_cllps_awards|{{{dep155splega_premis| }}}}}} <!-- llargada a partir de la que es fa caixa desplegable -->
| desplega_participa = {{{v_cllps_p7participant_in|{{{desplega_pynarticipa|}}}}}} <!-- llargada a partir de la que es fa caixa desplegable -->
| subheader = {{{subheader|}}}
| v_icon = {{#ifeq:{{{v_icon|{{{icona_esquerra|}}}}}}|NONE|<!-- skip without icon
-->|{{if empty|{{{v_icon|{{{icona_esquerra|}}}}}}
|{{MyValue|IBperson|icon_person}} <!-- default icon -->
}} }}
| prefix_honorific = {{#invoke:Wikidades |claim |property=P511 |value={{{v_p511|{{{prefix_honorific|}}}}}}
|list=false|case=gender}}
| sufix_honorific = {{#invoke:Wikidades |claim |property=P1035 |value={{{v_p1035|{{{sufix_honorific|}}}}}}
|list=false}}
| nom = {{if empty| {{{v_name|{{{nom|{{{name|{{{ennym|}}}}}}}}}}}} | {{{nom_oficial|}}} |{{Enmys gyn reddaghey}} }}
<!--| nom_original_txt = {{#invoke:Wikidades | claim | property= P1559/P1705 | list=firstrank | formatting=text --><!-- to check
when name = original name. --><!--|editicon=no| value={{{v_p1559|{{{ennym_ruggyr|}}}}}} }}--><!-- The "original name" -->
<!-- contains language -->
| nom_original = {{#invoke:Wikidades | claim | property= P1559/P1705 | list=firstrank
| value={{{v_p1559|{{{ennym_ruggyr|}}}}}} |formatting=$text ($language)|separator=<br/> }}
| nom_original_lleng = {{{nom_original_lleng|}}}<!-- llengua en camp separat, si manual. Si és de WD va dins el nom en span-->
| nom_temple = {{#invoke:wikidata | claim | property=P1785 | value={{{nom_temple|}}} |list=firstrank}}
| nom_postum = {{#invoke:wikidata | claim | property=P1786 | value={{{nom_postum|}}} |list=firstrank}}
| jalloo = {{#invoke:InfoboxImage |InfoboxImage |image={{#invoke:Wikidata |claim |property=P18 |value={{{jalloo|}}} |list=false}} |size=300x300px<!--
-->|alt={{{alt|}}} }}
| fo-heidyl = {{{fo-heidyl|}}}
| extensio_noms_farao ={{#ifeq: {{{v_p7383|{{{v_prenomen|{{{v_prenomen2|{{{v_nomen|{{{v_nomen2|{{{v_horus|{{{v_horus2|{{{v_nebty|{{{v_golden|{{{prenomen|{{{prenomen2|{{{nomen|{{{nomen2|{{{horus|{{{horus2|{{{nebty|{{{golden|}}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}}|NONE|<!-- no take WD
-->|{{#if: {{{prenomen|}}}{{{prenomen2|}}}{{{nomen|}}}{{{nomen2|}}}{{{horus|}}}{{{horus2|}}}
{{{nebty|}}}{{{golden|}}}<!-- Manual parameters, create list -->
|{{Collapsible list
|titlestyle = infobox_titlestyle_pharaon
|title='''{{GetLabelFix|Q263595|lang={{{lang|}}}}}'''
|1 = {{infoboxFrame
|headerclass = infobox_headerstyle
|imagestyle = text-align:center;
|labelclass = infobox-label
|datastyle = text-align:start
|decat = yes
| header10 =
{{#if: {{{v_prenomen|{{{prenomen|}}}}}}
|'''{{GetLabelFix|Q1413565|lang={{{lang|}}}}}''' }}
| data11 =
{{#if:{{{v_prenomen|{{{prenomen|}}}}}}
|{{{v_prenomen|{{{prenomen|}}}}}}<br>
}}<div class="center">
{{#if: {{{v_prenomen_hiero|{{{prenomen_hiero|}}}}}}
|{{Pharoah hiero draw|1=Prenomen|2={{{v_prenomen_hiero|{{{prenomen_hiero|}}}}}}}}
}}</div>
| header30 =
{{#if: {{{v_nomen|{{{nomen|}}}}}}
|'''{{GetLabelFix|Q1303227|lang={{{lang|}}}}}''' }}
| data31 =
{{#if:{{{v_nomen|{{{nomen|}}}}}}
|{{{v_nomen|{{{nomen|}}}}}}<br>
}}<div class="center">
{{#if: {{{v_nomen_hiero|{{{nomen_hiero|}}}}}}
|{{Pharoah hiero draw|1=Nomen|2={{{v_nomen_hiero|{{{nomen_hiero|}}}}}}}}
}}</div>
| header50 =
{{#if:{{{v_horus|{{{horus|}}}}}}
|'''{{GetLabelFix|Q153263|lang={{{lang|}}}}}''' }}
| data51 =
{{#if: {{{v_horus|{{{horus|}}}}}}
|{{{v_horus|{{{horus|}}}}}}<br>
}}<div class="center">
{{#if: {{{v_horus_hiero|{{{horus_hiero|}}}}}}
|{{Pharoah hiero draw|1=Horus|2={{{v_horus_hiero|{{{horus_hiero|}}}}}}}}
}}</div>
| header70 =
{{#if: {{{v_nebty|{{{nebty|}}}}}}
|'''{{GetLabelFix|Q15523428|lang={{{lang|}}}}}'''}}
| data71 =
{{#if: {{{v_nebty|{{{nebty|}}}}}}
|{{{v_nebty|{{{nebty|}}}}}}<br>
}}<div class="center">
{{#if: {{{v_netby_hiero|{{{netby_hiero|}}}}}}
|{{Pharoah hiero draw|1=Nebty|2={{{v_netby_hiero|{{{netby_hiero|}}}}}}}}
}}</div>
| header80 =
{{#if: {{{v_golden|{{{golden|}}}}}}
|'''{{GetLabelFix|Q1535966|lang={{{lang|}}}}}''' }}
| data81 =
{{#if: {{{v_golden|{{{golden|}}}}}}
|{{{v_golden|{{{golden|}}}}}}<br>
}}<div class="center">
{{#if: {{{v_golden_hiero|{{{golden_hiero|}}}}}}
| {{Pharoah hiero draw|1=Golden|2= {{{v_golden_hiero|{{{golden_hiero|}}}}}}}}
}}</div>
}}<!-- end infobox -->
}}<!-- end collapsible manuals -->
|{{#if:{{#invoke:Wikidades | claim |property=P7383}}<!-- Build list from WD -->
|{{Collapsible list
|titlestyle = infobox_titlestyle_pharaon
|title='''{{GetLabelFix|Q263595|lang={{{lang|}}}}}'''
|1 = {{infoboxFrame
|headerclass = infobox_headerstyle
|imagestyle = text-align:center;
|labelclass = infobox-label
|datastyle = text-align:start
|decat = yes
| data10 = <tr>{{#invoke:Wikidades | claim |property=P7383 |qualifier=P3831
| formatting=table |list=lang
| separator=</tr><tr>|conjunction=</tr><tr>
| qualifier2= P2561 |rowsubformat2= ''$2'' <!-- Per ara aquest contingut resulta inoperatiu, ja què WD està amb lang=und
i -->
| qualifier3= P2441 |rowsubformat3=<br>$3 |xcolformat3=lang
| qualifier4= P3831 |colformat4=raw
| rowformat=<!-- Position HEADER: Seal image + ordinal + position + (of)
--><th colspan="2" class=infobox_center_BG>$1</th><!--
--><!-- Position DESCRIPTION lines
--><tr><td colspan="2" style="text-align:start;">$2$3<!--
-->{{((}}Pharoah hiero draw{{!}}$4{{!}}$0{{))}}</td>
}}</tr><!-- end invokem WD-->
}}<!-- end infobox from WD-->
}}<!-- end collapsible WD -->
}}<!-- end if P7383 -->
}} <!-- end pharaons-->
}}<!-- end NONE -->
<!-- ++++++++++++++++++++ Versió antiga +++++++++++++++++++++++
{{#if: {{{prenomen|}}}{{{prenomen2|}}}{{{nomen|}}}{{{nomen2|}}}
{{{horus|}}}{{{horus2|}}}{{{nebty|}}}{{{golden|}}}
|{{WD Kishtey Fys Dooinney/parameadaryn
|bloc = nom_farao
|prenomen = {{{Prenomen|{{{prenomen|}}}}}}
|prenomenhiero = {{{PrenomenHiero|{{{prenomenhiero|}}}}}}
|prenomen2 = {{{Prenomen2|{{{prenomen2|}}}}}}
|prenomenhiero2 = {{{PrenomenHiero2|{{{prenomenhiero2|}}}}}}
|nomen = {{{Nomen|{{{nomen|}}}}}}
|nomenhiero = {{{NomenHiero|{{{nomenhiero|}}}}}}
|nomen2 = {{{Nomen2|{{{nomen2|}}}}}}
|nomenhiero2 = {{{NomenHiero2|{{{nomenhiero2|}}}}}}
|horus = {{{Horus|{{{horus|}}}}}}
|horushiero = {{{HorusHiero|{{{horushiero|}}}}}}
|horusprefix = {{{HorusPrefix|{{{horusprefix|}}}}}}
|horus2 = {{{Horus2|{{{horus2|}}}}}}
|horushiero2 = {{{HorusHiero2|{{{horushiero2|}}}}}}
|nebty = {{{Nebty|{{{nebty|}}}}}}
|nebtyhiero = {{{NebtyHiero|{{{nebtyhiero|}}}}}}
|golden = {{{Golden|{{{golden|}}}}}}
|goldenhiero = {{{GoldenHiero|{{{goldenhiero|}}}}}}
}} }} -->
| nom_naixement = {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->|{{#invoke:Wikidades | claim | property=P1477 |list=false
|formatting=$text ($language)|value={{{v_p1477|{{{ennym_ruggyr|}}}}}} }}
}}
| nom_naixement_txt = {{#invoke:Wikidades |claim |property=P1477 |list=false |formatting=text |editicon=no}}<!--to check
when name = birth name. -->
| data_naixement = {{#if: {{{date_ruggyr|}}}
| {{{date_ruggyr}}}{{#if:{{#Property:P570}}||<br />({{WD Kishtey Fys Dooinney/eash|{{{date_ruggyr|}}}}} {{#switch: {{#expr: {{WD Kishtey Fys Dooinney/eash|{{{date_ruggyr|}}}}} mod 10 }}
|1=vlein d'eash
|2=vleeaney d'eash
|#default=bleeaney d'eash
}})}}
|{{#ifexpr: {{#invoke:WikidataIB|getDatePrecision|1=P569|default=0}} >= 9
| {{#invoke:Wd|property|P569}}{{#if:{{#Property:P570}}||<br />({{WD Kishtey Fys Dooinney/eash|{{{date_ruggyr|}}}}} {{#switch: {{#expr: {{WD Kishtey Fys Dooinney/eash|{{{date_ruggyr|}}}}} mod 10 }}
|1=vlein d'eash
|2=vleeaney d'eash
|#default=bleeaney d'eash
}})}}
|
}}
}}
| floruit = {{#invoke:wikidata | claim | property=P1317|list=firstrank |conjunction=–
|separator=–| value={{{floruit|}}} }}
| bateig = {{#invoke:wikidata | claim | property=P1636|list=firstrank |conjunction=–
|separator=–| value={{{floruit|}}} }}
| lloc_naixement = {{#ifeq:{{{boayl_ruggyr|}}}|NONE|<!-- no es vol WD
-->|{{if empty | {{{boayl_ruggyr|}}}
| {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->|{{#if:{{#invoke:wikidata | claim | property=P19 | qualifier=P17}}<!--
-->|{{#invoke:wikidades | claim | property=P19 | qualifier=/P19
| qualifier2=P17 | formatting=table
| colformat0=sitelink | colformat1=label | colformat2= label
| rowformat=[[$0|$1 ($2)]] |editicon=no | list=false }}
{{#invoke:wikidata|editAtWikidata|property=P19 |editicon=true }}
|{{#invoke:wikidades | claim | property=P19 |qualifier=P1480
|list=false |formatting=table
|rowformat=$0$1 |colformat0=$text ($language) |rowsubformat1=, $1
| case=locationcontext }}
}}
}}
}}
}}
| desaparicio = {{#ifeq:{{{date_coayl|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{date_coayl|}}} | {{{date_coaylo|}}}
|{{#if:{{#invoke:wikidata|validProperty|P746|item={{{item|}}}}}
|{{circa|P746 |list=false|item={{{item|}}}|lang={{{lang|}}}}}<!--
-->{{#invoke:wikidades | claim | property=P746 |qualifier=P276
|qualifier2=P3831 |list=false |formatting=table
|rowformat=$1$2 |rowsubformat1=, $1 |rowsubformat2= ($2)}}
}} }} }}
| data_defuncio = {{{date_baaish|{{#invoke:WikidataIB|getValue|1=P570|2=|fwd=ALL|osd=false|df=dmy|noicon=true}}}}}
| lloc_defuncio = {{#ifeq:{{{boayl_baaish|}}}|NONE|<!-- no es vol WD
-->|{{if empty | {{{boayl_baaish|}}}
| {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->|{{#if:{{#invoke:wikidata | claim | property=P20 | qualifier=P17}}<!--
-->|{{#invoke:wikidades | claim | property=P20 | qualifier=/P20
| qualifier2=P17 | formatting=table
| colformat0=sitelink | colformat1=label | colformat2= label
| rowformat=[[$0|$1 ($2)]] |editicon=no | list=false }}
{{#invoke:wikidata|editAtWikidata|property=P20 |editicon=true }}
|{{#invoke:wikidades | claim | property=P20 |qualifier=P1480
|list=false |formatting=table
|rowformat=$0$1 |colformat0=$text ($language) |rowsubformat1=, $1
| case=locationcontext }}
}}
}}
}}
}}
| circumstancia_defuncio = {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->|{{#invoke:wikidata | claim | property=P1196 | list=firstrank |formatting=ucfirst
|value={{{tuittymys_baaish|{{{cor_baaish|}}}}}} }}
}}
| causa_defuncio = {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->|{{#invoke:wikidata | claim | property=P509 | list=firstrank
|value={{{bun_baaish|}}} | {{{cooish_baaish|}}} |formatting=ucfirst }}
}}
| sepultura = {{#ifeq:{{{boayl_oanluckee|}}}|NONE|<!-- no es vol WD
-->|{{if empty | {{#if: {{{boayl_oanluckee|}}} | {{{boayl_oanluckee|}}} {{{co-ordnaidyn_boayl_oanluckee|}}}}}
| {{#ifeq:{{lc:{{{child}}}}} |yes|<!-- taula incrustada, no agafar WD
-->| {{#invoke:wikidades | claim |formatting = table | property=P119
|qualifier=P580| qualifier2=P582 |colformat1=Y |colformat2=Y
|qualifier3=P625
|colformat3= <sup>{{((}}coord{{!}}$lat{{!}}$lon{{!}}display{{=}}inline{{))}}</sup>
|qualifier4=P965 |rowsubformat4=, $4 |tablesort=1|sorting=-1
|rowformat= $0$4 <small>{{((}}Format start end{{!}}$1{{!}}$2{{!}}lang{{=}}{{{lang|}}}{{))}} $3</small>
}} }}
}}
}}
| coordenades_sepultura = {{#if: {{{boayl_oanluckee|}}} | {{{co-ordnaidyn_boayl_oanluckee|}}}}}<!-- sepultura manual, agafa coord manual -->
<!-- Eliminada segons discussió 15-16 gener 2019
Es deixa com a paràmetre manual exclusivament. 27/5/2019
| residencia = {{#ifeq: {{{residencia|}}}|NONE|
|{{if empty | {{{residencia|}}}
|{{#invoke:wikidata | claim| property= P263/P551
| list=false}}
}}
}}
-->
| ynnyd_beaghee = {{{ynnyd_beaghee|}}}
| nacionalitat = {{ucfirst:{{{ashoonaght|}}} }}
| ciutadania = {{#ifeq:{{{seyraanaght|}}}|NONE|<!-- no es vol WD
-->|{{#ifeq:{{{seyraanaght|}}}|OKWD<!-- es vol forçar WD
-->|{{#invoke:wikidades | claim | property=P27
|qualifier=P580| qualifier2=P582 |formatting = table
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y}}
|{{{seyraanaght|}}}
}}
}}
| etnia = {{#invoke:wikidata | claim | property=P172 |list=firstrank |value={{{etnia|}}}
|formatting=ucfirst }}
| ideologia = {{#invoke:wikidata | claim | property=P1142|list=firstrank |value={{{ideologia|}}}
|formatting=ucfirst }}
| religio = {{#invoke:wikidata | claim | property=P140 |list=firstrank |value={{{religio|{{{craueeaght|}}}}}}
|formatting=ucfirst }}
| educacio = {{{educacio|}}}
<!-- Construir llista alma mater + tesi / alma mater + llista tesi-->
| alma_mater = <!-- La tesi (P1026) no es gestiona aquí per un canvi del 4/2/2018 s/discussió-->
{{#invoke:wikidades |claim |formatting=table |value={{{alma_mater|}}}
| property=P69 |qualifier=P580| qualifier2=P582 |qualifier3=P812 OR P512
|rowformat= $0 <small>$3 {{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
| rowsubformat3=- $3 |case3=gender
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y }}
| bloc_tesi = {{#ifeq:{{{tesi|}}}|NONE|<!-- no es vol WD
-->|{{#ifexpr:{{#invoke:wikidata|numStatements|P1026}} > 1
|'''{{GetLabelFix|P1026|lang={{{lang|}}}}}:'''<br><!--
-->{{#invoke:wikidades |claim |property=P1026 |list=firstrank |formatting=table |separator=<hr>
|qualifier =P577 or P1026/P577 |colformat=Y |rowsubformat1=<small>($1)</small>
|qualifier2=P123 or P4101 or P1026/P123 or P1026/P4101
|rowsubformat2=<br> <small>{{GetLabelFix|P4101|lang={{{lang|}}}}}:</small> $2.
|qualifier3=P953 or P2699 or P1026/P953 or P1026/P2699
|rowsubformat3= [[Coadan:Editcopy.svg|15px|link=$3]]
|qualifier4=P184 or P1026/P184
|rowsubformat4=<br> <small>{{GetLabelFix|P184|lang={{{lang|}}}}}:</small> $4
|rowformat=''$0''$3 $1$2$4 }}
}} }}
| tesi = {{#ifeq:{{{tesi|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{tesi|}}} | {{{tesi|}}}
|{{#ifexpr:{{#invoke:wikidata|numStatements|P1026}} > 1|<!-- skip. Is in bloc_tesi
-->|{{if empty|{{#invoke:wikidata | claim | property=P1026 |list=firstrank }}
|{{#invoke:wikidata | claim | property=P69 | qualifier=P1026 |list=firstrank }}
|{{#invoke:wikidata | claim | property=P512 | qualifier=P1026 |list=firstrank }}
}}
}} }} }}
| tesi_url = {{#ifeq:{{{tesi|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{tesi|}}} | {{{tesi_url|}}}
|{{#ifexpr:{{#invoke:wikidata|numStatements|P1026}} > 1|<!-- skip. Is in bloc_tesi
--><!-- Opcions: qualificador P2699(URL) o P953(text complet) del statement P1026 de la persona -->
|{{if empty|{{#invoke:wikidades| claim | property=P1026 |list=false |formatting=table
| qualifier=P2699 OR P953 |rowformat=$1 |rowsubformat1=$1 |editicon=no}}<!--
el valor de P2699(URL) o P953(text complet) de l'ítem on apunta el statement de la P1026 de la persona -->
|{{#invoke:wikidades| claim | property=P1026 | qualifier=P1026/P2699 OR P1026/P953
|list=false|formatting=table |rowformat=$1
|rowsubformat1=$1 |editicon=no}}<!--
el valor de P2699(URL) de l'ítem on apunta el qualificador P1026 de la P69 -->
|{{#invoke:wikidades| claim | property= P69/P512
| qualifier=P1026/P2699 |list=false
|formatting=table |rowformat=$1 |rowsubformat1=$1 |editicon=no}}<!--
el valor de P953(text complet) de l'ítem on apunta el qualificador P1026 de la P69 -->
|{{#invoke:wikidades| claim | property= P69/P512 | qualifier=P1026/P953
|list=false |formatting=table |rowformat=$1 |rowsubformat1=$1 |editicon=no}}
}}
}} }} }}
| tesi_any = {{#ifeq:{{{tesi|{{{tesi_any|}}}}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{tesi|}}} | {{{tesi_any|}}}
|{{#ifexpr:{{#invoke:wikidata|numStatements|P1026}} > 1|<!-- skip. Is in bloc_tesi
--><!-- Opcions: qualifi. P577(data public.) o P571(data creac.) de statement de P1026 de la persona -->
|{{if empty|{{#invoke:wikidades| claim | property=P1026 |list=false | qualifier= P577 OR P571
| formatting=table |rowformat=$1}}
<!-- el valor de P577(data public.) o P571(data creac.) de l'ítem on apunta la P1026 de la persona -->
|{{#invoke:wikidades| claim | property=P1026 | qualifier= P1026/P577 OR P1026/P571
|list=false| formatting=table |rowformat=$1|colformat1=Y}}
<!-- el valor de P577(data public.) o P571(data creac.) de l'ítem on apunta el qualificador P1026 de la P512 o P69 -->
|{{#invoke:wikidades| claim | property= P69/P512 | formatting=table
|qualifier=P1026/P577 OR P1026/P571 |list=false |rowformat=$1|colformat1=Y}}
}}
}} }} }}
| direccio_tesi = {{#ifeq:{{{tesi|{{{direccio_tesi|}}}}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{tesi|}}} | {{{direccio_tesi|}}}
|{{#ifexpr:{{#invoke:wikidata|numStatements|P1026}} > 1|<!-- skip. Is in bloc_tesi
-->|{{if empty|{{#invoke:wikidata | claim | property=P184 |list=firstrank }}
|{{#invoke:wikidata | claim | property=P1026 | qualifier=P184 |list=firstrank }}
|{{#invoke:wikidades | claim | property=P1026 | qualifier=P1026/P184 |list=false
| formatting=table |rowformat=$1 }}
|{{#invoke:wikidata | claim | property=P69 | qualifier=P184 |list=firstrank }}
|{{#invoke:wikidata | claim | property= P512/P69
| qualifier=P1026/P184 |list=false }}
}}
}} }} }}
| conegut_per = {{{conegut_per|}}}
| etiqueta_camp_treball = {{#if:{{{etiqueta_camp_treball|}}} | {{{etiqueta_camp_treball|}}} }}
| camp_treball = {{#invoke:wikidata | claim | property=P101 |list=firstrank |value={{{camp_treball|}}}
|formatting=ucfirst }}
| lloc_treball = {{#invoke:wikidades | claim | property=P937 |value={{{lloc_treball|}}}
|qualifier=P580| qualifier2=P582 |formatting = table
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1|sorting=-1 |colformat0=ucfirst |colformat1=Y |colformat2=Y}}
| etiqueta_ocupacio= {{{etiqueta_ocupacio|{{{l_occupation|}}}}}}
| ocupacio = {{#invoke:wikidades | claim | property=P106 |list=firstrank |value={{{ocupacio|}}}
|qualifier=P580| qualifier2=P582 |formatting = table |separator={{·}}|conjunction={{·}}
|rowformat= $0<small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{!}}obre= ({{))}}</small>
|tablesort=1|sorting=-1 |case0=gender |colformat1=Y |colformat2=Y}}
| etiqueta_epoca = {{if empty|{{{etiqueta_epoca|}}}|Època}}
| epoca = {{#invoke:wikidata | claim | property=P2348 |list=firstrank |value={{{epoca|}}}
|formatting=ucfirst }}
| periode_actiu = {{#ifeq:{{{periode_actiu|}}}|NONE|<!-- no es vol WD
-->|{{#if: {{{periode_actiu|}}} | {{{periode_actiu|}}}
|{{FormatData deireadh tosach|inici=P2031 | final=P2032 |lloc=P276
|item={{{item|}}}|lang={{{lang|}}} }} }}
}}
<!-- En aquesta versió 2.0, organitzacio, mitjans i ocupador són sinònims i, per tant, excloents entre si.
Fer servir un o altre paràmetre permet la compatibilitat amb plantilles antigues i determina el nom de l'etiqueta que es mostrarà,
llevat que es vulgui informar un altre contingut manualment mitjançant "etiqueta_organitzacio", que és prioritari a qualsevol altre .
-->
| etiqueta_organitzacio = {{{etiqueta_organitzacio|{{{l_employer|}}}}}}
| ocupador = {{#invoke:wikidades | claim | property=p108 |value={{{ocupador|}}}
|qualifier =P580 |qualifier2=P582 |formatting = table
|qualifier3=P39 |rowsubformat3=, $3 |case3=gender
|qualifier4=P2868 |rowsubformat4=, $4 |case4=gender
|qualifier5=P361 |rowsubformat5=, $5
|qualifier6=P1534 |rowsubformat6= $6
|rowformat= $0$3$4$5 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}$6</small>
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y}}
| organitzacio = {{{organitzacio|}}}
| mitjans = {{{mitjans|}}}
| agent = {{#invoke:wikidata | claim | property=P1875 |list=firstrank |value={{{agent|}}}
|formatting=ucfirst }}
|cronologia = {{#ifeq:{{{cronologia|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{cronologia|}}}|{{{cronologia|}}}
|{{if then show|{{#invoke:wikidades |claim
|formatting=table |tablesort=1/2 |sorting=-1
|property=P793 |blacklist0=Q182020<!-- extravehicular activity in astronaut block -->
|qualifier =P580 or P793/P580 or P585 or P793/P585<!-- start date or date -->
|qualifier2=P582 or P793/P582<!-- end date -->
|qualifier3=P710 or P1346 or P3279 or P748 or P1598<!-- participant, appointed by/ consecrator -->
|qualifier4=P276<!-- location -->
|qualifier5=P518<!-- apply to-->
|qualifier6=P770<!-- cause destruct.-->
|qualifier7=P828<!-- has caused -->
|separator=</tr><tr>|conjunction=</tr><tr>
|rowsubformat1=$1$2
|rowsubformat2=-$2
|rowsubformat3=, per $3
|rowsubformat4= ($4)
|rowsubformat5=: $5
|rowsubformat6=<br/>{{GetLabelFix|P770|lang={{{lang|}}}}}: $6
|rowsubformat7=<br/>{{GetLabelFix|P828|lang={{{lang|}}}}}: $7
|rowformat=<td style="background: #eeeeee;"><small>$1</small></td><td>$0$5$4$3$6$7 }}
|<!-- no show -->|<tr>|</tr>
}} }} }}
| obres_notables = {{#ifeq:{{{obres_notables|{{{millors_films|}}}}}}|NONE|<!-- no es vol WD
-->|{{#if: {{{obres_notables|{{{millors_films|}}}}}} | {{{obres_notables|{{{millors_films|}}}}}}
|{{#iferror:{{#ifexpr:{{#invoke:wikidata|numStatements|P800|item={{{item|}}}}}<20<!-- limitat a 20 -->
|{{#invoke:wikidades | claim | property=P800 |formatting = table
| qualifier= P571 OR P577 OR P585 OR P800/P571 OR P800/P577
OR P800/P1191 OR P800/P580
| qualifier2= P800/P582
| rowformat =*$1 $0 |rowsubformat1=<small>($1$2)</small>
| rowsubformat2=-$2
| tablesort=1 |colformat1=Y |colformat2=Y |separator=</br> }}
|{{#invoke:wikidades | claim
|property=P800
|qualifier= P571 OR P577 OR P585 OR P800/P571 OR P800/P577 OR P800/P1191 OR P800/P580
|qualifier2= P800/P582
|formatting = table |list=false
|rowformat =*$1 $0../... {{#invoke:wikidata|numStatements|P800|item={{{item|}}}}}+
|rowsubformat1=<small>($1$2)</small> |rowsubformat2=-$2
|tablesort=1 |colformat1=Y |colformat2=Y |separator=</br> }}
}} }} }} }}
| arxius = {{#invoke:wikidades | claim | property=P485 |formatting = table |value ={{{arxius|}}}
| qualifier= P217 |qualifier2=P6224 |qualifier3=P973 |qualifier4=P518
| rowformat =* $0$2 $4 $1|colformat1=[$3 $1] |separator=</br>
| rowsubformat2=, $2
| rowsubformat4={{#ifeq:{{dir|{{{lang|}}}}}|rtl|←|→}} $4 }}
| trimmid = {{#ifeq:{{{trimmid|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{trimmid|}}} | {{{trimmid|}}}
|{{#if:{{#invoke:wikidades|validProperty|P2067|item={{{item|}}}}}
| {{#invoke:wikidades | claim | property=P2067 |list=false
|value={{{trimmid|}}}| formatting=unitcode | convert=default }}
}} }} }}
| yrjid = {{#ifeq:{{{yrjid|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{yrjid|}}} | {{{yrjid|}}}
|{{#if:{{#invoke:wikidades|validProperty|P2048|item={{{item|}}}}}
| {{#invoke:wikidades | claim | property=P2048 |list=false
|value={{{yrjid|}}}| formatting=unitcode | convert=default }}
}} }} }}
| towshan = {{{towshan|}}}
| ulls = {{#invoke:wikidata | claim | property=P1340 |list=firstrank |value={{{ulls|}}}
|formatting=ucfirst }}
| cabells = {{#invoke:wikidata | claim | property=P1884 |list=firstrank |value={{{cabells|}}}
|formatting=ucfirst }}
| genere = {{#invoke:wikidata | claim | property=P136 | value= {{{genere|}}} |formatting=ucfirst }}
| moviment = {{#invoke:wikidata | claim | property=P135 | value= {{{moviment|}}} |formatting=ucfirst }}
| cataleg_raonat = {{#invoke:wikidades | claim
|formatting=table |list=firstrank
|property= P9969 |qualifier= P585 or P9969/P577
|rowformat=$0 $1 |rowsubformat1=<small>($1)</small>
| value={{{cataleg_raonat|}}} }}
| estil = {{{estil|}}}
| instrument = {{#invoke:wikidata | claim | property=P1303 | value={{{instrument|}}}
|formatting=ucfirst }}
<!-- BLOC MILITAR -->
| extensio_carrera_militar = <!-- posar "yes" quan tinguen dades militars en un "no exclusivament militar" per aconseguir una capçalera de "carrera militar -->
| lleialtat = {{#invoke:wikidata | claim | property=P945 | value={{{ammys|}}}
|formatting=ucfirst |conjunction=<br/> |separator=<br/>}}
| arma = {{#invoke:wikidata | claim | property=P241 | value={{{arma|}}}
|formatting=ucfirst }}
| rang = {{#invoke:wikidades | claim | property=P410 | value={{{rang|}}}
|qualifier=P580|qualifier2=P582|formatting = table
| rowformat = $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1 |colformat1=Y |colformat2=Y }}
| unitat = {{{unitat|}}}
| comandaments = {{#invoke:wikidata | claim | property=P598 | value={{{comandaments |}}}
|formatting=ucfirst }}
| batalles = {{#invoke:wikidata | claim | property=P607 | value={{{batalles|}}}
|formatting=ucfirst }}
| victories = {{{victories|}}}
| periode_actiu_militar = {{{periode_actiu_militar|}}}
| temps_espai = {{#invoke:wikidata | claim | property=P2873 | formatting=duration |value={{{temps_espai|}}} }}
| eva1 = {{#invoke:wikidades |claim |value={{{eva1|}}}
|formatting=table |tablesort=1/2 |sorting=-1
|property=P793 |whitelist0=Q182020<!-- extravehicular activity -->
|qualifier=P585<!-- date -->
|qualifier2=P580<!-- start date -->
|qualifier3=P582<!-- end date -->
|qualifier4=P518 or P642 <!-- apply to-->
|qualifier5=P1114<!-- quantity -->
|qualifier6=P2047 or P2873 <!-- durada -->
|rowsubformat1=$1
|rowsubformat2=$2-$3
|rowsubformat4=$4:
|rowsubformat6= ($6) |colformat6=duration
|rowformat=$1$2$4$5$6 }}
| tripulacio = {{{tripulacio|}}}
| missio_espacial = {{#ifeq:{{{insignia_missio|}}} |NONE
|{{#invoke:wikidata | claim
|property=P450
|value={{{missio_espacial|}}}
|formatting=ucfirst }}
|{{#invoke:wikidades | claim
|property=P450
|qualifier=P450/P154 or P450/P94 |qualifier2=P450
|value={{{missio_espacial|}}}
|formatting=table
<!-- |separator=, -->
|rowformat = {{nowrap|$1$0}} |rowsubformat1 =[[File:$1|18px|link=$2]]–}}
}}
| altres_ocupacions = {{{altres_ocupacions|{{{altres_carrecs|}}}}}}
<!-- Grup d'humans -->
|grup_humans = {{#if: {{#invoke:wikidades |claim |formatting=table |property=P31 |rowformat=$0
|whitelist0= Q16334295/Q14073567}}
|{{#invoke:wikidades |claim |formatting=table |property=P527
|qualifier = P527/P19 |rowsubformat1=$1, |
|qualifier2 = P527/P20 |rowsubformat2=$2,
|qualifier3 = P527/P569 |qualifier4 =P527/P570
|qualifier5 = P527/P106 |rowsubformat5=. $5
|qualifier6 = P527/P411 |rowsubformat6=. $6
|qualifier7 = P527/P841 |rowsubformat7= {{small|($7)}}
|qualifier8 = P527/P31|whitelist8= Q5
<!-- |qualifier9 = P527 |colformat9= raw -->
|case5=gender |case6=gender |itemgender=P527
|colformat5=ucfirst |colformat6=ucfirst
|rowformat= $0 ($1$3 - $2$4)$5$6$7 |separator=<hr>}} }}
<!-- |label12=tipus -->
|grup_tipus = {{#if: {{#invoke:wikidades |claim |formatting=table |property=P31 |rowformat=$0
|whitelist0= Q16334295/Q14073567}}
|{{#invoke:wikidades |claim |formatting=table |property=P31
|rowformat=$0 |blacklist0=Q16334295}}
}}
<!-- religiosos -->
| enaltiment = {{#ifeq:{{{enaltiment|}}}|NONE|<!-- no fer res
-->|{{#if:{{{enaltiment|}}} | {{{enaltiment|}}}
| {{#if:{{#property:P411|from={{{item|}}} }} | {{GetLabelFix|Q107292093|lang={{{lang|}}}}}}}
}} }}
| venerat_a = {{#invoke:wikidata | claim |property=P1049
|value= {{{venerat_a|{{{venerat_en|}}}}}} |list=firstrank}}
<!-- Si no hi ha informació manual de beatificació/canonització, construeix llista des de WD, else passa totes les dades manuals -->
| llista_enaltiments = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} |<!-- entrada manual, no fer servir P411
-->| {{#ifeq:{{{enaltiment|}}}|NONE|<!-- no fer res
-->| {{#invoke:wikidades |claim |formatting=table | case=gender
|property=P411 |qualifier=P585 |qualifier2=P1027 |qualifier3=P276
|rowformat= *$1 $0$2 $3 |rowsubformat1 = $1 -
| rowsubformat3= ($3) | rowsubformat2=, {{lc:{{GetLabelFix|P748|lang={{{lang|}}}}}}} $2
|colformat1 = Y |tablesort=1|sorting=-1}}
}} }}
<!-- informació manual de beatificació/canonització -->
| data_beatificacio = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{data_beatificacio|}}} }}
| lloc_beatificacio = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{lloc_beatificacio|}}} }}
| beatificat_per = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{beatificat_per|}}} }}
| data_canonitzacio = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{data_canonitzacio|}}} }}
| lloc_canonitzacio = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{lloc_canonitzacio|}}} }}
| canonitzat_per = {{#if:{{{data_beatificacio|}}}{{{data_canonitzacio|}}} | {{{canonitzat_per|}}} }}
| lloc_pelegrinatge = {{#invoke:wikidata | claim | property=P5873 | value={{{lloc_pelegrinatge|}}} |list=firstrank
|formatting=ucfirst }}
| festivitat = {{#invoke:wikidades | claim | property=P841 |qualifier = P642 OR P140
|formatting=table |list=firstrank | value={{{festivitat|}}}
| rowformat=$0 $1 |rowsubformat1 =($1) |colformat1=ucfirst}}
| fets_destacables = {{{fets_destacables|}}}
| iconografia = {{#invoke:wikidata | claim | property=P4185 | value={{{iconografia|}}} |list=firstrank
|formatting=ucfirst }}
| patronatge = {{#invoke:wikidata | claim | property=P2925 | value={{{patronatge|}}} |list=firstrank
|formatting=ucfirst }}
| orde = {{#invoke:wikidata | claim | property=P611 | value={{{orde|}}} |list=firstrank
|formatting=ucfirst }}
|ordenacio = {{#invoke:wikidata | claim | property=P611 |list=false
|value={{{ordenacio|}}}| qualifier= P580 OR P585 }}
|consagracio = {{#invoke:wikidades |claim |formatting=table |list=false
|property=P1598 |qualifier= P585 |value={{{consagracio|}}}|
|rowformat=$1 $0 |rowsubformat1=$1, }}
|proclamacio = {{{proclamacio|}}}
| veu = {{#invoke:wikidata | claim | property=P412 | value={{{veu|}}} |list=firstrank
|formatting=ucfirst }}
| notes_veu = {{#invoke:wikidades | claim | property=P1897 |formatting=table |list=firstrank
|qualifier =P2144 |colformat1=unitcode |rowsubformat1=<small> ($1)</small>|rowformat=↑ $0$1}}<br>
{{#invoke:wikidades | claim | property=P1898 |formatting=table |list=firstrank
|qualifier =P2144 |colformat1=unitcode |rowsubformat1=<small> ($1)</small>|rowformat=↓ $0$1}}
| discografica = {{#invoke:wikidades | claim | property=P264 |qualifier= P580 |qualifier2= P582 |tablesort=1
| formatting=table |list=firstrank | value={{{discografica|}}}
| rowformat = $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|colformat0=ucfirst |colformat1=Y |colformat2=Y
}}
| influencies_de = {{#invoke:wikidata | claim | property=P737 | value={{{influencies_de|}}} |list=firstrank
|formatting=ucfirst }}
| influi_en = {{{influi_en|}}}
| mestres = {{#invoke:wikidata | claim | property=P1066 | value={{{mestres|}}} |list=firstrank
|formatting=ucfirst }}
| deixebles = {{#ifeq: {{{deixebles|}}}| NONE
|<!-- no take WD -->
|{{#if: {{{deixebles|}}} | {{{deixebles|}}}
|{{#iferror:{{#ifexpr:{{#invoke:wikidata|numStatements|P802|item={{{item|}}}}}<25<!-- limit 25 -->
|{{#invoke:wikidata | claim | property=P802 | value={{{deixebles|}}} |list=firstrank
|formatting=ucfirst }}
|{{#invoke:wikidata | claim
|property=P802 | value={{{deixebles|}}} |list=false
|formatting=$1../... {{#invoke:wikidata|numStatements|P802|item={{{item|}}}}}+}}
}} }} }} }}
| orquestres = {{{orquestres|}}}
| artistes_relacionats = {{#invoke:wikidades | claim |property=P1327 |formatting = table |tablesort=1
|qualifier =P580 or P582 |rowsubformat1=<small>($2–$3)</small>
|qualifier2=P580|qualifier3=P582 |colformat2=Y |colformat3=Y
|qualifier4=P1416 |rowsubformat4=: $4
|rowformat = $0$4 $1 |value={{{artistes_relacionats|}}} }}
| instruments_destacats = {{{instruments_destacats|}}}
| cataleg = {{{cataleg|}}}
| director_musical = {{#invoke:wikidata | claim | property=P3300 | value={{{director_musical|}}}
|list=firstrank}}
| sotsdirector_musical = {{{sotsdirector_musical|}}}
| membres = {{{membres|}}}
| membres_anteriors = {{{membres_anteriors|}}}
| repertori = {{{repertori|}}}
| trajectoria = {{{trajectoria|}}}
| papers = {{{papers|}}}
| series = {{{series|}}}
| films = {{{films|}}}
<!-- La diferència entre "altres_noms" i "alies" és que el primer són formes diferents amb que se li coneix i tenen versió idiomàtica (Ex: Jesús, Crist, Fill de Déu,..)
mentre que els pseudònims acostumen a ser noms artístics i no es tradueixen.
Alhora, els pseudònims poden ser els "noms de ploma" amb que signen els autores literaris o l'àlies o malnom tradicional. -->
| altres_noms = {{#invoke:Wikidades | claim | formatting=table |list=firstrank |value={{{altres_noms|}}}
| property=P2561 |qualifier=P2553 |qualifier2= P580 |qualifier3= P582
|rowformat=$0$1 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$2{{!}}fi{{=}}$3{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|rowsubformat1=as $1
|tablesort=2|sorting=1 |colformat2=Y |colformat3=Y}}
| indica_alies_ploma = {{#if:{{{alies|}}} {{{nom_ploma|}}} |<!-- si hi ha algun dels dos paràmetres manuals, saltar tractament WD
-->|{{#if: {{#invoke:Wikidades |claim |formatting=table |property=P106 |rowformat=$0
|whitelist0= Q36180<!-- escriptor -->/Q18844224<!-- escriptor c.ficció
-->/Q15980158<!-- escriptor no ficció
-->/Q10297252<!-- escriptor n.policiaca-->/Q1930187<!-- periodista
-->/Q6051619<!-- periodista opinió -->Q6625963<!-- novel·lista
-->/Q11774202<!-- assagista -->/Q49757<!-- poeta -->}}
|ploma|alies}}
}}
| alies = {{#ifeq:{{{ennym_keirdey|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{ennym_keirdey|}}}|{{{ennym_keirdey|}}}<!-- Si manual, agafar-lo -->
|{{#if:{{{nom_ploma|}}} |<!-- si hi ha nom_ploma manual, saltar tractament WD
-->|{{#invoke:Wikidades | claim | formatting=table |list=firstrank
| property=P742 |qualifier=P2553 |qualifier2= P580 |qualifier3= P582
|rowformat=$0$1 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$2{{!}}fi{{=}}$3{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|rowsubformat1=as $1
|tablesort=2|sorting=1 |colformat2=Y |colformat3=Y}}
}}
}}
}}
| nom_ploma = {{#ifeq:{{{nom_ploma|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{nom_ploma|}}}|{{{nom_ploma|}}}<!-- Si manual, agafar-lo -->
}}
}}
<!--
_______________________________
Es va eliminar el tractament de P1412 per desacord amb contingut generalitzat a WD. en el seu lloc es va agafar P103.
Veure [[Tema:Tt6g5ysw6tuwqk5u]]
Posteriorment es va decidir tornar a P1412, però no per defecte sinó a petició mitjançant "siWD" com a valor de paràmetre -->
| llengua = {{#ifeq:{{{çhengey|}}}|NONE|<!-- no es vol WD
-->|{{#invoke:wikidata | claim | property=P1412 |list=firstrank |formatting=ucfirst |separator={{·}}|conjunction={{·}}}}
|{{{çhengey|}}}
}}
| llengua_materna = {{#ifeq:{{{çhengey_ghooghyssagh|}}}|NONE|
|{{#invoke:wikidata | claim | property=P103 | value={{{çhengey_ghooghyssagh|}}} |list=firstrank}} }}
| editor = {{{editor|}}}
| programes = {{{programes|}}}
| primeres_obres = {{{primeres_obres|}}}
| art = {{{art|}}}
| obres = {{{obres|}}}
| principals_projectes = {{{principals_projectes|{{{principals_dissenys|}}}}}}
| estudiants_doctorals = {{#invoke:wikidata | claim | property=P185 | value={{{estudiants_doctorals|}}}
|list=firstrank |formatting=ucfirst }}
| estudiants_notables = {{{estudiants_notables|}}}
| autor_abrev_bot = {{#invoke:wikidata | claim | property=P428 | value={{{autor_abrev_bot|}}}
|list=false}}
| autor_abrev_zoo = {{#invoke:wikidata | claim | property=P835 | value={{{autor_abrev_zoo|}}}
|list=false}}
| interessos = {{#invoke:wikidata | claim | property=P2650 | value={{{interessos|}}}
|list=firstrank |formatting=ucfirst }}
| idees = {{{idees|}}}
| opositors = {{{opositors|}}}
| titol_personal = {{#invoke:wikidades | claim | property=P97| value={{{titol_personal|}}}
|qualifier=P580| qualifier2=P582 |formatting = table
|rowformat= $0 <small>{{((}}Format start end{{!}}$1{{!}}$2<!--
-->{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|colformat0=ucfirst |case0=gender
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y}}
| titol_escacs = {{#invoke:wikidades | claim | property=P2962 |qualifier=P585 OR P580 | formatting=table
|list=firstrank | value={{{titol_escacs|}}} |tablesort=1
|rowformat=$0 $1 |rowsubformat1=($1) |colformat0=ucfirst |colformat1=Y}}
| extensio_carrecs_successoris =
{{#ifeq:{{{carrec|{{{P39|}}}}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{extensio_carrecs_successoris|}}} | {{{extensio_carrecs_successoris|}}}<!-- ve preparat -->
|{{#if:{{{carrec|}}}{{{carrec2|}}}{{{carrec3|}}}{{{carrec4|}}}{{{carrec5|}}}{{{carrec6|}}}
{{{carrec7|}}}{{{carrec8|}}}{{{carrec9|}}}{{{carrec10|}}}
|<!-- Munta blocs de càrrecs successoris manuals si hi ha alguna dada manual
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{carrec|}}}
| w_ordre = {{{ordre|}}}
| w_escut_carrec = {{{escut_carrec|}}}
| w_inici = {{{inici|{{{term_start|}}}}}}
| w_final = {{{final|{{{term_end|}}}}}}
| w_predecessor = {{{predecessor|}}}
| w_successor = {{{successor|}}}
| w_junt_a = {{{junt_a|}}}
| w_nominat = {{{nominat|}}}
| w_designat = {{{designat|}}}
| w_a_etiqueta = {{{a_etiqueta|}}}
| w_a_nom = {{{a_nom|}}}
| w_b_etiqueta = {{{b_etiqueta|}}}
| w_b_nom = {{{b_nom|}}}
| w_e_etiqueta = {{{e_etiqueta|}}}
| w_e_nom = {{{e_nom|}}}
| w_f_etiqueta = {{{f_etiqueta|}}}
| w_f_nom = {{{f_nom|}}}
| w_gabinet = {{{gabinet|}}}
| w_oponents = {{{oponents|}}}
| w_k_etiqueta = {{{k_etiqueta|}}}
| w_k_nom = {{{k_nom|}}}
| w_l_etiqueta = {{{l_etiqueta|}}}
| w_l_nom = {{{l_nom|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec2|{{{office2|{{{carrec2|{{{order2|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec2|{{{escut_carrec2|}}}}}}
| w_inici = {{{inici2|{{{term_start2|}}}}}}
| w_final = {{{final2|{{{term_end2|}}}}}}
| w_predecessor = {{{predecessor2|}}}
| w_successor = {{{successor2|}}}
| w_junt_a = {{{junt_a2|}}}
| w_nominat = {{{nominat2|}}}
| w_designat = {{{designat2|}}}
| w_a_etiqueta = {{{a_etiqueta2|}}}
| w_a_nom = {{{a_nom2|}}}
| w_b_etiqueta = {{{b_etiqueta2|}}}
| w_b_nom = {{{b_nom2|}}}
| w_e_etiqueta = {{{e_etiqueta2|}}}
| w_e_nom = {{{e_nom2|}}}
| w_f_etiqueta = {{{f_etiqueta2|}}}
| w_f_nom = {{{f_nom2|}}}
| w_gabinet = {{{gabinet2|}}}
| w_oponents = {{{oponents2|}}}
| w_k_etiqueta = {{{k_etiqueta2|}}}
| w_k_nom = {{{k_nom2|{{{k_nom 2|}}}}}}
| w_l_etiqueta = {{{l_etiqueta2|}}}
| w_l_nom = {{{l_nom2|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec3|{{{office3|{{{carrec3|{{{order3|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec3|{{{escut_carrec3|}}}}}}
| w_inici = {{{inici3|{{{term_start3|}}}}}}
| w_final = {{{final3|{{{term_end3|}}}}}}
| w_predecessor = {{{predecessor3|}}}
| w_successor = {{{successor3|}}}
| w_junt_a = {{{junt_a3|}}}
| w_nominat = {{{nominat3|}}}
| w_designat = {{{designat3|}}}
| w_a_etiqueta = {{{a_etiqueta3|}}}
| w_a_nom = {{{a_nom3|}}}
| w_b_etiqueta = {{{b_etiqueta3|}}}
| w_b_nom = {{{b_nom3|}}}
| w_e_etiqueta = {{{e_etiqueta3|}}}
| w_e_nom = {{{e_nom3|}}}
| w_f_etiqueta = {{{f_etiqueta3|}}}
| w_f_nom = {{{f_nom3|}}}
| w_gabinet = {{{gabinet3|}}}
| w_oponents = {{{oponents3|}}}
| w_k_etiqueta = {{{k_etiqueta3|}}}
| w_k_nom = {{{k_nom3|}}}
| w_l_etiqueta = {{{l_etiqueta3|}}}
| w_l_nom = {{{l_nom3|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec4|{{{office4|{{{carrec4|{{{order4|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec4|{{{escut_carrec4|}}}}}}
| w_inici = {{{inici4|{{{term_start4|}}}}}}
| w_final = {{{final4|{{{term_end4|}}}}}}
| w_predecessor = {{{predecessor4|}}}
| w_successor = {{{successor4|}}}
| w_junt_a = {{{junt_a4|}}}
| w_nominat = {{{nominat4|}}}
| w_designat = {{{designat4|}}}
| w_a_etiqueta = {{{a_etiqueta4|}}}
| w_a_nom = {{{a_nom4|}}}
| w_b_etiqueta = {{{b_etiqueta4|}}}
| w_b_nom = {{{b_nom4|}}}
| w_e_etiqueta = {{{e_etiqueta4|}}}
| w_e_nom = {{{e_nom4|}}}
| w_f_etiqueta = {{{f_etiqueta4|}}}
| w_f_nom = {{{f_nom4|}}}
| w_gabinet = {{{gabinet4|}}}
| w_oponents = {{{oponents4|}}}
| w_k_etiqueta = {{{k_etiqueta4|}}}
| w_k_nom = {{{k_nom4|}}}
| w_l_etiqueta = {{{l_etiqueta4|}}}
| w_l_nom = {{{l_nom4|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec5|{{{office5|{{{carrec5|{{{order5|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec5|{{{escut_carrec5|}}}}}}
| w_inici = {{{inici5|{{{term_start5|}}}}}}
| w_final = {{{final5|{{{term_end5|}}}}}}
| w_predecessor = {{{predecessor5|}}}
| w_successor = {{{successor5|}}}
| w_junt_a = {{{junt_a5|}}}
| w_nominat = {{{nominat5|}}}
| w_designat = {{{designat5|}}}
| w_a_etiqueta = {{{a_etiqueta5|}}}
| w_a_nom = {{{a_nom5|}}}
| w_b_etiqueta = {{{b_etiqueta5|}}}
| w_b_nom = {{{b_nom5|}}}
| w_e_etiqueta = {{{e_etiqueta5|}}}
| w_e_nom = {{{e_nom5|}}}
| w_f_etiqueta = {{{f_etiqueta5|}}}
| w_f_nom = {{{f_nom5|}}}
| w_gabinet = {{{gabinet5|}}}
| w_oponents = {{{oponents5|}}}
| w_k_etiqueta = {{{k_etiqueta5|}}}
| w_k_nom = {{{k_nom5|}}}
| w_l_etiqueta = {{{l_etiqueta5|}}}
| w_l_nom = {{{l_nom5|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec6|{{{office6|{{{carrec6|{{{order6|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec6|{{{escut_carrec6|}}}}}}
| w_inici = {{{inici6|{{{term_start6|}}}}}}
| w_final = {{{final6|{{{term_end6|}}}}}}
| w_predecessor = {{{predecessor6|}}}
| w_successor = {{{successor6|}}}
| w_junt_a = {{{junt_a6|}}}
| w_nominat = {{{nominat6|}}}
| w_designat = {{{designat6|}}}
| w_a_etiqueta = {{{a_etiqueta6|}}}
| w_a_nom = {{{a_nom6|}}}
| w_b_etiqueta = {{{b_etiqueta6|}}}
| w_b_nom = {{{b_nom6|}}}
| w_e_etiqueta = {{{e_etiqueta6|}}}
| w_e_nom = {{{e_nom6|}}}
| w_f_etiqueta = {{{f_etiqueta6|}}}
| w_f_nom = {{{f_nom6|}}}
| w_gabinet = {{{gabinet6|}}}
| w_oponents = {{{oponents6|}}}
| w_k_etiqueta = {{{k_etiqueta6|}}}
| w_k_nom = {{{k_nom6|}}}
| w_l_etiqueta = {{{l_etiqueta6|}}}
| w_l_nom = {{{l_nom6|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec7|{{{office7|{{{carrec7|{{{order7|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec7|{{{escut_carrec7|}}}}}}
| w_inici = {{{inici7|{{{term_start7|}}}}}}
| w_final = {{{final7|{{{term_end7|}}}}}}
| w_predecessor = {{{predecessor7|}}}
| w_successor = {{{successor7|}}}
| w_junt_a = {{{junt_a7|}}}
| w_nominat = {{{nominat7|}}}
| w_designat = {{{designat7|}}}
| w_a_etiqueta = {{{a_etiqueta7|}}}
| w_a_nom = {{{a_nom7|}}}
| w_b_etiqueta = {{{b_etiqueta7|}}}
| w_b_nom = {{{b_nom7|}}}
| w_e_etiqueta = {{{e_etiqueta7|}}}
| w_e_nom = {{{e_nom7|}}}
| w_f_etiqueta = {{{f_etiqueta7|}}}
| w_f_nom = {{{f_nom7|}}}
| w_gabinet = {{{gabinet7|}}}
| w_oponents = {{{oponents7|}}}
| w_k_etiqueta = {{{k_etiqueta7|}}}
| w_k_nom = {{{k_nom7|}}}
| w_l_etiqueta = {{{l_etiqueta7|}}}
| w_l_nom = {{{l_nom7|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec8|{{{office8|{{{carrec8|{{{order8|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec8|{{{escut_carrec8|}}}}}}
| w_inici = {{{inici8|{{{term_start8|}}}}}}
| w_final = {{{final8|{{{term_end8|}}}}}}
| w_predecessor = {{{predecessor8|}}}
| w_successor = {{{successor8|}}}
| w_junt_a = {{{junt_a8|}}}
| w_nominat = {{{nominat8|}}}
| w_designat = {{{designat8|}}}
| w_a_etiqueta = {{{a_etiqueta8|}}}
| w_a_nom = {{{a_nom8|}}}
| w_b_etiqueta = {{{b_etiqueta8|}}}
| w_b_nom = {{{b_nom8|}}}
| w_e_etiqueta = {{{e_etiqueta8|}}}
| w_e_nom = {{{e_nom8|}}}
| w_f_etiqueta = {{{f_etiqueta8|}}}
| w_f_nom = {{{f_nom8|}}}
| w_gabinet = {{{gabinet8|}}}
| w_oponents = {{{oponents8|}}}
| w_k_etiqueta = {{{k_etiqueta8|}}}
| w_k_nom = {{{k_nom8|}}}
| w_l_etiqueta = {{{l_etiqueta8|}}}
| w_l_nom = {{{l_nom8|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec9|{{{office9|{{{carrec9|{{{order9|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec9|{{{escut_carrec9|}}}}}}
| w_inici = {{{inici9|{{{term_start9|}}}}}}
| w_final = {{{final9|{{{term_end9|}}}}}}
| w_predecessor = {{{predecessor9|}}}
| w_successor = {{{successor9|}}}
| w_junt_a = {{{junt_a9|}}}
| w_nominat = {{{nominat9|}}}
| w_designat = {{{designat9|}}}
| w_a_etiqueta = {{{a_etiqueta9|}}}
| w_a_nom = {{{a_nom9|}}}
| w_b_etiqueta = {{{b_etiqueta9|}}}
| w_b_nom = {{{b_nom9|}}}
| w_e_etiqueta = {{{e_etiqueta9|}}}
| w_e_nom = {{{e_nom9|}}}
| w_f_etiqueta = {{{f_etiqueta9|}}}
| w_f_nom = {{{f_nom9|}}}
| w_gabinet = {{{gabinet9|}}}
| w_oponents = {{{oponents9|}}}
| w_k_etiqueta = {{{k_etiqueta9|}}}
| w_k_nom = {{{k_nom9|}}}
| w_l_etiqueta = {{{l_etiqueta9|}}}
| w_l_nom = {{{l_nom9|}}}
}}<!--
-->{{WD Kishtey Fys Dooinney/Shellooder oik politickagh
| w_carrec = {{{càrrec10|{{{office10|{{{carrec10|{{{order10|}}}}}}}}}}}}
| w_escut_carrec = {{{escut càrrec10|{{{escut_carrec10|}}}}}}
| w_inici = {{{inici10|{{{term_start10|}}}}}}
| w_final = {{{final10|{{{term_end10|}}}}}}
| w_predecessor = {{{predecessor10|}}}
| w_successor = {{{successor10|}}}
| w_junt_a = {{{junt_a10|}}}
| w_nominat = {{{nominat10|}}}
| w_designat = {{{designat10|}}}
| w_a_etiqueta = {{{a_etiqueta10|}}}
| w_a_nom = {{{a_nom10|}}}
| w_b_etiqueta = {{{b_etiqueta10|}}}
| w_b_nom = {{{b_nom10|}}}
| w_e_etiqueta = {{{e_etiqueta10|}}}
| w_e_nom = {{{e_nom10|}}}
| w_f_etiqueta = {{{f_etiqueta10|}}}
| w_f_nom = {{{f_nom10|}}}
| w_gabinet = {{{gabinet10|}}}
| w_oponents = {{{oponents10|}}}
| w_k_etiqueta = {{{k_etiqueta10|}}}
| w_k_nom = {{{k_nom10|}}}
| w_l_etiqueta = {{{l_etiqueta10|}}}
| w_l_nom = {{{l_nom10|}}}
}}
|<!-- càrrecs des de WD
-->{{WD Kishtey Fys|child=yes|item={{{item|}}}|decat=yes
|data3= <tr>{{#invoke:wikidades |claim |formatting=table
|property=P39 |case0=gender | colformat0=ucfirst
|qualifier = P580 | rowsubformat1 = $1 –
|qualifier2= P582
|qualifier3= P1365 | rowsubformat3=<span style="display:block;margin-top:0;line-height:1.2;">{{#ifeq:{{dir|{{{lang|}}}}}|rtl|→|←}} $3
|qualifier4= P1366 | rowsubformat4= – $4 {{#ifeq:{{dir|{{{lang|}}}}}|rtl|←|→}}</span>
|qualifier5= P768 | rowsubformat5=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P768|lang={{{lang|}}}}}: $5|small}}
|qualifier6= P2715 | rowsubformat6=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P2715|lang={{{lang|}}}|itemgender={{{item|{{#invoke:wikibase|id}}}}}}}: $6|small}}
|qualifier7= P748 OR P1027 | rowsubformat7=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P748|lang={{{lang|}}}|itemgender={{{item|{{#invoke:wikibase|id}}}}}}}: $7|small}}
|qualifier8= P108 OR P2389
|qualifier9= P642
|qualifier10=P1706 | rowsubformat10=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P1706|lang={{{lang|}}}}}: $10}}
|qualifier11=P748
|qualifier12=P158 OR P94 OR P642/P158 OR P642/P94 OR P39/P158 OR P39/P94
| rowsubformat12=[[File:$12|25x30px|link=]]
|qualifier13=P1268 | rowsubformat13={{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P1268|lang={{{lang|}}}}}: $13|small}}<br />
|qualifier14=P708 | rowsubformat14=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P708|lang={{{lang|}}}}}: $14|small}}
|qualifier15=P5054 | rowsubformat15=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P5054|lang={{{lang|}}}}}: $15|small}}
|qualifier16=P1534 | rowsubformat16= {{small|($16)}}
|qualifier17=P2868 | rowsubformat17={{GetLabelFix|P2868|lang={{{lang|}}}}}: $17<br />
|qualifier18=P2937 | rowsubformat18=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P2937|lang={{{lang|}}}}}: $18|small}}
|rowformat=<!-- Position HEADER: Seal image + position + institution -->
<th colspan="2" style="text-align:center;
background-color:{{WD Kishtey Fys/Daaghyn|beashnys}};">$12 $0 $8</th><!--
--><!-- Position DESCRIPTION lines
--><tr><td colspan="2" style="text-align:center;">$13 $17 $1 $2$16<br />$3 $4 $9 $10 $18 $15 $5 $14 $7 $6</td>
|separator=</tr><tr>|conjunction=</tr><tr>
|tablesort=1|sorting=-1}}</tr>
}}
}}
}}
}}
| dades_medaller = {{{dades_medaller|}}}
| partit_politic = {{#invoke:wikidades | claim| property=P102 | value={{{partit_politic|}}}
|qualifier=P580|qualifier2=P582 |formatting = table
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y}}
| membre_de = {{#invoke:wikidades | claim| property=P463 | value={{{membre_de|}}} |formatting = table
|qualifier=P580 OR P585 |qualifier2=P582
|qualifier3=P2868 or P39 |rowsubformat3=($3) |case3=gender
|rowformat= $0 $3 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}$1{{!}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1|sorting=-1 |colformat1=Y |colformat2=Y}}
| etiqueta_dinastia = {{{etiqueta_dinastia|{{{l_family|}}}}}}
| dinastia = {{#invoke:wikidades | claim| property=P53 | value={{{dinastia|}}}
|formatting=ucfirst }}
| conjuge = {{#invoke:wikidades | claim |value={{{conjuge|}}} |formatting = table
| property=P26|qualifier=P580|qualifier2=P582|qualifier3=P1534
| rowformat = $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}$3</small>
|tablesort=1 |colformat1=Y |colformat2=Y|rowsubformat3=, $3}}
| parella = {{#invoke:wikidades | claim |value={{{parella|}}} | property=P451|qualifier=P580|qualifier2=P582
|formatting = table| rowformat = $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1 |colformat1=Y |colformat2=Y}}
| paitçhyn = {{#if:{{#Property:P40}}|{{collapsible list|title=Rolley|{{#invoke:Wikidata | claim | property=P40|formatting = internallink|separator=<br />|conjunction=<br />|value={{{paitçhyn|}}}}}}}}}
| pares = {{{paarantyn|}}}
| pare = {{#invoke:wikidata | claim| property=P22 | value={{{pare|{{{ayr|}}}}}} }}
| mare = {{#invoke:wikidata | claim| property=P25 | value={{{mare|{{{moir|}}}}}} }}
| braaraghyn_shuyraghyn = {{#if:{{#Property:P3373}}|{{collapsible list|title=Rolley
|{{#invoke:Wikidata | claim | property=P3373|value={{{braaraghyn_shuyraghyn|}}}|formatting = internallink|separator=<br />|conjunction=<br />}}}}}}
| lught_mooinjeragh = {{#if:{{#Property:P1038}}|{{collapsible list|title=Rolley|{{#invoke:Wikidata | claim | property=P1038|value={{{lught_mooinjeragh|}}}|formatting = internallink|separator=<br />|conjunction=<br />}}}}}}
| carrecs_judicials = {{#invoke:wikidata | claim| property=P1595 | value={{{carrecs_judicials|}}}
|formatting=ucfirst }}
| condemnes = {{#invoke:wikidades | claim| property=P1399
|qualifier =P1596 |rowsubformat1=<br/><small>→ ($3$1)</small>
|qualifier2=P580 OR P585 |rowsubformat2=<small>($2)</small> |colformat2=Y
|qualifier3=P1114 OR P2047|rowsubformat3=$3 |colformat3=unit |convert3=M
|qualifier4=P582
|rowsubformat4=<br/><small>→ {{GetLabelFix|Q12769393|lang={{{lang|}}}}}: $4$7</small>
|qualifier5=P642 |rowsubformat5= $5
|qualifier6=P1674 |rowsubformat6=<small>$6 </small>
|qualifier7=P1534 |rowsubformat7=, $7<!-- → $4 -->
|formatting = table| value={{{condemnes|}}}
|rowformat = $6$0$5 $2 $1 $4
|tablesort=2 }}
<!--
| situacio_penal = {{#ifeq:{{{situacio_penal|}}}|NONE|
|{{#invoke:wikidata | claim| property=P1596 | value={{{situacio_penal|}}}| item={{{item|}}} }} }}
-->
| monuments = {{{monuments|}}}
| etiqueta_monuments= {{{etiqueta_monuments|{{{l_memorials|}}}}}}
| extensio_guardons = {{{extensio_guardons|}}}
| premis = {{#if:{{#property:P166|from={{{item|}}} }}|{{#invoke:Wikidata | claim | property=P166 |qualifier=P585| qualifier2=P1027 |qualifier3=P1686|formatting=table
|rowformat = {{((}}Sub-item image{{!}}$0{{!}}P2425{{!}}40x20px{{))}} [[{{((}}#invoke:Wikibase{{!}}label{{!}}$0{{))}}]] $2 $1 $3 |rowsubformat1=<small> ($1)</small> |rowsubformat2=: <small>$2</small>|rowsubformat3=: <small>$3</small> | colformat0=raw | colformat2=internallink| separator=<br />}} }}
| imatgeobra = {{{imatgeobra|}}}
| peuobra = {{{peuobra|}}}
| signatura = {{#ifeq:{{{signatura|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{signatura|}}}
|{{InfoboxImage|image= {{{signatura|}}}
|size=220x100px |sizedefault=frameless |upright=1
|suppressplaceholder=yes}}
|{{#invoke:wikidata | claim| property=P109 |formatting= [[File:$1|220x100px]] | list=false}}
}} }}
| escutpeu = {{#ifeq:{{{escutpeu|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{escutpeu|}}}
|{{InfoboxImage|image= {{{escutpeu|}}} |size=100px |sizedefault=frameless
|upright=1 |suppressplaceholder=yes}}
|{{#invoke:wikidata | claim| property= P94/P154 |list=false |formatting= [[File:$1|100px]]}}
}} }}
| lema_escut = {{#ifeq:{{{lema_escut|}}}|NONE|<!-- no es vol WD
-->|{{if empty|{{#if:{{{escutpeu|}}}|{{{lema_escut|}}} }}
|{{#invoke:wikidata | claim| property= P1451 |list=false |formatting=$text ($language)}}
}} }}
<!-- Bloc esportista -->
| nacionalitat_esportiva = {{#invoke:wikidades | claim| property=P1532 |formatting=table
|value={{{ashoonaght_spoyrtoil|}}}
|qualifier=P580|qualifier2=P582 |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| esport = {{#invoke:wikidades | claim| property=P641 | value={{{esport|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| disciplina = {{#invoke:wikidades | claim| property=P2416 | value={{{disciplina|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| classe = {{#invoke:wikidades | claim| property=P2094 | value={{{classe|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| posicio_equip = {{#invoke:wikidata | claim | property=P413 | value={{{posicio_equip|{{{posició|{{{position|}}}}}}}}}
|case=gender |list=firstrank |formatting=ucfirst }}
| lateralitat = {{#invoke:wikidata | claim| property=P552 |list=false
| value={{{lateralitat|}}} |formatting=ucfirst |case=gender }}
| ma_joc = {{#invoke:wikidata | claim | property=P741 | value={{{laue_chloie|}}} |case=gender
|separator=, |conjunction= as }}
| lliga = {{#invoke:wikidata | claim| property=P118 |list=firstrank
| value={{{lliga|}}} |formatting=ucfirst }}
| club_actual = {{{club_actual|{{{clubactual|{{{currentclub|}}}}}}}}}
| dorsal_club = {{#invoke:wikidata | claim| property=P1618 |list=false
| value={{{dorsal_club|{{{numeroclub|{{{clubnumber|}}}}}}}}} }}
| draft = {{#ifeq:{{{draft|{{{draft_equip|}}}}}}|NONE|<!-- no es vol WD
-->|{{if both|{{{draft|}}}|{{{draft_equip|}}}
| {{{draft_equip|}}}, {{{draft|}}}{{#if:{{{draft_any|}}}| ({{{draft_any|}}}) }}<!--
-->|{{#invoke:wikidades | claim | property=P647 | value={{{draft|}}}
|qualifier=P585|qualifier2=P1836 |formatting = table
| rowformat = $0<small>$2 $1</small>|rowsubformat1=($1) |rowsubformat2=, $2 | case2=ordinal
|tablesort=1 }}
}} }}
| lloc_debut = {{{lloc_debut|}}}
| data_debut = {{{data_debut|}}}
| lloc_retirada = {{{lloc_retirada|}}}
| data_retirada = {{{data_retirada|}}}
| copilot = {{#invoke:wikidades | claim | property=P2095 | value={{{copilot|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| entrenador = {{#invoke:wikidades | claim | property=P286 | value={{{entrenador|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| patrocinador = {{#invoke:wikidades | claim | property=P859 | value={{{patrocinador|{{{patrons|}}}}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1 |list=firstrank
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
| patrocinador_material = {{#invoke:wikidades | claim | property=P5995 | value={{{patrocinador_material|}}}
|qualifier=P580|qualifier2=P582 |formatting=table |tablesort=1 |list=firstrank
|rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small> }}
<!--
BLOC RESULTATS ESPORTIUS
-->
| extensio_parametres_esport =
{{#ifeq:{{{P641|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{extensio_parametres_esport|}}}
| {{{extensio_parametres_esport|}}} <!-- Ve d'una pre-infotaula de dades manuals-->
|{{#if:{{#Property:P641|from={{{item|}}}}}
| {{WD Kishtey Fys Dooinney/parameadaryn|bloc=esport | item={{{item|}}}
|titol_escacs= {{{titol_escacs|{{{titol_personal|}}}}}} |elo_max={{{elo_max|}}}
|esport={{#invoke:wikidata | claim| property=P641 | list=false}}
|lang={{{lang|}}} }}
}}<!-- Fi és esportista-->
}}<!-- Fi dades manuals des de pre-infotaula -->
}}
| extensio_carrera_esportiva =
{{#ifeq:{{{P54|}}}|NONE|<!-- no es vol WD
-->|{{#if:{{{extensio_carrera_esportiva|}}}
| {{{extensio_carrera_esportiva|}}} <!-- Ve d'una pre-infotaula de dades manuals-->
|{{#if:{{{equips|}}} | {{{equips|}}}
|{{#if:{{#Property:P54|from={{{item|}}}}} {{#property:P6087|from={{{item|}}} }}
|{{WD Kishtey Fys Dooinney/spoyrt|{{#invoke:wikidata|claim|property=P641 |list=false|formatting=raw}}
|{{{item|}}} | lang={{{lang|}}} }}
}}<!-- Fi hi ha P54 -->
}}<!-- Fi hi ha paràmetre equips -->
}}<!-- Fi dades manuals des de pre-infotaula -->
}}
| extensio_participacio_esdeveniments =
{{#if:{{{extensio_participacio_esdeveniments|}}}
| {{{extensio_participacio_esdeveniments|}}} <!-- manual participant manage pre-infobox -->
| {{#ifeq:{{{participa_en|{{{P1344|}}} }}}|NONE|<!-- no es vol WD
-->|{{#if:{{{participa_en|{{{P1344|}}} }}} | {{{participa_en|{{{P1344|}}} }}}
|{{#if:{{#invoke:wikidata|validProperty|P1344|item={{{item|}}} }}<!--
-->|{{#iferror:{{#ifexpr:{{#invoke:wikidata|numStatements|P1344|item={{{item|}}}}}<25<!--up to 25 -->
|<tr>{{#invoke:wikidades|claim |formatting=table
|tablesort=1 |sorting=-1
|property=P1344
|qualifier=P585 OR P1344/P585 OR P1344/P577 OR P1344/P580
|qualifier2=P1352 |rowsubformat2=($2) |case2=ordinal
|qualifier3=P166 |rowsubformat3= <small>($3)</small>
|qualifier4=P2416 |rowsubformat4=–<small>$4</small>
|rowformat=<td><small>$1</small></td><td>$0$4 $2$3</td>
|separator=</tr><tr>|conjunction=</tr><tr>}}
</tr>
|<tr>{{#invoke:wikidades |claim
|property=P1344
|qualifier=P585 OR P1344/P585 OR P1344/P577 OR P1344/P580
|qualifier2=P1352 |rowsubformat2=($2) |case2=ordinal
|qualifier3=P166 |rowsubformat3= <small>($3)</small>
|qualifier4=P2416 |rowsubformat4=–<small>$4</small>
|formatting=table |list=false
|tablesort=1 |sorting=-1
|rowformat=<td><small>$1</small></td><td>$0$4 $2$3../... 25+</td>
|separator=</tr><tr>|conjunction=</tr><tr>}}
</tr>
}} }} }} }} }} }}
<!--
| extensio_participacio_esdevenimxxx =
{{#ifeq:{{{extensio_participacio_esdeveniments|}}} |NONE|
|{{#if: {{{extensio_participacio_esdeveniments|}}} | {{{extensio_participacio_esdeveniments|}}}
|{{#iferror:{{#ifexpr:{{#invoke:wikidata|numStatements|P1344|item={{{item|}}}}}<21
| {{#invoke:wikidades | claim | property=P800 |formatting = table
| qualifier= P571 OR P577 OR P585 OR P800/P571 OR P800/P577 OR P800/P1191
| rowformat =*$1 $0 |rowsubformat1=<small>($1)</small>
| tablesort=1 |colformat1=Y |separator=</br> }}
| {{#invoke:wikidata|numStatements|P1344|item={{{item|}}}}}
}} }} }} }}
| obres_xxxx = {{#if: {{{extensio_participacio_esdeveniments|}}} | {{{extensio_participacio_esdeveniments|}}}
|{{#iferror:{{#ifexpr:{{#invoke:wikidata|numStatements|P1344|item={{{item|}}}}}<21
|{{#invoke:wikidades | claim | property=P800 |formatting = table
| qualifier= P571 OR P577 OR P585 OR P800/P571 OR P800/P577 OR P800/P1191
| rowformat =*$1 $0 |rowsubformat1=<small>($1)</small>
| tablesort=1 |colformat1=Y |separator=</br> }}
| {{#invoke:wikidata|numStatements|P1344|item={{{item|}}}}}
}} }} }}
-->
| lloc_web = {{#ifeq:{{{lloc_web|{{{web|}}}}}} |NONE|<!-- saltar, no es vol recuperar WD
-->|{{#if:{{{lloc_web|{{{web|}}}}}}
|{{if empty|{{{lloc_web|}}} | {{{web|}}} }}
|{{#if:{{#invoke:wikidata|validProperty|P856|item={{{item|}}} }}
|{{#ifeq:{{#invoke:wikidades |claim |property=P856 or P1581 |list=false |formatting=table
|qualifier=P582 |rowformat=$1 |editicon=no}} | {{somevalue|lang={{{lang|}}}}}<!--
-->|{{#invoke:wikidata |claim |property=P856 or P1581 |list=false |formatting=weblink }}<!--
-->|{{#invoke:wikidades |claim |property=P856 or P1581 |list=false |formatting=table |colformat0=weblink
|qualifier =P582 |rowsubformat1= → $2$3
|qualifier2=P1065 |rowsubformat2=[[File:Cloud download font awesome.svg|15px|link=$2]]
|qualifier3=P2960 |colformat3=Y |rowsubformat3= <small>($3)</small>
|rowformat=$0$1 }}
}}
}} }} }}
| xarxes = {{#ifeq:{{{identificadors|}}}|NONE|<!-- no es vol WD
-->|{{Identifiers | item={{{item|}}} | lang={{{lang|}}}}} }}
| notes = {{{notes|}}}
| color_notes = {{{color_notes|}}}<!--
_________________________________BLOC temporal per depurar continguts manuals de P39 i P166 ______________
-->|compara_carrecs =
{{#if:{{{carrec|}}}{{{carrec2|}}}{{{carrec3|}}}{{{carrec4|}}}{{{carrec5|}}}{{{carrec6|}}} {{{carrec7|}}}{{{carrec8|}}}
{{{carrec9|}}}{{{carrec10|}}}
|{{#if:{{#property:P39 | from={{{item|}}} }}
|{{Caixa desplegable
|border = 0px |color_títol = white
|contingut = {{WD Kishtey Fys |data10=<tr>{{#invoke:wikidades |claim |formatting=table
|property=P39 |case0=gender | colformat0=ucfirst
|qualifier = P580 | rowsubformat1 = $1 –
|qualifier2= P582
|qualifier3= P1365 | rowsubformat3=<br />{{#ifeq:{{dir|{{{lang|}}}}}|rtl|→|←}} $3
|qualifier4= P1366 | rowsubformat4=– $4 {{#ifeq:{{dir|{{{lang|}}}}}|rtl|←|→}}
|qualifier5= P768 | rowsubformat5=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P768|lang={{{lang|}}}}}: $5|small}}
|qualifier6= P2715 | rowsubformat6=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P2715|lang={{{lang|}}}|itemgender={{{item|{{#invoke:wikibase|id}}}}}}}: $6|small}}
|qualifier7= P748 OR P1027 | rowsubformat7=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P748|lang={{{lang|}}}|itemgender={{{item|{{#invoke:wikibase|id}}}}}}}: $7|small}}
|qualifier8= P108 OR P2389
|qualifier9= P642
|qualifier10=P1706 | rowsubformat10=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P1706|lang={{{lang|}}}}}: $10}}
|qualifier11=P748
|qualifier12=P158 OR P94 OR P642/P158 OR P642/P94 OR P39/P158 OR P39/P94
| rowsubformat12=[[File:$12|25x30px|link=]]
|qualifier13=P1268 | rowsubformat13={{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P1268|lang={{{lang|}}}}}: $13|small}}<br />
|qualifier14=P708 | rowsubformat14=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P708|lang={{{lang|}}}}}: $14|small}}
|qualifier15=P5054 | rowsubformat15=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P5054|lang={{{lang|}}}}}: $15|small}}
|qualifier16=P1534 | rowsubformat16= {{small|($16)}}
|qualifier17=P2868 | rowsubformat17={{GetLabelFix|P2868|lang={{{lang|}}}}}: $17<br />
|qualifier18=P2937 | rowsubformat18=<br />{{align|{{#ifeq:{{dir|{{{lang|}}}}}|rtl|right|left}}
|{{GetLabelFix|P2937|lang={{{lang|}}}}}: $18|small}}
|rowformat=<!-- Position HEADER: Seal image + position + institution -->
<th colspan="2" style="text-align:center;
background-color:{{WD Kishtey Fys/daaghyn|beashnys}};">$12 $0 $8</th><!--
--><!-- Position DESCRIPTION lines
--><tr><td colspan="2" style="text-align:center;">$13 $17 $1 $2$16 $3 $4 $9 $10 $18 $15 $5 $14 $7 $6</td>
|separator=</tr><tr>|conjunction=</tr><tr>
|tablesort=1|sorting=-1}}</tr>
}}
}}<!-- fi caixa desplegable P39 -->
}} }}<!-- fi hi ha P39 i carrec(s) -->
{{#if:{{{extensio_guardons|}}}
|{{#if:{{#property:P166 | from={{{item|}}} }}
|{{Ambox
|border = 0px |color_títol = white
|text = {{#invoke:wikidades |claim |formatting=table |case0=gender
|property=P166 |qualifier=P585 | qualifier2=P1686 |qualifier3 =P1027
|qualifier4 =P166/P2425 |qualifier5 =P642 |separator=<br />
|rowformat=* $1 $4 $0$5$2$3
|rowsubformat1=<small>($1)</small>
|rowsubformat2=, {{lcfirst:{{GetLabelFix|P1686|lang={{{lang|}}}}}}} $2
|rowsubformat3= {{GetLabelFix|P1027|lang={{{lang|}}}}} $3
|rowsubformat4=[[File:$4|30px|link=]]
|rowsubformat5= {{lc:{{GetLabelFix|P642|lang={{{lang|}}}}}}} $5.
|tablesort=1 |sorting=-1}}
}}<!-- fi caixa desplegable P166 -->
}} }}<!-- fi hi ha P166 i guardons -->
{{#if:{{{extensio_carrera_esportiva|}}}
|{{#if: {{#property:P54 | from={{{item|}}} }} {{#property:P6087 | from={{{item|}}} }}<!-- equips o entrenador -->
|{{Caixa desplegable
|border = 0px |color_títol = white
|contingut = {{WD Kishtey Fys Dooinney/spoyrt|{{#invoke:wikidata|claim|property=P641 |list=false|formatting=raw}}
|{{{item|}}} | lang={{{lang|}}} }}
}}<!-- fi caixa desplegable P154 -->
}} }}<!-- fi hi ha P54 i guardons -->
<!--
____________________________________ BLOCK of OLD AND DEPRECATED CODE since V20200101 _______________________________
-->
<!-- | lloc_desaparicio = {{{lloc_desaparicio|}}} +++ Anul·lat sense manuals i a WD està com qualifier de P746 +++ -->
<!-- | patrons = {{#ifeq:{{{patrons|}}} |NONE| +++ Anul·lat per integració amb la P859 (patrocinador) +++
|{{#invoke:wikidades | claim | property=P1962 | value={{{patrons|}}}
|qualifier=P580|qualifier2=P582
|formatting=table |rowformat= $0 <small>{{((}}Taishbyn jerrey hoshiaght{{!}}inici{{=}}$1{{!}}fi{{=}}$2{{!}}lang{{=}}{{{lang|}}}{{))}}</small>
|tablesort=1 }} }} -->
<!-- | convoca_internacional = {{#ifeq:{{{convoca_internacional|}}} |NONE| +++ Anul·lat abans de 2019 aprx. +++
|{{#invoke:wikidata | claim| property=P1129 |list=false
| value={{{convoca_internacional|}}} }} }} -->
<!-- | eva2 = {{{eva2|}}} +++ Anul·lat eva1 integra la informació recuperada de WD a la P793 +++ -->
<!-- | supressio_culte +++ Traslladat a P793-esdeveniment significatiu +++ -->
<!-- _______________________ DUE TO LOW OR NULL USE __________________
| peu_veu = {{{peu_veu|}}}
| especialitat = {{{especialitat|}}}
| estudi_arquitectes = {{{estudi_arquitectes|}}}
| principals_edificis = {{{principals_edificis|}}}
| principals_dissenys = {{{principals_dissenys|}}}
| assessorament_academic = {{{assessorament_academic|}}}
| descobriment_cos = {{{descobriment_cos|}}}
| etiqueta_aliats = {{{etiqueta_aliats|}}}
| aliats = {{{aliats|}}}
| etiqueta_rivals = {{{etiqueta_rivals|}}}
| rivals = {{{rivals|}}}
| tematica = {{{tematica|}}}
| mesures = {{{mesures|}}}
| imatge_militar = {{{imatge_militar|}}}
| suprimit_per = {{{suprimit_per|}}}
| continuadors = {{{continuadors|}}}
| era = {{{era|}}}
| regio = {{{regio|}}}
| escola_tradicio = {{{escola_tradicio|}}}
-->
}}{{Ronney rere blein vaaish}}<!-- Parameter check:
-->{{#invoke:TemplatePar
|check
|template= Clowan:WD Kishtey Fys Dooinney
|all=
|opt=
a_etiqueta= a_etiqueta10= a_etiqueta11= a_etiqueta2= a_etiqueta3= a_etiqueta4= a_etiqueta5= a_etiqueta6= a_etiqueta7= a_etiqueta8= a_etiqueta9= a_nom= a_nom10= a_nom11= a_nom2= a_nom3= a_nom4= a_nom5= a_nom6= a_nom7= a_nom8= a_nom9= agent= alçada= ennym_keirdey= altres_noms= alma_mater= alt= altres_ocupacions= arma= art= artistes_relacionats= autor_abrev_bot= autor_abrev_zoo= b_etiqueta= b_etiqueta10= b_etiqueta11= b_etiqueta2= b_etiqueta3= b_etiqueta4= b_etiqueta5= b_etiqueta6= b_etiqueta7= b_etiqueta8= b_etiqueta9= b_nom= b_nom10= b_nom11= b_nom2= b_nom3= b_nom4= b_nom5= b_nom6= b_nom7= b_nom8= b_nom9= batalles= bateig= bust_natural= cabells= capçalera_superior= camp_treball= lloc_treball= carrec= carrec10= carrec11= carrec2= carrec3= carrec4= carrec5= carrec6= carrec7= carrec8= carrec9= carrecs_judicials= casa_reial= cataleg= causa_defuncio= causa_mort= child= ciutadania= comandaments= condemnes= conegut_per= conjuge= coordenades_sepultura= data_defuncio= data_desaparicio= date_ruggyr= boayl_ruggyr= data_naixement= deixebles= <!-- descobriment_cos= --> designat= designat10= designat11= designat2= designat3= designat4= designat5= designat6= designat7= designat8= designat9= dinastia= discografica= e_etiqueta= e_etiqueta10= e_etiqueta11= e_etiqueta2= e_etiqueta3= e_etiqueta4= e_etiqueta5= e_etiqueta6= e_etiqueta7= e_etiqueta8= e_etiqueta9= e_nom= e_nom10= e_nom11= e_nom2= e_nom3= e_nom4= e_nom5= e_nom6= e_nom7= e_nom8= e_nom9= educacio= equips= escut_carrec= escut_carrec10= escut_carrec11= escut_carrec2= escut_carrec3= escut_carrec4= escut_carrec5= escut_carrec6= escut_carrec7= escut_carrec8= escut_carrec9= escutpeu= estil= l_occupation= <!-- estudi_arquitectes= etiqueta_dinastia= etiqueta_ocupacio= etiqueta_organitzacio= alt_signatura= --> etnia= extensio_carrecs_successoris= extensio_carrera_militar= extensio_guardons= extensio_incrustada1= extensio_incrustada2= extensio_incrustada3= extensio_incrustada4= extensio_incrustada5= extensio_noms_farao= f_etiqueta= f_etiqueta10= f_etiqueta11= f_etiqueta2= f_etiqueta3= f_etiqueta4= f_etiqueta5= f_etiqueta6= f_etiqueta7= f_etiqueta8= f_etiqueta9= f_nom= f_nom10= f_nom11= f_nom2= f_nom3= f_nom4= f_nom5= f_nom6= f_nom7= f_nom8= f_nom9= festival_berlin= festival_canes= festival_sant_sebastia= festival_sitges= páistí= seyraanaght= filmfare_awards= films= final= final10= final11= final2= final3= final4= final5= final6= final7= final8= final9= gabinet= gabinet10= gabinet11= gabinet2= gabinet3= gabinet4= gabinet5= gabinet6= gabinet7= gabinet8= gabinet9= genere= golden= goldenhiero= honors= horus= horus2= horushiero= horushiero2= horusprefix= ideologia= image= imatgeobra= influencies_de= influi_en= inici= inici10= inici11= inici2= inici3= inici4= inici5= inici6= inici7= inici8= inici9= instrument= junt_a= junt_a10= junt_a11= junt_a2= junt_a3= junt_a4= junt_a5= junt_a6= junt_a7= junt_a8= junt_a9= k_etiqueta= k_etiqueta10= k_etiqueta11= k_etiqueta2= k_etiqueta3= k_etiqueta4= k_etiqueta5= k_etiqueta6= k_etiqueta7= k_etiqueta8= k_etiqueta9= k_nom= k_nom10= k_nom11= k_nom2= k_nom3= k_nom4= k_nom5= k_nom6= k_nom7= k_nom8= k_nom9= l_etiqueta= l_etiqueta10= l_etiqueta11= l_etiqueta2= l_etiqueta3= l_etiqueta4= l_etiqueta5= l_etiqueta6= l_etiqueta7= l_etiqueta8= l_etiqueta9= l_nom= l_nom10= l_nom11= l_nom2= l_nom3= l_nom4= l_nom5= l_nom6= l_nom7= l_nom8= l_nom9= lema_escut= lught_mooinjeragh= ammys= periode_actiu_militar= llengua_nom_original= çhengey= lloc_defuncio= lloc_desaparicio= lloc_naixement= lloc_web= mare= membre_de= membres_anteriors= yrjid= towshan= enmyn_elley= trimmid= ynnyd_beaghee= bleeantyngobbyr= mestres= millors_films= monuments= mostra_venecia= moviment= myspace= nacionalitat= national_film_awards= nom_naixement= nom_original_lleng= nom_original= nom= nom_temple= nom_postum= nomen= nomen2= nomenhiero= nomenhiero2= nominat= nominat10= nominat11= nominat2= nominat3= nominat4= nominat5= nominat6= nominat7= nominat8= nominat9= notes= obres_notables= obres= ocupacio= ocupacioWD= ocupador= organitzacio= oponents= oponents10= oponents11= oponents2= oponents3= oponents4= oponents5= oponents6= oponents7= oponents8= oponents9= orquestres= pare= parella= parents= paarantyn= paitçhyn= germans= partit_politic= patrons= patrocinador= periode_actiu_militar= periode_actiu= pes= <!-- imatge_militar= peu_imatge_militar= peu_veu= --> fo-heidyl= peuobra= predecessor= predecessor10= predecessor11= predecessor2= predecessor3= predecessor4= predecessor5= predecessor6= predecessor7= predecessor8= date_baaish= ashoonaght= ennym_ruggyr= boayl_baaish= ennym= jalloo= predecessor9= prefix_honorific= premis= prenomen= prenomen2= prenomenhiero= prenomenhiero2= <!-- principals_dissenys= principals_edificis= mitjans= --> principals_projectes= editor= programes= proposit= rang= registre_veu= religio= repertori= residencia= salari= sepultura= series= signatura= <!-- situacio_judicial= tematica= --> subheader= successor= successor10= successor11= successor2= successor3= successor4= successor5= successor6= successor7= successor8= successor9= sufix_honorific= talla_penis= titol_personal= trajectoria= ulls= unitat= valor_net= veu= victories= tesi= tesi_any= tesi_url= direccio_tesi= idees= <!-- era= regio= escola_tradicio= --> interessos= opositors= estudiants_doctorals= <!-- estudiants_notables= --> nom_ploma= primeres_obres= papers= ayr= ashoonaght_spoyrtoil= membres= socis= president= vicepresident= direccio_tesi2= director_musical= sotsdirector_musical= nebty= nebtyhiero= instruments_destacats= ordre= ordre2= ordre3= ordre4= ordre5= ordre6= ordre7= ordre8= ordre9= ordre10= ordre11= <!-- assessorament_academic= premis_afi= premis_bafta= premis_butaca= premis_cesar= premis_emmy= premis_gaudi= premis_golden_globe= premis_goya= premis_grammy= premis_olivier= premis_oscar= premis_tony= premis_pulitzer= premis_nacionals= premis_regas= premis_mvm= premis_asensio= premis_ondas= premis_barnils= premis_cerecedo= premis_ofici_periodista= --> temps_espai= tripulacio= missio_espacial= insignia_missio= eva1= braaraghyn_shuyraghyn= <!-- eva2= -->
decat= item= lang= cronologia= arxius= identificadors= copilot= wikidata= epoca= çhengey_ghooghyssagh= l_memorials= l_employer= l_family=
<!--aliats= rivals= etiqueta_aliats= etiqueta_rivals= etiqueta_monuments= --> floruit= participa_en= circumstancia_defuncio=
orde= ordenacio= consagracio= proclamacio=
patronatge= data_beatificacio= data_canonitzacio= venerat_en= venerat_a= lloc_canonitzacio= enaltiment= lloc_beatificacio= beatificat_per= canonitzat_per= fets_destacables= festivitat= lloc_pelegrinatge= iconografia= fets_destacables= patronatge= <!-- supressio_culte= suprimit_per= continuadors= -->
lloc_debut= data_debut= lloc_retirada= data_retirada= lliga= dades_medaller= club_actual= posicio_equip= dorsal_club= posicio_equip= lateralitat= ma_joc= draft= draft_equip= draft_any= esport= disciplina= classe=<!-- especialitat= --> draft_equip= draft_any= entrenador= convoca_internacional= patrimoni_personal= extensio_parametres_esport = =extensio_carrera_esportiva= extensio_participacio_esdeveniments=
titol_escacs= elo_max= patrocinador_material= nacionalitat_esportiva= desplega_premis= desplega_obres= desplega_influencia=
unit_P2048= unit_P2067= list_naixement=
<!-- a eliminar després bot (PENDENT PASSAR)-->
tesi2= tesi_any2= tesi_url2= situacio_penal=
altres_carrecs= imatge_espiritual= peu_imatge_espiritual= condecoracions=
<!-- a eliminar
-->
mon
1= 2= 3=
<!-- extensio_atributs_professionals= extensio_activitat_professional= -->
|cat=Kishtaghyn fys ymmydit marish parameadaryn gyn fys
|format=0|preview=1|errNS=0
}}<!--
rastreig provisional de paràmetres
-->{{#if:{{{carrec|}}}{{{carrec2|}}}{{{carrec3|}}}{{{carrec4|}}}{{{carrec5|}}}{{{carrec6|}}} {{{carrec7|}}}{{{carrec8|}}}{{{carrec9|}}}{{{carrec10|}}}
|{{#if:{{#property:P39 | from={{{item|}}} }} | [[categoria:Articles amb càrrecs manuals i P39]]
| [[categoria:Articles amb càrrecs manuals sense P39]]}} }}<!--
-->{{#if:{{{carrec|}}}
|{{#if:{{{carrec2|}}}{{{carrec3|}}}{{{carrec4|}}}{{{carrec5|}}}{{{carrec6|}}} {{{carrec7|}}}|<!-- ni ha +1, saltar
-->|{{#invoke:utilities|rastreig|Infotaula_persona/1carrec}}}} }}<!--
-->{{#if:{{{extensio_guardons|}}}|{{#invoke:utilities|rastreig|Infotaula_persona/premis_manuals}}}}<!-- 1100 aprx
-->{{#if:{{{carrecs_judicials|}}}|{{#invoke:utilities|rastreig|Infotaula_persona/carrecs_judicials}}}}<!-- 4
-->{{#if:{{{condemnes|}}}|{{#invoke:utilities|rastreig|Infotaula_persona/condemnes}}}}<!-- 21
-->{{#if:{{{data_defuncio|}}}
|{{#if:{{#invoke:wikidata | claim | property=P570 }}|<!-- res -->|{{#invoke:utilities|rastreig|Infotaula_persona/recuperarDD}} }}}}<!-- 325
-->{{#ifexpr: {{str find|{{lc:{{#property:P31|from={{{item|}}} }}}}|grup}} +
{{str find|{{lc:{{#property:P31|from={{{item|}}} }}}}|col·lectiu}} +
{{str find|{{lc:{{#property:P31|from={{{item|}}} }}}}|cor}} > 0
|{{#invoke:utilities|rastreig|Infotaula_persona/grup}} }}<!-- 89
-->{{#if:{{{notes|}}}|{{#invoke:utilities|rastreig|Infotaula_persona/notes}}}} <!--
--><!-- Paràmetres manuals candidats a ser eliminats
-->{{#if:
{{{oponents|}}} {{{a_etiqueta|}}} {{{a_nom|}}} {{{b_etiqueta|}}} {{{b_nom|}}} {{{e_etiqueta|}}} {{{e_nom|}}} {{{f_etiqueta|}}}{{{f_nom|}}}
{{{l_etiqueta|}}} {{{l_nom|}}}
{{{a_etiqueta2|}}} {{{a_nom2|}}} {{{b_etiqueta2|}}} {{{b_nom2|}}} {{{e_etiqueta2|}}} {{{e_nom2|}}} {{{f_etiqueta2|}}}{{{f_nom2|}}} {{{l_etiqueta2|}}} {{{l_nom2|}}}
{{{a_etiqueta3|}}} {{{a_nom3|}}} {{{b_etiqueta3|}}} {{{b_nom3|}}} {{{e_etiqueta3|}}} {{{e_nom3|}}} {{{f_etiqueta3|}}}{{{f_nom3|}}}
{{{l_etiqueta3|}}} {{{l_nom3|}}}
{{{a_etiqueta4|}}} {{{a_nom4|}}} {{{b_etiqueta4|}}} {{{b_nom4|}}} {{{e_etiqueta4|}}} {{{e_nom4|}}} {{{f_etiqueta4|}}}{{{f_nom4|}}}
{{{l_etiqueta4|}}} {{{l_nom4|}}}
{{{a_etiqueta5|}}} {{{a_nom5|}}} {{{b_etiqueta5|}}} {{{b_nom5|}}} {{{e_etiqueta5|}}} {{{e_nom5|}}} {{{f_etiqueta5|}}}{{{f_nom5|}}}
{{{l_etiqueta5|}}} {{{l_nom5|}}}
{{{a_etiqueta6|}}} {{{a_nom6|}}} {{{b_etiqueta6|}}} {{{b_nom6|}}} {{{e_etiqueta6|}}} {{{e_nom6|}}} {{{f_etiqueta6|}}}{{{f_nom6|}}}
{{{l_etiqueta6|}}} {{{l_nom6|}}}
{{{a_etiqueta7|}}} {{{a_nom7|}}} {{{b_etiqueta7|}}} {{{b_nom7|}}} {{{e_etiqueta7|}}} {{{e_nom7|}}} {{{f_etiqueta7|}}}{{{f_nom7|}}}
{{{l_etiqueta7|}}} {{{l_nom7|}}}
|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}<!--
-->{{#if:{{{k_etiqueta|}}} |{{#ifeq:{{{k_etiqueta|}}} |Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta2|}}}|{{#ifeq:{{{k_etiqueta2|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta3|}}}|{{#ifeq:{{{k_etiqueta3|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta4|}}}|{{#ifeq:{{{k_etiqueta4|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta5|}}}|{{#ifeq:{{{k_etiqueta5|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta6|}}}|{{#ifeq:{{{k_etiqueta6|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{k_etiqueta7|}}}|{{#ifeq:{{{k_etiqueta7|}}}|Circumscripció|{{#invoke:utilities|rastreig|Infotaula_persona/eticarrecs}}}}}}<!--
-->{{#if:{{{premis|{{{guardons|}}}}}}|{{#invoke:utilities|rastreig|Infotaula_persona/premis-condecoracions}}}}<!-- 569
-->{{#if: {{{educacio|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/educacio}}}}<!-- 160
-->{{#if: {{{instruments_destacats|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/instruments_destacats}}}}<!-- 48
-->{{#if: {{{organitzacio|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/organitzacio}}}}<!-- 1070
-->{{#if: {{{mitjans|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/mitjans}}}}<!-- 166
-->{{#if: {{{club_actual|{{{clubactual|{{{currentclub|}}}}}}}}} |{{#invoke:utilities|rastreig|Infotaula_persona/clubactual}}}}<!-- 6072
-->{{#if: {{{era|}}}{{{regio|}}}{{{escola_tradicio|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/regio-escola}}}}<!-- 63
-->{{#if: {{{monuments|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/monuments}}}}<!-- 28
-->{{#if: {{{orquestres|}}}{{{artistes_relacionats|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/orquestres}}}}<!-- 285
-->{{#if: {{{idees|}}} | {{#invoke:utilities|rastreig|Infotaula_persona/idees}}}}<!-- 32
-->{{#if:{{{unitat|}}}{{{victories|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/unitat_victories}}}}<!-- 130
-->{{#if: {{{periode_actiu_militar|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/periode_militar}}}}<!-- 53
-->{{#if:{{{estil|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/estil}}}}<!-- 80
-->{{#if:{{{millors_films|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/millors_films}}}}<!-- 40
-->{{#if:{{{nom_original|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/nom_original}}}}<!-- 130
-->{{#if:{{{altres_ocupacions|}}}{{{altres_carrecs|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/altres ocupacions}}}}<!-- 265
-->{{#if:{{{editor|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/editor}}}}<!-- 3
-->{{#if:{{{primeres_obres|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/primeres_obres}}}}<!-- 81
-->{{#if:{{{obres|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/obres}}}}<!-- 40
-->{{#if:{{{tematica|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/tematica}}}}<!-- 119
-->{{#if:{{{programes|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/programes}}}}<!-- 29
-->{{#if:{{{art|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/art}}}}<!-- 1222 revisar amb professió
-->{{#if:{{{lloc_debut|}}}{{{data_debut|}}}{{{lloc_retirada|}}}{{{data_retirada|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/debut}}}}<!-- 151
-->{{#if:{{{conegut_per|}}} | {{#ifexpr:{{str find|{{{conegut_per|}}}|llegend}} + {{str find|{{{conegut_per|}}}|dubt}} +
{{str find|{{{conegut_per|}}}|inexis}} > 0
| {{#invoke:utilities|rastreig|Infotaula_persona/llegendari}}}} }}<!-- 89
-->{{#if:{{{image|}}}
|{{#if:{{#invoke:wikidata | claim | property=P18 }}|<!-- res -->|{{#invoke:utilities|rastreig|Infotaula_persona/imatge_per_WD}} }}}}<!--
-->{{#if:{{{conegut_per|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/conegut_per}}}}<!-- 4541
-->{{#if:{{{patrons|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/patrons}}}}<!-- 42
-->{{#if:{{{films|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/films}}}}<!-- 20
-->{{#if:{{{principals_projectes|}}} |{{#invoke:utilities|rastreig|Infotaula_persona/principals_projectes}}}}<!-- <50
--></div></includeonly><noinclude>
{{Docamadys}}
[[Ronney:WD Kishtaghyn Fys Dooinney]]
</noinclude>
b5fc71mmmau1yxgdz0fh5vz1lu5m9lw
Kristen Welker
0
55792
392640
2026-09-01T12:22:49Z
MacTire02
219
toshiaght art
392640
wikitext
text/x-wiki
{{WD Kishtey Fys Dooinney
| date_ruggyr = {{date_ruggyr|1976|07|01|df=yes}}
| boayl_ruggyr = [[Philadelphia]], [[Pennsylvania]], ny Steatyn Unnaneysit<ref name="DOB">{{cite web|author=Kristen Welker (@kwelkernbc)|title=Thanks so much! "@ happy. We share with Pam Anderson and Lady Diana. Solid company." |url=https://twitter.com/kwelkernbc/status/616244590664794112 |publisher=[[Twitter]]|access-date=6 Averil 2016|date=1 Jerrey Souree 2015}}</ref>
}}
{{Çhyndaait|1=en|2=Kristen Welker|lhieggan=1372284338}}
She [[earisheyr]] çhellveeish Americaanagh ta gobbraghey lesh [[NBC News]] ee '''Kristen Welker''' (ruggit er 1 Jerrey Souree 1976). T'ee gobbraghey myr co-reggyrtagh y Thie Bane bunnit ayns [[Washington, D.C.]],<ref name=":2">{{cite web|url=https://www.nbcnews.com/author/kristen-welker-ncpn6396|title=Kristen Welker|work=msnbc.com|date=11 Jerrey Fouyir 2010 |access-date=18 Averil 2016}}</ref> as ren ee obbraghey myr co-hebbeyder ''[[Weekend Today]]'', lhieggan Jesarn jeh ''[[Today (claare hellveeish Americaanagh|Today]]'', marish [[Peter Alexander (earisheyr)|Peter Alexander]] veih 2020 derrey 2023. Ghow ee shelloo er currymyn çhebbal da'n chlaare ''[[Meet the Press]]'' er 17 Mean Fouyir 2023, y chlaare s'odjey scaalheanit ayns shennaghys y çhellveeish Americaanagh.<ref name="first show">{{cite web |title=Trump joins Kristen Welker in her first show as moderator of Meet the Press – September 17 |url=https://www.nbc.com/meet-the-press/video/trump-joins-kristen-welker-in-her-first-show-as-moderator-of-meet-the-press-september-17/NBCN147461836 |publisher=NBC News |access-date=3 Mean Souree 2024 |date=17 Mean Fouyir 2023}}</ref><ref name="LATimes-2023Sep">{{Cite web |date=17 Mean Fouyir 2023 |title=Commentary: 'Meet the Press' debuts with Kristen Welker and treads familiar ground with Trump |url=https://www.latimes.com/entertainment-arts/tv/story/2023-09-17/meet-the-press-kristen-welker-donald-trump |access-date=8 Toshiaght Arree 2024 |website=Los Angeles Times |language=en-US}}</ref>
== Imraaghyn ==
{{reflist}}
==Kianglaghyn magh==
* [https://www.nbcnews.com/author/kristen-welker-ncpn6396 Beashnys Kristen Welker lesh NBC]
* {{C-SPAN|107682}}
{{gurneil eaghtyrys}}
{{DEFAULTSORT:Welker, Kristen}}
[[Ronney:Ruggyryn 'sy vlein 1976]]
[[Ronney:Feallee vio]]
[[Ronney:Earisheyryn bwoirrin Americaanagh y 21d eash]]
[[Ronney:Persoonidyn çhellveeish Affro-Americaanagh]]
[[Ronney:Earisheyryn bwoirrin Affro-Americaanagh]]
[[Ronney:Çhebbeyderyn as lhaideryn naight Americaanagh]]
[[Ronney:Earisheyryn politickagh Americaanagh]]
[[Ronney:Naighteyryn as co-reggyrtee hellveeish Americaanagh]]
[[Ronney:Earisheyryn çhellveeish bwoirrin Americaanagh]]
[[Ronney:Feallee MS NOW]]
[[Ronney:Feallee NBC News]]
[[Ronney:Co-reggyrtee yn Thie Bane]]
[[Ronney:Feallee kianglt rish reihys eaghtyraneagh ny Steatyn Unnaneysit, 2020]]
[[Ronney:Feallee ass Pennsylvania]]
fwekpr6q2yja58pr20787vyj1uigkqw
Clowan:Kishtey fys straid
10
55793
392641
2026-09-01T13:19:12Z
MacTire02
219
clowan noa
392641
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|{{{ennym}}}|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheader = {{{ennym_elley|}}}
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
h7hgrpbh411781441sxl9w0crmq244c
392648
392641
2026-09-01T13:58:32Z
MacTire02
219
elley
392648
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|{{{ennym}}}|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheader = {{{ennym_elley|}}}
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
qnz4hx6fz249h1yj3i0xrh2miuxwtuh
392654
392648
2026-09-01T14:30:15Z
MacTire02
219
++
392654
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheader = {{{ennym_elley|}}}
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
po6rkzyms4iiqs7jwqk0cw1b2tmrofg
392657
392654
2026-09-01T14:37:06Z
MacTire02
219
prowal
392657
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= background-color: #E7DCC3; text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
qrc1s6bcklkaa18byy0qnzsd7gcc5ty
392658
392657
2026-09-01T16:37:43Z
MacTire02
219
--
392658
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh {{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
fglzw1ce11o7hsp01jojk38smjja3ha
392660
392658
2026-09-01T17:00:46Z
MacTire02
219
++
392660
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh<br/>{{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
a7dtjni6tktdwo1i0rvolgn9cnbdhf3
392664
392660
2026-09-01T20:21:53Z
MacTire02
219
--
392664
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh<br/>{{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
2ry4sncg62m6xh3i24vadfcob8sk8qu
392673
392664
2026-09-01T20:30:30Z
MacTire02
219
Undid revision [[Special:Diff/392664|392664]] by [[Special:Contributions/MacTire02|MacTire02]] ([[User talk:MacTire02|talk]])
392673
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh<br/>{{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
a7dtjni6tktdwo1i0rvolgn9cnbdhf3
392676
392673
2026-09-01T20:38:24Z
MacTire02
219
++
392676
wikitext
text/x-wiki
<includeonly>{{Infobox
| child = {{{embed|}}}
| bodyclass = vcard
| titleclass = fn org street-address
| title = {{#if:{{{ennym|}}}|'''{{{ennym}}}'''|{{#ifeq:{{{embed|}}}|yes||{{PAGENAMEBASE}}}}}}
| autoheaders = yes
| aboveclass = adr
| above = {{{jalloo_cowreyder|}}}
| subheaderclass= nickname
| subheaderstyle= font-size:100%; text-align: center;
| subheader = {{{ennym_elley|}}}
| imagestyle = padding:0.3em 0.2em 0.2em 0.2em; text-align:center;
| captionstyle = padding: 0.2em 0em;
| bodystyle = width:24.5em; line-height:1.5em;
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo|}}}|size={{{mooadys_jalloo|}}}}}
| caption = {{{fo-heidyl|}}}
| image2 = {{#invoke:Location map|infobox_pushpin_map
| pushpin_map = {{{caslys-çheerey_freeney|}}}
}}
| image3 = {{#invoke:InfoboxImage|InfoboxImage|image={{{jalloo_caslys-çheerey|}}}|size={{{mooadys_caslys-çheerey|}}}|sizedefault=frameless|{{{fo-heidyl_caslys-çheerey|}}}}}
| caption3 = {{{fo-heidyl_caslys-çheerey|}}}
| image4 = {{#invoke:Infobox mapframe
| autoWithCaption
| onByDefault = {{#if:{{{jalloo_caslys-çheerey|}}}{{{caslys-çheerey_freeney|}}}|no|yes}}
| mapframe-stroke-width = 1.5
| mapframe-type = landmark
| mapframe-length_km = {{{lhiurid_km|}}}
| mapframe-length_mi = {{{lhiurid_mi|}}}
| mapframe-caption = Caslys-çheerey eddyr-obbragh jeh<br/>{{if empty|{{{ennym|}}}|{{PAGENAMEBASE}}}}
}}
| class1 = nickname
| label1 = Ennym dooghyssagh
| data1 = {{native name checker|{{{ennym_dooghyssagh|}}}}}
| label2 = Shenn-ennym
| data2 = {{{shenn-ennym|}}}
| class2 = nickname
| label3 = Ayrn jeh
| data3 = {{{ayrn_jeh|}}}
| label4 = Co-ennymagh
| data4 = {{{co-ennymagh|}}}
| label5 = Sorçh
| data5 = {{{sorçh|}}}
| class5 = category
| label6 = Shellooder
| data6 = {{{shellooder|}}}
| class6 = agent
| label7 = Freaylt lesh
| data7 = {{#if:{{{freaylt|}}}|{{#ifeq:{{{freaylt|}}}|none||{{{freaylt}}}}}}}
| label8 = Lhiurid
| data8 = {{if empty|{{{lhiurid|}}}|{{convinfobox|{{{lhiurid_mi|}}}|mi|{{{lhiurid_km|}}}|km}}|{{convinfobox|{{{lhiurid_m|}}}|m|{{{lhiurid_ft|}}}|ft}}}}{{#if:{{{lhiurid|}}}{{{lhiurid_mi|}}}{{{lhiurid_km|}}}{{{lhiurid_m|}}}{{{lhiurid_ft|}}}|{{{imraa-lhiruid|}}}{{#if:{{{noteyn_lhiurid|}}}|<br/>{{{noteyn_lhiurid}}} }} }}
| label9 = Lheead
| data9 = {{{lheead|}}}
| label10 = Eaghtyr
| data10 = {{{eaghtyr|}}}
| label11 = {{longitem|{{#ifeq:{{{çheer|}}}|AUS|[[Earroo bollee#Yn Austrail{{!}}Rheynn]]|Co-raaidyn<br />mooarey}}}}
| data11 = {{{rheynn|}}}
| label12 = {{longitem|Bollee hurryssagh}}
| data12 = {{{turryssagh|}}}
| label13 = Lhiettalyssyn
| data13 = {{{lhiettalyssyn|}}}
<!-- LOCATION -->
| label14 = Enmyssyn
| data14 = {{{enmyssyn|}}}
| label15 = Soiaghey
| data15 = {{{soiaghey|}}}
| class15 = locality
| label16 = [[Slystyn baljagh y Rank|Arrondissement]]
| data16 = {{{arrondissement|}}}
| label17 = [[Kerroo (aarheynn valjagh)|Kerroo]]
| data17 = {{{kerroo|}}}
| label18 = {{longitem|{{if empty|{{{sorçh_coad_postagh|}}}|Coad postagh}}}}
| data18 = {{{coad_postagh|}}}
| class18 = postal-code
| label19 = {{longitem|Y stashoon {{if empty|{{{corys_fo-halloo|}}}|fo-halloo}} s'niessey}}
| data19 = {{{fo-halloo|}}}
| label20 = Co-ordnaidyn
| data20 = {{#if:{{{co-ordnaidyn|}}}|{{#invoke:Coordinates|coordinsert|{{{co-ordnaidyn|}}}|type:landmark}} }}
| label21 = {{if empty|{{{ennym_ingagh|}}}|Soiaghey ingagh}}
| data21 = {{{soiaghey_ingagh|}}}
<!-- MAJOR JUNCTIONS -->
| label22 = {{#if:{{{kione_a|}}}|{{#if:{{{troa_a|}}}|Kione {{{troa_a}}}|Veih}}|}}
| data22 = {{{kione_a|}}}
| label23 = {{longitem|Goalyn mooarey}}
| data23 = {{{goal|}}}
| label24 = {{#if:{{{kione_b|}}}|{{#if:{{{troa_b|}}}|Kione {{{troa_b}}}|Dys}}|}}
| data24 = {{{kione_b|}}}
<!-- ADJACENT -->
| label25 = Twoaie
| data25 = {{{twoaie|}}}
| label26 = Shiar
| data26 = {{{shiar|}}}
| label27 = Jiass
| data27 = {{{jiass|}}}
| label28 = Sheear
| data28 = {{{sheear|}}}
<!-- CONSTRUCTION -->
| header29 = Troggalys
| label30 = Commishoonit
| data30 = {{{date_commishooney|}}}
| label31 = {{longitem|Toshiaght y troggal}}
| data31 = {{{date_toshee_yn _troggal|}}}
| label32 = Jerrey yn troggal
| data32 = {{{date_jerrey_yn_troggal|}}}
| label33 = {{if empty|{{{lipaid_bunneeaght|}}}|Bunneeaght}}
| data33 = {{{date_bunneeaght|}}}
| label34 = Scrysst
| data34 = {{{date_scryssey|}}}
<!-- OTHER -->
| header35 = Elley
| label36 = Kiaddeyder
| data36 = {{{kiaddeyder|}}}
| label37 = Mie er enney son
| data37 = {{{ennit_son|}}}
| label38 = Staydys
| data38 = {{{staydys|}}}
| label39 = Ynnyd-eggey
| data39 = {{{ynnyd-eggey|}}}
| rowstyle40 = width:100%; border-collapse:collapse;
| data40 = {{#if:{{{femblal|}}}|{{#invoke:Road data/browsetable|browsetable|{{{femblal}}}}}}}
<!-- EMBEDDED -->
| header41 = _BLANK_
| data42 = {{{embedded|}}}
}}</includeonly>{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Ronney:Duillagyn gymmydey kishtey fys straid lesh parameadaryn gyn enney|_VALUE_{{PAGENAME}}]]}}|preview=Ta'n duillag gymmydey [[Clowan:Kishtey fys straid]] lesh y pharameadar "_VALUE_" gyn enney |ignoreblank=y|mapframe_args=y|pushpin_map_args=y| enmyssyn | rheynn | eaghtyr | arrondissement | femblal | fo-heidyl | date_commishooney | date_jerrey_yn_troggal | date_toshee_yn_troggal| co-ordnaidyn | çheer | date_scryssey| kiaddeyder | troa_a | troa_b | shiar | embed | embedded | shenn-ennym| ennym_ingagh | soiaghey_ingagh | jalloo | jalloo_caslys-çheerey| mooadys_jalloo | date_bunneeaght| lipaid_bunneeaght| goal | ennit_son| lhiurid| lhiurid_ft | lhiurid_km | lhiurid_m | lhiurid_mi | noteyn_lhiurid | imraa_lhiurid | soiaghey | freaylt | fo-heidyl_caslys-çheerey | mooadys_caslys-çheerey | jalloo_cowreyder | fo-halloo | corys_fo-halloo | ennym | co-ennymagh | ennym_dooghyssagh | twoaie | ennym_elley | shellooder | ayrn_jeh | coad_postagh | sorçh_coad_postagh | kerroo | lhiettalyssyn | jiass | staydys | kione_a | kione_b | turryssagh | sorçh | ynnyd-eggey | sheear | lheead }}<noinclude>
{{documentation}}
</noinclude>
b4uouufrtfjaz27vrnsyiz3c3cy08ly
Clowan:Scruteyr ennym dooghyssagh
10
55795
392646
2026-09-01T13:33:17Z
MacTire02
219
MacTire02 moved page [[Clowan:Scruteyr ennym dooghyssagh]] to [[Clowan:Native name checker]]
392646
wikitext
text/x-wiki
#REDIRECT [[Clowan:Native name checker]]
59uk1symy1a1rlcr478eod3nvb4jzn1
Resooney ymmydeyr:WikiBayer
3
55796
392647
2026-09-01T13:54:38Z
MacTire02
219
/* Updating MediaWiki:Common.css */ new section
392647
wikitext
text/x-wiki
== Updating MediaWiki:Common.css ==
Hi, I was wondering if it would be possible to update the Common.css with the following:
.infobox {
border: 1px solid #aaa;
background-color: #f9f9f9;
border: 1px solid #a2a9b1;
color: black;
margin: 0.5em 0 0.5em 1em;
padding: 0.2em;
float: right;
clear: right;
font-size: 88%;
line-height: 1.5em;
border-spacing: 3px;
margin: 0.5em 0;
}
@media screen {
.infobox {
background-color: var(--background-color-neutral-subtle, #f8f9fa);
}
}
@media (max-width: 640px) {
.infobox {
width: 100%;
}
.infobox .nowrap {
white-space: normal;
}
}
@media (min-width: 640px) {
.infobox {
/* @noflip */
margin-left: 1em;
/* @noflip */
float: right;
/* @noflip */
clear: right;
width: 22em;
}
}
.infobox-header,
.infobox-label,
.infobox-above,
.infobox-full-data,
.infobox-data,
.infobox-below,
.infobox-subheader,
.infobox-image,
.infobox-navbar,
.infobox td,
}
.infobox-label,
.infobox-data,
.infobox th,
.infobox td {
/* @noflip */
text-align: left;
}
.infobox .infobox-above,
.infobox .infobox-title,
.infobox caption {
font-size: 125%;
font-weight: bold;
text-align: center;
}
.infobox-title,
.infobox caption {
font-size: larger;
margin-left: inherit;
padding: 0.2em;
}
.infobox .infobox-header,
.infobox .infobox-subheader,
.infobox .infobox-image,
.infobox .infobox-full-data,
.infobox .infobox-below {
text-align: center;
}
.infobox .infobox-navbar {
/* @noflip */
text-align: right;
}
As it stands, our infoboxes don't automatically align text for lables in infoboxes to the left hand side. Let me know if this is something you can do. Thank you, [[Ymmydeyr:MacTire02|<span style="color:#003300;font-family:serif;font-size:100%"><sup>'''Mac Tíre'''</sup></span>]] [[Resooney ymmydeyr:MacTire02|<span style="color:red;font-family:cursive;font-size:80%"><sub>''Cowag''</sub></span>]] 13:54, 1 Mean Fouyir 2026 (UTC)
02wmpzpi9bcap742wqanpr8hgqwot8l
Module:Infobox dim
828
55797
392652
2026-09-01T14:25:09Z
MacTire02
219
moddyl noa
392652
Scribunto
text/plain
require('strict')
local getArgs = require('Module:Arguments').getArgs
local p = {}
local log2 = 0.693147181
local ppm = 1000/0.3 -- pixels per meter, from 0.3 mm / pixel from https://wiki.openstreetmap.org/wiki/Zoom_levels
-- To convert to OSM zoom level, we need to know meters per pixel at zoom level 9
-- On the equator, it's 305.748 meters/pixel according to https://wiki.openstreetmap.org/wiki/Zoom_levels
-- This quantity depends on the latitude (which we usually don't have easy access to)
-- Instead, we'll be correct at 38 degrees N, given en-WP bias towards NA and Europe
-- 38N was chosen because:
-- * It's the furthest north where scale=100000 maps to zoom=12
-- * One hemisphere (20000km) maps to zoom=1
local mppl9Equator = 305.748
-- Convert from Geohack's scale to OSM style zoom levels as used by <maplink>
local function geohackScaleToMapZoom(scale,latitude)
scale = tonumber(scale)
if not scale or scale <= 0 then return end
latitude = latitude or 38
local mppl9 = mppl9Equator*math.cos(math.rad(latitude))
return math.log(mppl9*ppm/scale)/log2 + 9
end
-- compute the viewport size (on screen) in meters, assuming ppm pixels per meter on screen
local function computeViewport(args)
local viewport_cm = tonumber(args.viewport_cm)
local viewport_px = tonumber(args.viewport_px)
return viewport_cm and viewport_cm / 100 or viewport_px and viewport_px / ppm
or tonumber(args.default_viewport) or 0.1
end
-- convert from geohack dim (knowing the viewpoint size on screen) to geohack scale
local function geohackDimToScale(dim, args)
dim = tonumber(dim)
args = args or {}
if not dim or dim <= 0 then return end
local units = args.units
if units and string.lower(units) == 'km' then
dim = dim*1000
end
return dim / computeViewport(args)
end
-- inverse of above function, returning dim in km
local function geohackScaleToDim(scale, args)
scale = tonumber(scale)
args = args or {}
if not scale or scale <= 0 then return end
return scale * computeViewport(args) * 1e-3
end
local oddShape = 2.09 --- length/sqrt(area) of Boston (to choose an example)
-- Convert from Geohack's types to Geohack dim
local function geohackTypeToDim(args)
local t = args.type
if not t then return end
local typeDim = mw.loadData('Module:Infobox_dim/data')
local dim = typeDim[t]
local population = tonumber(args.population)
if t == 'city' and population and population > 0 then
-- assume city is a circle with density of 1000/square kilometer
-- compute diameter, in meters. Then multiply by oddShape to account for weird shapes
dim = 35.68e-3*math.sqrt(population)*oddShape
-- don't zoom in too far
if dim < 5 then
dim = 5
end
end
return dim
end
-- Convert from dimension of object to Geohack dim
local function computeDim(length,width,area)
if length and width then
return math.max(length,width)
end
if length then return length end
if width then return width end
if area then return oddShape*math.sqrt(area) end
end
-- compute geohack dim from unit arguments (e.g., length_mi)
local function convertDim(args)
local length = args.length_mi and 1.60934*args.length_mi or args.length_km
local width = args.width_mi and 1.60934*args.width_mi or args.width_km
local area = args.area_acre and 0.00404686*args.area_acre or
args.area_ha and 0.01*args.area_ha or
args.area_mi2 and 2.58999*args.area_mi2 or args.area_km2
local dim = computeDim(length, width, area)
return dim
end
local function computeScale(args)
if args.scale then return args.scale end
local dim, units, scale
if args.dim then
dim, units = mw.ustring.match(args.dim,"^([-%d%.]+)%s*(%D*)")
args.units = units
args.default_viewport = 0.1 -- default geohack viewpoirt
scale = geohackDimToScale(dim, args)
end
if not scale then
dim = convertDim(args) or geohackTypeToDim(args)
args.units = 'km'
args.default_viewport = 0.2 --- when object dimensions or type is specified, assume 20cm viewport
scale = dim and geohackDimToScale(dim, args)
end
if not scale then return end
scale = math.floor(scale+0.5)
-- keep scale within sane bounds (OSM zoom levels 1-17)
if scale < 1600 then
scale = 1600
end
if scale > 200e6 then
scale = 200e6
end
return scale
end
-- Argument checking
local positiveNumericArgs = {viewport_cm=true,viewport_px=true,length_mi=true,length_km=true,
width_mi=true,width_km=true,area_mi2=true,area_km2=true,
area_acre=true,area_ha=true,scale=true,population=true}
local function cleanArgs(args)
local clean = {}
if type(args) == 'table' then
for k, v in pairs(args) do
if positiveNumericArgs[k] then
v = v and mw.ustring.gsub(v,",","") -- clean out any commas
v = tonumber(v) -- ensure argument is numeric
if v and v <= 0 then -- if non-positive, ignore value
v = nil
end
end
clean[k] = v
end
end
return clean
end
-- Module entry points
function p._dim(args)
args = cleanArgs(args)
if args.dim then return args.dim end
-- compute scale for geohack
local scale = args.scale
local dim
if not scale then
args.default_viewport = 0.2 -- when specifying a object dimension or type, assume output spans 20cm
dim = convertDim(args) or geohackTypeToDim(args)
args.units = 'km'
scale = dim and geohackDimToScale(dim, args)
end
-- reset back to 10cm viewport for correct geohack dim output
args.viewport_cm = 10
dim = scale and geohackScaleToDim(scale, args)
return dim and tostring(math.floor(dim+0.5))..'km'
end
function p._scale(args)
args = cleanArgs(args)
return computeScale(args)
end
function p._zoom(args)
args = cleanArgs(args)
args.viewport_px = args.viewport_px or 200 --- viewport for Kartographer is 200px high
local scale = computeScale(args)
if scale then
local latitude = tonumber(args.latitude)
latitude = latitude and (latitude > 70 and 70 or latitude < -70 and -70 or latitude)
local zoom = geohackScaleToMapZoom(scale,latitude)
return zoom and math.floor(zoom)
end
end
-- Template entry points
function p.dim(frame)
return p._dim(getArgs(frame)) or ''
end
function p.scale(frame)
return p._scale(getArgs(frame)) or ''
end
function p.zoom(frame)
return p._zoom(getArgs(frame)) or ''
end
return p
jy5fyn8gcmhd8ajqw0ljt5qgmzyo4hz
Module:Infobox dim/data
828
55798
392653
2026-09-01T14:26:03Z
MacTire02
219
fysseree
392653
Scribunto
text/plain
local typeToDim = { -- typical size of object (in km)
country = 2000,
satellite = 2000,
state = 600,
adm1st = 200,
adm2nd = 60,
adm3rd = 20,
city = 20,
isle = 20,
mountain = 20,
river = 20,
waterbody = 20,
event = 10,
forest = 10,
glacier = 10,
airport = 6,
landmark = 2,
railwaystation = 2,
edu = 2,
pass = 2,
camera = 2
}
return typeToDim
q8gk4m0g59kpt1szm28fnnl9cyh4rhi
Ronney:Duillagyn gymmydey infobox mapframe lesh laaraghey eignit
14
55799
392656
2026-09-01T14:34:17Z
MacTire02
219
ronney noa
392656
wikitext
text/x-wiki
{{Tracking category|template=Infobox mapframe}}
{{CatAutoTOC}}
[[Ronney:Eiyrt er infobox mapframe|Coordnaidyn]]
ffc33h2v50pav8zk2yzufj2q9bahajb
Clowan:Kishtey fys/styles.css
10
55800
392663
2026-09-01T20:19:55Z
WikiBayer
13794
Duillag crooit lesh: .infobox { border: 1px solid #aaa; background-color: #f9f9f9; border: 1px solid #a2a9b1; color: black; margin: 0.5em 0 0.5em 1em; padding: 0.2em; float: right; clear: right; font-size: 88%; line-height: 1.5em; border-spacing: 3px; margin: 0.5em 0; } @media screen { .infobox { background-color: var(--background-color-neutral-subtle, #f8f9fa); } } @media (max-width: 640px) { .infobox { width: 10...
392663
sanitized-css
text/css
.infobox {
border: 1px solid #aaa;
background-color: #f9f9f9;
border: 1px solid #a2a9b1;
color: black;
margin: 0.5em 0 0.5em 1em;
padding: 0.2em;
float: right;
clear: right;
font-size: 88%;
line-height: 1.5em;
border-spacing: 3px;
margin: 0.5em 0;
}
@media screen {
.infobox {
background-color: var(--background-color-neutral-subtle, #f8f9fa);
}
}
@media (max-width: 640px) {
.infobox {
width: 100%;
}
.infobox .nowrap {
white-space: normal;
}
}
@media (min-width: 640px) {
.infobox {
/* @noflip */
margin-left: 1em;
/* @noflip */
float: right;
/* @noflip */
clear: right;
width: 22em;
}
}
.infobox-label,
.infobox-data,
.infobox th,
.infobox td {
/* @noflip */
text-align: left;
}
.infobox .infobox-above,
.infobox .infobox-title,
.infobox caption {
font-size: 125%;
font-weight: bold;
text-align: center;
}
.infobox-title,
.infobox caption {
font-size: larger;
margin-left: inherit;
padding: 0.2em;
}
.infobox .infobox-header,
.infobox .infobox-subheader,
.infobox .infobox-image,
.infobox .infobox-full-data,
.infobox .infobox-below {
text-align: center;
}
.infobox .infobox-navbar {
/* @noflip */
text-align: right;
}
ntf63y3irryiaovhzongglfiq5f9mns
392669
392663
2026-09-01T20:24:26Z
WikiBayer
13794
[[Mediawiki:Common.css]] import
392669
sanitized-css
text/css
/* Infobox template style */
.infobox {
border: 1px solid #aaa;
background-color: #f9f9f9;
color: black;
margin: 0.5em 0 0.5em 1em;
padding: 0.2em;
float: right;
clear: right;
}
.infobox td,
.infobox th {
vertical-align: top;
}
.infobox caption {
font-size: larger;
margin-left: inherit;
}
.infobox.bordered {
border-collapse: collapse;
}
.infobox.bordered td,
.infobox.bordered th {
border: 1px solid #aaa;
}
.infobox.bordered .borderless td,
.infobox.bordered .borderless th {
border: 0;
}
.infobox.sisterproject {
width: 20em;
font-size: 90%;
}
@media print {
.infobox.sisterproject {
display: none;
}
}
.infobox.standard-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
}
.infobox.standard-talk.bordered td,
.infobox.standard-talk.bordered th {
border: 1px solid #c0c090;
}
/* styles for bordered infobox with merged rows */
.infobox.bordered .mergedtoprow td,
.infobox.bordered .mergedtoprow th {
border: 0;
border-top: 1px solid #aaa;
border-right: 1px solid #aaa;
}
.infobox.bordered .mergedrow td,
.infobox.bordered .mergedrow th {
border: 0;
border-right: 1px solid #aaa;
}
/* Styles for geography infoboxes, e.g. countries, country subdivisions, cities, etc. */
.infobox.geography {
text-align: left;
border-collapse: collapse;
line-height: 1.2em;
font-size: 90%;
}
.infobox.geography td,
.infobox.geography th {
border-top: solid 1px #aaa;
padding: 0.4em 0.6em 0.4em 0.6em;
}
.infobox.geography .mergedtoprow td,
.infobox.geography .mergedtoprow th {
border-top: solid 1px #aaa;
padding: 0.4em 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedrow td,
.infobox.geography .mergedrow th {
border: 0;
padding: 0 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedbottomrow td,
.infobox.geography .mergedbottomrow th {
border-top: 0;
border-bottom: solid 1px #aaa;
padding: 0 0.6em 0.4em 0.6em;
}
.infobox.geography .maptable td,
.infobox.geography .maptable th {
border: 0;
padding: 0;
}
/* Style for "notices" */
.notice {
margin: 1em;
padding: 0.2em;
}
#disambig {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.spoiler {
border-top: 2px solid #ddd;
border-bottom: 2px solid #ddd;
}
hlucl9wixif1se2h30exyprd12fugg9
Ronney:Duillagyn gymmydey infobox mapframe gyn co-ordnaidyn
14
55801
392678
2026-09-01T20:51:39Z
MacTire02
219
Duillag crooit lesh: {{Tracking category|template=Infobox mapframe}} {{CatAutoTOC}} [[Ronney:Eiyrt er infobox mapframe|Coordnaidyn]]
392678
wikitext
text/x-wiki
{{Tracking category|template=Infobox mapframe}}
{{CatAutoTOC}}
[[Ronney:Eiyrt er infobox mapframe|Coordnaidyn]]
ffc33h2v50pav8zk2yzufj2q9bahajb
Clowan:Cowrey raaidey ny h-Ellanyn Goaldagh
10
55802
392680
2026-09-01T21:35:34Z
MacTire02
219
Clowan noa
392680
wikitext
text/x-wiki
<includeonly>{{#switch:{{{2|}}}
| IRL = [[File:{{#switch:{{{1}}}
| M1 | M2 | M3 | M4 | M6 | M7 | M8 | M9 | M11 | M17 | M18 | M20 | M21 | M22 | M23 | M25 | M28 | M50 = {{{1}}}-IE.svg
| #default = IRL_{{{1}}}.svg
}}|x30px|link=]]
| #default = [[Coadan:UK_road_{{{1}}}.svg|x30px|link=]]
}}{{#ifeq:{{{art|n}}}|y| [[{{{1}}} ({{#switch:{{{2|}}}
| IRL = Nerin
| NIR = Nerin Hwoaie
| ENG = Sostyn
| SCO = Nalbin
| WAL = Bretyn
| GBM | IOM = Mannin
| GBJ | JER = Jersee
| GBG | GUE = Guernsey
| #default = {{{2}}}
}})|{{{1}}}]]}}</includeonly>
<noinclude>
Usage:
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL|art=y}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|A1|GBM|art=y}}</nowiki></code>
* <code><nowiki>{{ERAA|A1|IOM|art=y}}</nowiki></code>
The marker is always 30px high and cannot be clicked. With <code>art=y</code>, only the route-number text links to the article.
</noinclude>
33x6vkwawuzeieqw3iy0daaphm5sn4i
392682
392680
2026-09-01T21:37:38Z
MacTire02
219
prowal y mooadys
392682
wikitext
text/x-wiki
<includeonly>{{#switch:{{{2|}}}
| IRL = [[File:{{#switch:{{{1}}}
| M1 | M2 | M3 | M4 | M6 | M7 | M8 | M9 | M11 | M17 | M18 | M20 | M21 | M22 | M23 | M25 | M28 | M50 = {{{1}}}-IE.svg
| #default = IRL_{{{1}}}.svg
}}|x30px|link=]]
| #default = [[Coadan:UK_road_{{{1}}}.svg|x25px|link=]]
}}{{#ifeq:{{{art|n}}}|y| [[{{{1}}} ({{#switch:{{{2|}}}
| IRL = Nerin
| NIR = Nerin Hwoaie
| ENG = Sostyn
| SCO = Nalbin
| WAL = Bretyn
| GBM | IOM = Mannin
| GBJ | JER = Jersee
| GBG | GUE = Guernsey
| #default = {{{2}}}
}})|{{{1}}}]]}}</includeonly>
<noinclude>
Usage:
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL|art=y}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|A1|GBM|art=y}}</nowiki></code>
* <code><nowiki>{{ERAA|A1|IOM|art=y}}</nowiki></code>
The marker is always 30px high and cannot be clicked. With <code>art=y</code>, only the route-number text links to the article.
</noinclude>
mm2oqpfea8kq4ehtorkpwtov00h6ksq
392683
392682
2026-09-01T21:37:59Z
MacTire02
219
jeant
392683
wikitext
text/x-wiki
<includeonly>{{#switch:{{{2|}}}
| IRL = [[File:{{#switch:{{{1}}}
| M1 | M2 | M3 | M4 | M6 | M7 | M8 | M9 | M11 | M17 | M18 | M20 | M21 | M22 | M23 | M25 | M28 | M50 = {{{1}}}-IE.svg
| #default = IRL_{{{1}}}.svg
}}|x30px|link=]]
| #default = [[Coadan:UK_road_{{{1}}}.svg|x22px|link=]]
}}{{#ifeq:{{{art|n}}}|y| [[{{{1}}} ({{#switch:{{{2|}}}
| IRL = Nerin
| NIR = Nerin Hwoaie
| ENG = Sostyn
| SCO = Nalbin
| WAL = Bretyn
| GBM | IOM = Mannin
| GBJ | JER = Jersee
| GBG | GUE = Guernsey
| #default = {{{2}}}
}})|{{{1}}}]]}}</includeonly>
<noinclude>
Usage:
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|N3|IRL|art=y}}</nowiki></code>
* <code><nowiki>{{Cowrey raaidey ny h-Ellanyn Goaldagh|A1|GBM|art=y}}</nowiki></code>
* <code><nowiki>{{ERAA|A1|IOM|art=y}}</nowiki></code>
The marker is always 30px high and cannot be clicked. With <code>art=y</code>, only the route-number text links to the article.
</noinclude>
n0jj8fyvnfd21j5kd8ye0k13llxr0pc
Clowan:ERAA
10
55803
392681
2026-09-01T21:35:59Z
MacTire02
219
aastiurey
392681
wikitext
text/x-wiki
#REDIRECT [[Clowan:Cowrey raaidey ny h-Ellanyn Goaldagh]]
8gm0pzuja32fjxi8l8nfq6ia9i2utl0
Clowan:Infobox river/calcunit
10
55804
392687
2026-09-01T23:07:10Z
MacTire02
219
cl
392687
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{free|}}}
|{{{free}}}{{#if:{{isnumeric|{{{free}}}}}| {{error|units?}}[[Ronney:Artyn as feme er scrutaghey unnidyn]]}}
|{{#if:{{{met|}}}
|{{convert|{{{met}}}|{{{met_unit|km}}}|abbr=on}}
|{{#if:{{{imp|}}}
|{{convert|{{{imp}}}|{{{imp_unit|mi}}}|abbr=on}}
}}
}}
}}
3kixzpseu8p5wsgqu9tpq1w2pxiwq2z
Clowan:Infobox river/row-style
10
55805
392688
2026-09-01T23:09:10Z
MacTire02
219
clowan noa
392688
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>padding: 0 0.6em 0.2em 0.6em;line-height: 1.2em;
f677wiw8m0s0nfn9aecylac1vg004t5
392714
392688
2026-09-02T01:27:46Z
MacTire02
219
++
392714
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>padding: 0 0.6em 0.2em 0.6em;line-height: 1.2em; font-size:85%;
ksg590ebpvxgd4ceyssr6ztlnionto0
392715
392714
2026-09-02T01:28:20Z
MacTire02
219
--
392715
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>padding: 0 0.6em 0.2em 0.6em;line-height: 1.2em;
f677wiw8m0s0nfn9aecylac1vg004t5
Clowan:Infobox river/source
10
55806
392689
2026-09-01T23:12:35Z
MacTire02
219
clowan noa
392689
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
b4snbfpuwbv87xhta5vw559y3r60gbj
392708
392689
2026-09-02T01:21:53Z
MacTire02
219
prowal
392708
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
ohpod9yho2rmyu9jrpuzhq11au6nz6u
392709
392708
2026-09-02T01:22:28Z
MacTire02
219
++
392709
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:100%;
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
iq0jjl3ut19kpyjocevq5dl6s0mpxn2
392710
392709
2026-09-02T01:22:52Z
MacTire02
219
++
392710
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:95%;
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
5r3b2svb5qgz4k170ur4dbfd5b1kcoh
392711
392710
2026-09-02T01:24:39Z
MacTire02
219
++
392711
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:90%;
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
gp7ov5zg2lmy65rd2wt5nxams8z6tvn
392712
392711
2026-09-02T01:25:42Z
MacTire02
219
++
392712
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{#if:{{{source|}}}{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| child = yes
| label1 = {{#if:{{{1|}}}|{{{1}}}|Moir}}
| data1 = {{#if:{{{source|}}}|{{{source}}}|{{#if:{{{loc|}}}{{{coord|}}}{{{len|}}}{{{elev|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • co-ordnaidyn</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{coord|}}}{{{coord_ref|}}}
| label4 = <span style="font-weight:normal"> • lhiurid</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{len|}}}
| label5 = <span style="font-weight:normal"> • yrjid</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{elev|}}}
}}}}
ovauwoezqh5gsnxhmt2nwj4rafq3sp2
Clowan:Infobox river/discharge
10
55807
392692
2026-09-01T23:41:35Z
MacTire02
219
Duillag crooit lesh: {{#if:{{{discharge|}}}{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}|{{infobox | child = yes | label1 = Stroo magh | rowstyle1 = {{Infobox river/row-style}} | data1 = {{#if:{{{discharge|}}}|{{{discharge}}}|{{#if:{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}| }}}} | label2 = <span style="font-weight:normal"> • location</span> | rowstyle2 = {{Infobox river/row-style}} | data2 = {{{loc|}}} | label3 = <span style="font-weight:normal"> ...
392692
wikitext
text/x-wiki
{{#if:{{{discharge|}}}{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}|{{infobox
| child = yes
| label1 = Stroo magh
| rowstyle1 = {{Infobox river/row-style}}
| data1 = {{#if:{{{discharge|}}}|{{{discharge}}}|{{#if:{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}| }}}}
| label2 = <span style="font-weight:normal"> • location</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{avg|}}}
| label4 = <span style="font-weight:normal"> • sloo</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{min|}}}
| label5 = <span style="font-weight:normal"> • smoo</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{max|}}}
}}}}<noinclude>
{{Documentation}}
</noinclude>
omhrp2mdogz1eqe62zpk99nm1o59166
392713
392692
2026-09-02T01:26:47Z
MacTire02
219
++
392713
wikitext
text/x-wiki
{{#if:{{{discharge|}}}{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| child = yes
| label1 = Stroo magh
| rowstyle1 = {{Infobox river/row-style}}
| data1 = {{#if:{{{discharge|}}}|{{{discharge}}}|{{#if:{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}| }}}}
| label2 = <span style="font-weight:normal"> • location</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{avg|}}}
| label4 = <span style="font-weight:normal"> • sloo</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{min|}}}
| label5 = <span style="font-weight:normal"> • smoo</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{max|}}}
}}}}<noinclude>
{{Documentation}}
</noinclude>
kwpsae3pxupywg15o2ub6mvvwx3g2xh
392717
392713
2026-09-02T01:45:33Z
MacTire02
219
++
392717
wikitext
text/x-wiki
{{#if:{{{discharge|}}}{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}|{{infobox
| labelstyle = padding:0.2em 1.0em 0.2em 0.2em; background:transparent; line-height:1.3em; text-align:left; font-size:85%;
| datastyle = padding:0.2em; line-height:1.3em; vertical-align:middle; font-size:85%;
| child = yes
| label1 = Stroo magh
| rowstyle1 = {{Infobox river/row-style}}
| data1 = {{#if:{{{discharge|}}}|{{{discharge}}}|{{#if:{{{loc|}}}{{{min|}}}{{{avg|}}}{{{max|}}}| }}}}
| label2 = <span style="font-weight:normal"> • soiaghey</span>
| rowstyle2 = {{Infobox river/row-style}}
| data2 = {{{loc|}}}
| label3 = <span style="font-weight:normal"> • meanagh</span>
| rowstyle3 = {{Infobox river/row-style}}
| data3 = {{{avg|}}}
| label4 = <span style="font-weight:normal"> • sloo</span>
| rowstyle4 = {{Infobox river/row-style}}
| data4 = {{{min|}}}
| label5 = <span style="font-weight:normal"> • smoo</span>
| rowstyle5 = {{Infobox river/row-style}}
| data5 = {{{max|}}}
}}}}<noinclude>
{{Documentation}}
</noinclude>
7b5yltpk5t5g7mkpftrcq4f3pse0tnq
Clowan:Infobox river
10
55808
392693
2026-09-01T23:42:04Z
MacTire02
219
aastiurey
392693
wikitext
text/x-wiki
#REDIRECT [[Clowan:Kishtey fys awin]]
5ubh1jjpvobbem39x6h2z9g4spvsps3
Clowan:Native name
10
55809
392703
2026-09-02T00:55:14Z
MacTire02
219
clowan noa
392703
wikitext
text/x-wiki
<includeonly>{{#invoke:native name|native_name}}</includeonly><noinclude>{{Documentation}}</noinclude>
gp4mircewcgfc8vfhzojwwumum7hr0j
Module:Unicode data/scripts
828
55810
392704
2026-09-02T00:59:20Z
MacTire02
219
Duillag crooit lesh: --[=[ -- Official Unicode script values for individual codepoints and ranges of -- codepoints. -- https://www.unicode.org/Public/UNIDATA/Scripts.txt provided -- the script names, and https://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt -- provided script codes corresponding to the names (see [[Script (Unicode)]]). --]=] local data = { singles = { [0x000AA] = "Latn", [0x000BA] = "Latn", [0x000D7] = "Zyyy", [0x000F7] = "Zyyy", [0x00374] = "Zyyy",...
392704
Scribunto
text/plain
--[=[
-- Official Unicode script values for individual codepoints and ranges of
-- codepoints.
-- https://www.unicode.org/Public/UNIDATA/Scripts.txt provided
-- the script names, and https://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt
-- provided script codes corresponding to the names (see [[Script (Unicode)]]).
--]=]
local data = {
singles = {
[0x000AA] = "Latn",
[0x000BA] = "Latn",
[0x000D7] = "Zyyy",
[0x000F7] = "Zyyy",
[0x00374] = "Zyyy",
[0x0037E] = "Zyyy",
[0x0037F] = "Grek",
[0x00384] = "Grek",
[0x00385] = "Zyyy",
[0x00386] = "Grek",
[0x00387] = "Zyyy",
[0x0038C] = "Grek",
[0x00605] = "Zyyy",
[0x0060C] = "Zyyy",
[0x0061B] = "Zyyy",
[0x0061F] = "Zyyy",
[0x00640] = "Zyyy",
[0x00670] = "Zinh",
[0x006DD] = "Zyyy",
[0x0085E] = "Mand",
[0x008E2] = "Zyyy",
[0x009B2] = "Beng",
[0x009D7] = "Beng",
[0x00A3C] = "Guru",
[0x00A51] = "Guru",
[0x00A5E] = "Guru",
[0x00AD0] = "Gujr",
[0x00B9C] = "Taml",
[0x00BD0] = "Taml",
[0x00BD7] = "Taml",
[0x00DBD] = "Sinh",
[0x00DCA] = "Sinh",
[0x00DD6] = "Sinh",
[0x00E3F] = "Zyyy",
[0x00E84] = "Laoo",
[0x00EA5] = "Laoo",
[0x00EC6] = "Laoo",
[0x010C7] = "Geor",
[0x010CD] = "Geor",
[0x010FB] = "Zyyy",
[0x01258] = "Ethi",
[0x012C0] = "Ethi",
[0x0171F] = "Tglg",
[0x01804] = "Mong",
[0x01805] = "Zyyy",
[0x01940] = "Limb",
[0x01CD3] = "Zyyy",
[0x01CE1] = "Zyyy",
[0x01CED] = "Zinh",
[0x01CF4] = "Zinh",
[0x01CFA] = "Zyyy",
[0x01D2B] = "Cyrl",
[0x01D78] = "Cyrl",
[0x01DBF] = "Grek",
[0x01F59] = "Grek",
[0x01F5B] = "Grek",
[0x01F5D] = "Grek",
[0x02071] = "Latn",
[0x0207F] = "Latn",
[0x02126] = "Grek",
[0x02132] = "Latn",
[0x0214E] = "Latn",
[0x02D27] = "Geor",
[0x02D2D] = "Geor",
[0x02D7F] = "Tfng",
[0x03005] = "Hani",
[0x03006] = "Zyyy",
[0x03007] = "Hani",
[0x030A0] = "Zyyy",
[0x031EF] = "Zyyy",
[0x032FF] = "Zyyy",
[0x0A92E] = "Zyyy",
[0x0A92F] = "Kali",
[0x0A95F] = "Rjng",
[0x0A9CF] = "Zyyy",
[0x0AB5B] = "Zyyy",
[0x0AB65] = "Grek",
[0x0FB3E] = "Hebr",
[0x0FEFF] = "Zyyy",
[0x0FF70] = "Zyyy",
[0x101A0] = "Grek",
[0x101FD] = "Zinh",
[0x102E0] = "Zinh",
[0x1039F] = "Ugar",
[0x1056F] = "Aghb",
[0x10808] = "Cprt",
[0x1083C] = "Cprt",
[0x1083F] = "Cprt",
[0x1091F] = "Phnx",
[0x1093F] = "Lydi",
[0x1107F] = "Brah",
[0x110CD] = "Kthi",
[0x11288] = "Mult",
[0x1133B] = "Zinh",
[0x11350] = "Gran",
[0x11357] = "Gran",
[0x1138B] = "Tutg",
[0x1138E] = "Tutg",
[0x113C2] = "Tutg",
[0x113C5] = "Tutg",
[0x118FF] = "Wara",
[0x11909] = "Diak",
[0x11D3A] = "Gonm",
[0x11FB0] = "Lisu",
[0x11FFF] = "Taml",
[0x16FE0] = "Tang",
[0x16FE1] = "Nshu",
[0x16FE4] = "Kits",
[0x18CFF] = "Kits",
[0x1B000] = "Kana",
[0x1B132] = "Hira",
[0x1B155] = "Kana",
[0x1D4A2] = "Zyyy",
[0x1D4BB] = "Zyyy",
[0x1D546] = "Zyyy",
[0x1E08F] = "Cyrl",
[0x1E2FF] = "Wcho",
[0x1E5FF] = "Onao",
[0x1EE24] = "Arab",
[0x1EE27] = "Arab",
[0x1EE39] = "Arab",
[0x1EE3B] = "Arab",
[0x1EE42] = "Arab",
[0x1EE47] = "Arab",
[0x1EE49] = "Arab",
[0x1EE4B] = "Arab",
[0x1EE54] = "Arab",
[0x1EE57] = "Arab",
[0x1EE59] = "Arab",
[0x1EE5B] = "Arab",
[0x1EE5D] = "Arab",
[0x1EE5F] = "Arab",
[0x1EE64] = "Arab",
[0x1EE7E] = "Arab",
[0x1F200] = "Hira",
[0x1F7F0] = "Zyyy",
[0x1FAC8] = "Zyyy",
[0xE0001] = "Zyyy",
},
ranges = {
{ 0x00000, 0x00040, "Zyyy" },
{ 0x00041, 0x0005A, "Latn" },
{ 0x0005B, 0x00060, "Zyyy" },
{ 0x00061, 0x0007A, "Latn" },
{ 0x0007B, 0x000A9, "Zyyy" },
{ 0x000AB, 0x000B9, "Zyyy" },
{ 0x000BB, 0x000BF, "Zyyy" },
{ 0x000C0, 0x000D6, "Latn" },
{ 0x000D8, 0x000F6, "Latn" },
{ 0x000F8, 0x002B8, "Latn" },
{ 0x002B9, 0x002DF, "Zyyy" },
{ 0x002E0, 0x002E4, "Latn" },
{ 0x002E5, 0x002E9, "Zyyy" },
{ 0x002EA, 0x002EB, "Bopo" },
{ 0x002EC, 0x002FF, "Zyyy" },
{ 0x00300, 0x0036F, "Zinh" },
{ 0x00370, 0x00373, "Grek" },
{ 0x00375, 0x00377, "Grek" },
{ 0x0037A, 0x0037D, "Grek" },
{ 0x00388, 0x0038A, "Grek" },
{ 0x0038E, 0x003A1, "Grek" },
{ 0x003A3, 0x003E1, "Grek" },
{ 0x003E2, 0x003EF, "Copt" },
{ 0x003F0, 0x003FF, "Grek" },
{ 0x00400, 0x00484, "Cyrl" },
{ 0x00485, 0x00486, "Zinh" },
{ 0x00487, 0x0052F, "Cyrl" },
{ 0x00531, 0x00556, "Armn" },
{ 0x00559, 0x0058A, "Armn" },
{ 0x0058D, 0x0058F, "Armn" },
{ 0x00591, 0x005C7, "Hebr" },
{ 0x005D0, 0x005EA, "Hebr" },
{ 0x005EF, 0x005F4, "Hebr" },
{ 0x00600, 0x00604, "Arab" },
{ 0x00606, 0x0060B, "Arab" },
{ 0x0060D, 0x0061A, "Arab" },
{ 0x0061C, 0x0061E, "Arab" },
{ 0x00620, 0x0063F, "Arab" },
{ 0x00641, 0x0064A, "Arab" },
{ 0x0064B, 0x00655, "Zinh" },
{ 0x00656, 0x0066F, "Arab" },
{ 0x00671, 0x006DC, "Arab" },
{ 0x006DE, 0x006FF, "Arab" },
{ 0x00700, 0x0070D, "Syrc" },
{ 0x0070F, 0x0074A, "Syrc" },
{ 0x0074D, 0x0074F, "Syrc" },
{ 0x00750, 0x0077F, "Arab" },
{ 0x00780, 0x007B1, "Thaa" },
{ 0x007C0, 0x007FA, "Nkoo" },
{ 0x007FD, 0x007FF, "Nkoo" },
{ 0x00800, 0x0082D, "Samr" },
{ 0x00830, 0x0083E, "Samr" },
{ 0x00840, 0x0085B, "Mand" },
{ 0x00860, 0x0086A, "Syrc" },
{ 0x00870, 0x00891, "Arab" },
{ 0x00897, 0x008E1, "Arab" },
{ 0x008E3, 0x008FF, "Arab" },
{ 0x00900, 0x00950, "Deva" },
{ 0x00951, 0x00954, "Zinh" },
{ 0x00955, 0x00963, "Deva" },
{ 0x00964, 0x00965, "Zyyy" },
{ 0x00966, 0x0097F, "Deva" },
{ 0x00980, 0x00983, "Beng" },
{ 0x00985, 0x0098C, "Beng" },
{ 0x0098F, 0x00990, "Beng" },
{ 0x00993, 0x009A8, "Beng" },
{ 0x009AA, 0x009B0, "Beng" },
{ 0x009B6, 0x009B9, "Beng" },
{ 0x009BC, 0x009C4, "Beng" },
{ 0x009C7, 0x009C8, "Beng" },
{ 0x009CB, 0x009CE, "Beng" },
{ 0x009DC, 0x009DD, "Beng" },
{ 0x009DF, 0x009E3, "Beng" },
{ 0x009E6, 0x009FE, "Beng" },
{ 0x00A01, 0x00A03, "Guru" },
{ 0x00A05, 0x00A0A, "Guru" },
{ 0x00A0F, 0x00A10, "Guru" },
{ 0x00A13, 0x00A28, "Guru" },
{ 0x00A2A, 0x00A30, "Guru" },
{ 0x00A32, 0x00A33, "Guru" },
{ 0x00A35, 0x00A36, "Guru" },
{ 0x00A38, 0x00A39, "Guru" },
{ 0x00A3E, 0x00A42, "Guru" },
{ 0x00A47, 0x00A48, "Guru" },
{ 0x00A4B, 0x00A4D, "Guru" },
{ 0x00A59, 0x00A5C, "Guru" },
{ 0x00A66, 0x00A76, "Guru" },
{ 0x00A81, 0x00A83, "Gujr" },
{ 0x00A85, 0x00A8D, "Gujr" },
{ 0x00A8F, 0x00A91, "Gujr" },
{ 0x00A93, 0x00AA8, "Gujr" },
{ 0x00AAA, 0x00AB0, "Gujr" },
{ 0x00AB2, 0x00AB3, "Gujr" },
{ 0x00AB5, 0x00AB9, "Gujr" },
{ 0x00ABC, 0x00AC5, "Gujr" },
{ 0x00AC7, 0x00AC9, "Gujr" },
{ 0x00ACB, 0x00ACD, "Gujr" },
{ 0x00AE0, 0x00AE3, "Gujr" },
{ 0x00AE6, 0x00AF1, "Gujr" },
{ 0x00AF9, 0x00AFF, "Gujr" },
{ 0x00B01, 0x00B03, "Orya" },
{ 0x00B05, 0x00B0C, "Orya" },
{ 0x00B0F, 0x00B10, "Orya" },
{ 0x00B13, 0x00B28, "Orya" },
{ 0x00B2A, 0x00B30, "Orya" },
{ 0x00B32, 0x00B33, "Orya" },
{ 0x00B35, 0x00B39, "Orya" },
{ 0x00B3C, 0x00B44, "Orya" },
{ 0x00B47, 0x00B48, "Orya" },
{ 0x00B4B, 0x00B4D, "Orya" },
{ 0x00B55, 0x00B57, "Orya" },
{ 0x00B5C, 0x00B5D, "Orya" },
{ 0x00B5F, 0x00B63, "Orya" },
{ 0x00B66, 0x00B77, "Orya" },
{ 0x00B82, 0x00B83, "Taml" },
{ 0x00B85, 0x00B8A, "Taml" },
{ 0x00B8E, 0x00B90, "Taml" },
{ 0x00B92, 0x00B95, "Taml" },
{ 0x00B99, 0x00B9A, "Taml" },
{ 0x00B9E, 0x00B9F, "Taml" },
{ 0x00BA3, 0x00BA4, "Taml" },
{ 0x00BA8, 0x00BAA, "Taml" },
{ 0x00BAE, 0x00BB9, "Taml" },
{ 0x00BBE, 0x00BC2, "Taml" },
{ 0x00BC6, 0x00BC8, "Taml" },
{ 0x00BCA, 0x00BCD, "Taml" },
{ 0x00BE6, 0x00BFA, "Taml" },
{ 0x00C00, 0x00C0C, "Telu" },
{ 0x00C0E, 0x00C10, "Telu" },
{ 0x00C12, 0x00C28, "Telu" },
{ 0x00C2A, 0x00C39, "Telu" },
{ 0x00C3C, 0x00C44, "Telu" },
{ 0x00C46, 0x00C48, "Telu" },
{ 0x00C4A, 0x00C4D, "Telu" },
{ 0x00C55, 0x00C56, "Telu" },
{ 0x00C58, 0x00C5A, "Telu" },
{ 0x00C5C, 0x00C5D, "Telu" },
{ 0x00C60, 0x00C63, "Telu" },
{ 0x00C66, 0x00C6F, "Telu" },
{ 0x00C77, 0x00C7F, "Telu" },
{ 0x00C80, 0x00C8C, "Knda" },
{ 0x00C8E, 0x00C90, "Knda" },
{ 0x00C92, 0x00CA8, "Knda" },
{ 0x00CAA, 0x00CB3, "Knda" },
{ 0x00CB5, 0x00CB9, "Knda" },
{ 0x00CBC, 0x00CC4, "Knda" },
{ 0x00CC6, 0x00CC8, "Knda" },
{ 0x00CCA, 0x00CCD, "Knda" },
{ 0x00CD5, 0x00CD6, "Knda" },
{ 0x00CDC, 0x00CDE, "Knda" },
{ 0x00CE0, 0x00CE3, "Knda" },
{ 0x00CE6, 0x00CEF, "Knda" },
{ 0x00CF1, 0x00CF3, "Knda" },
{ 0x00D00, 0x00D0C, "Mlym" },
{ 0x00D0E, 0x00D10, "Mlym" },
{ 0x00D12, 0x00D44, "Mlym" },
{ 0x00D46, 0x00D48, "Mlym" },
{ 0x00D4A, 0x00D4F, "Mlym" },
{ 0x00D54, 0x00D63, "Mlym" },
{ 0x00D66, 0x00D7F, "Mlym" },
{ 0x00D81, 0x00D83, "Sinh" },
{ 0x00D85, 0x00D96, "Sinh" },
{ 0x00D9A, 0x00DB1, "Sinh" },
{ 0x00DB3, 0x00DBB, "Sinh" },
{ 0x00DC0, 0x00DC6, "Sinh" },
{ 0x00DCF, 0x00DD4, "Sinh" },
{ 0x00DD8, 0x00DDF, "Sinh" },
{ 0x00DE6, 0x00DEF, "Sinh" },
{ 0x00DF2, 0x00DF4, "Sinh" },
{ 0x00E01, 0x00E3A, "Thai" },
{ 0x00E40, 0x00E5B, "Thai" },
{ 0x00E81, 0x00E82, "Laoo" },
{ 0x00E86, 0x00E8A, "Laoo" },
{ 0x00E8C, 0x00EA3, "Laoo" },
{ 0x00EA7, 0x00EBD, "Laoo" },
{ 0x00EC0, 0x00EC4, "Laoo" },
{ 0x00EC8, 0x00ECE, "Laoo" },
{ 0x00ED0, 0x00ED9, "Laoo" },
{ 0x00EDC, 0x00EDF, "Laoo" },
{ 0x00F00, 0x00F47, "Tibt" },
{ 0x00F49, 0x00F6C, "Tibt" },
{ 0x00F71, 0x00F97, "Tibt" },
{ 0x00F99, 0x00FBC, "Tibt" },
{ 0x00FBE, 0x00FCC, "Tibt" },
{ 0x00FCE, 0x00FD4, "Tibt" },
{ 0x00FD5, 0x00FD8, "Zyyy" },
{ 0x00FD9, 0x00FDA, "Tibt" },
{ 0x01000, 0x0109F, "Mymr" },
{ 0x010A0, 0x010C5, "Geor" },
{ 0x010D0, 0x010FA, "Geor" },
{ 0x010FC, 0x010FF, "Geor" },
{ 0x01100, 0x011FF, "Hang" },
{ 0x01200, 0x01248, "Ethi" },
{ 0x0124A, 0x0124D, "Ethi" },
{ 0x01250, 0x01256, "Ethi" },
{ 0x0125A, 0x0125D, "Ethi" },
{ 0x01260, 0x01288, "Ethi" },
{ 0x0128A, 0x0128D, "Ethi" },
{ 0x01290, 0x012B0, "Ethi" },
{ 0x012B2, 0x012B5, "Ethi" },
{ 0x012B8, 0x012BE, "Ethi" },
{ 0x012C2, 0x012C5, "Ethi" },
{ 0x012C8, 0x012D6, "Ethi" },
{ 0x012D8, 0x01310, "Ethi" },
{ 0x01312, 0x01315, "Ethi" },
{ 0x01318, 0x0135A, "Ethi" },
{ 0x0135D, 0x0137C, "Ethi" },
{ 0x01380, 0x01399, "Ethi" },
{ 0x013A0, 0x013F5, "Cher" },
{ 0x013F8, 0x013FD, "Cher" },
{ 0x01400, 0x0167F, "Cans" },
{ 0x01680, 0x0169C, "Ogam" },
{ 0x016A0, 0x016EA, "Runr" },
{ 0x016EB, 0x016ED, "Zyyy" },
{ 0x016EE, 0x016F8, "Runr" },
{ 0x01700, 0x01715, "Tglg" },
{ 0x01720, 0x01734, "Hano" },
{ 0x01735, 0x01736, "Zyyy" },
{ 0x01740, 0x01753, "Buhd" },
{ 0x01760, 0x0176C, "Tagb" },
{ 0x0176E, 0x01770, "Tagb" },
{ 0x01772, 0x01773, "Tagb" },
{ 0x01780, 0x017DD, "Khmr" },
{ 0x017E0, 0x017E9, "Khmr" },
{ 0x017F0, 0x017F9, "Khmr" },
{ 0x01800, 0x01801, "Mong" },
{ 0x01802, 0x01803, "Zyyy" },
{ 0x01806, 0x01819, "Mong" },
{ 0x01820, 0x01878, "Mong" },
{ 0x01880, 0x018AA, "Mong" },
{ 0x018B0, 0x018F5, "Cans" },
{ 0x01900, 0x0191E, "Limb" },
{ 0x01920, 0x0192B, "Limb" },
{ 0x01930, 0x0193B, "Limb" },
{ 0x01944, 0x0194F, "Limb" },
{ 0x01950, 0x0196D, "Tale" },
{ 0x01970, 0x01974, "Tale" },
{ 0x01980, 0x019AB, "Talu" },
{ 0x019B0, 0x019C9, "Talu" },
{ 0x019D0, 0x019DA, "Talu" },
{ 0x019DE, 0x019DF, "Talu" },
{ 0x019E0, 0x019FF, "Khmr" },
{ 0x01A00, 0x01A1B, "Bugi" },
{ 0x01A1E, 0x01A1F, "Bugi" },
{ 0x01A20, 0x01A5E, "Lana" },
{ 0x01A60, 0x01A7C, "Lana" },
{ 0x01A7F, 0x01A89, "Lana" },
{ 0x01A90, 0x01A99, "Lana" },
{ 0x01AA0, 0x01AAD, "Lana" },
{ 0x01AB0, 0x01ADD, "Zinh" },
{ 0x01AE0, 0x01AEB, "Zinh" },
{ 0x01B00, 0x01B4C, "Bali" },
{ 0x01B4E, 0x01B7F, "Bali" },
{ 0x01B80, 0x01BBF, "Sund" },
{ 0x01BC0, 0x01BF3, "Batk" },
{ 0x01BFC, 0x01BFF, "Batk" },
{ 0x01C00, 0x01C37, "Lepc" },
{ 0x01C3B, 0x01C49, "Lepc" },
{ 0x01C4D, 0x01C4F, "Lepc" },
{ 0x01C50, 0x01C7F, "Olck" },
{ 0x01C80, 0x01C8A, "Cyrl" },
{ 0x01C90, 0x01CBA, "Geor" },
{ 0x01CBD, 0x01CBF, "Geor" },
{ 0x01CC0, 0x01CC7, "Sund" },
{ 0x01CD0, 0x01CD2, "Zinh" },
{ 0x01CD4, 0x01CE0, "Zinh" },
{ 0x01CE2, 0x01CE8, "Zinh" },
{ 0x01CE9, 0x01CEC, "Zyyy" },
{ 0x01CEE, 0x01CF3, "Zyyy" },
{ 0x01CF5, 0x01CF7, "Zyyy" },
{ 0x01CF8, 0x01CF9, "Zinh" },
{ 0x01D00, 0x01D25, "Latn" },
{ 0x01D26, 0x01D2A, "Grek" },
{ 0x01D2C, 0x01D5C, "Latn" },
{ 0x01D5D, 0x01D61, "Grek" },
{ 0x01D62, 0x01D65, "Latn" },
{ 0x01D66, 0x01D6A, "Grek" },
{ 0x01D6B, 0x01D77, "Latn" },
{ 0x01D79, 0x01DBE, "Latn" },
{ 0x01DC0, 0x01DFF, "Zinh" },
{ 0x01E00, 0x01EFF, "Latn" },
{ 0x01F00, 0x01F15, "Grek" },
{ 0x01F18, 0x01F1D, "Grek" },
{ 0x01F20, 0x01F45, "Grek" },
{ 0x01F48, 0x01F4D, "Grek" },
{ 0x01F50, 0x01F57, "Grek" },
{ 0x01F5F, 0x01F7D, "Grek" },
{ 0x01F80, 0x01FB4, "Grek" },
{ 0x01FB6, 0x01FC4, "Grek" },
{ 0x01FC6, 0x01FD3, "Grek" },
{ 0x01FD6, 0x01FDB, "Grek" },
{ 0x01FDD, 0x01FEF, "Grek" },
{ 0x01FF2, 0x01FF4, "Grek" },
{ 0x01FF6, 0x01FFE, "Grek" },
{ 0x02000, 0x0200B, "Zyyy" },
{ 0x0200C, 0x0200D, "Zinh" },
{ 0x0200E, 0x02064, "Zyyy" },
{ 0x02066, 0x02070, "Zyyy" },
{ 0x02074, 0x0207E, "Zyyy" },
{ 0x02080, 0x0208E, "Zyyy" },
{ 0x02090, 0x0209C, "Latn" },
{ 0x020A0, 0x020C1, "Zyyy" },
{ 0x020D0, 0x020F0, "Zinh" },
{ 0x02100, 0x02125, "Zyyy" },
{ 0x02127, 0x02129, "Zyyy" },
{ 0x0212A, 0x0212B, "Latn" },
{ 0x0212C, 0x02131, "Zyyy" },
{ 0x02133, 0x0214D, "Zyyy" },
{ 0x0214F, 0x0215F, "Zyyy" },
{ 0x02160, 0x02188, "Latn" },
{ 0x02189, 0x0218B, "Zyyy" },
{ 0x02190, 0x02429, "Zyyy" },
{ 0x02440, 0x0244A, "Zyyy" },
{ 0x02460, 0x027FF, "Zyyy" },
{ 0x02800, 0x028FF, "Brai" },
{ 0x02900, 0x02B73, "Zyyy" },
{ 0x02B76, 0x02BFF, "Zyyy" },
{ 0x02C00, 0x02C5F, "Glag" },
{ 0x02C60, 0x02C7F, "Latn" },
{ 0x02C80, 0x02CF3, "Copt" },
{ 0x02CF9, 0x02CFF, "Copt" },
{ 0x02D00, 0x02D25, "Geor" },
{ 0x02D30, 0x02D67, "Tfng" },
{ 0x02D6F, 0x02D70, "Tfng" },
{ 0x02D80, 0x02D96, "Ethi" },
{ 0x02DA0, 0x02DA6, "Ethi" },
{ 0x02DA8, 0x02DAE, "Ethi" },
{ 0x02DB0, 0x02DB6, "Ethi" },
{ 0x02DB8, 0x02DBE, "Ethi" },
{ 0x02DC0, 0x02DC6, "Ethi" },
{ 0x02DC8, 0x02DCE, "Ethi" },
{ 0x02DD0, 0x02DD6, "Ethi" },
{ 0x02DD8, 0x02DDE, "Ethi" },
{ 0x02DE0, 0x02DFF, "Cyrl" },
{ 0x02E00, 0x02E5D, "Zyyy" },
{ 0x02E80, 0x02E99, "Hani" },
{ 0x02E9B, 0x02EF3, "Hani" },
{ 0x02F00, 0x02FD5, "Hani" },
{ 0x02FF0, 0x03004, "Zyyy" },
{ 0x03008, 0x03020, "Zyyy" },
{ 0x03021, 0x03029, "Hani" },
{ 0x0302A, 0x0302D, "Zinh" },
{ 0x0302E, 0x0302F, "Hang" },
{ 0x03030, 0x03037, "Zyyy" },
{ 0x03038, 0x0303B, "Hani" },
{ 0x0303C, 0x0303F, "Zyyy" },
{ 0x03041, 0x03096, "Hira" },
{ 0x03099, 0x0309A, "Zinh" },
{ 0x0309B, 0x0309C, "Zyyy" },
{ 0x0309D, 0x0309F, "Hira" },
{ 0x030A1, 0x030FA, "Kana" },
{ 0x030FB, 0x030FC, "Zyyy" },
{ 0x030FD, 0x030FF, "Kana" },
{ 0x03105, 0x0312F, "Bopo" },
{ 0x03131, 0x0318E, "Hang" },
{ 0x03190, 0x0319F, "Zyyy" },
{ 0x031A0, 0x031BF, "Bopo" },
{ 0x031C0, 0x031E5, "Zyyy" },
{ 0x031F0, 0x031FF, "Kana" },
{ 0x03200, 0x0321E, "Hang" },
{ 0x03220, 0x0325F, "Zyyy" },
{ 0x03260, 0x0327E, "Hang" },
{ 0x0327F, 0x032CF, "Zyyy" },
{ 0x032D0, 0x032FE, "Kana" },
{ 0x03300, 0x03357, "Kana" },
{ 0x03358, 0x033FF, "Zyyy" },
{ 0x03400, 0x04DBF, "Hani" },
{ 0x04DC0, 0x04DFF, "Zyyy" },
{ 0x04E00, 0x09FFF, "Hani" },
{ 0x0A000, 0x0A48C, "Yiii" },
{ 0x0A490, 0x0A4C6, "Yiii" },
{ 0x0A4D0, 0x0A4FF, "Lisu" },
{ 0x0A500, 0x0A62B, "Vaii" },
{ 0x0A640, 0x0A69F, "Cyrl" },
{ 0x0A6A0, 0x0A6F7, "Bamu" },
{ 0x0A700, 0x0A721, "Zyyy" },
{ 0x0A722, 0x0A787, "Latn" },
{ 0x0A788, 0x0A78A, "Zyyy" },
{ 0x0A78B, 0x0A7DC, "Latn" },
{ 0x0A7F1, 0x0A7FF, "Latn" },
{ 0x0A800, 0x0A82C, "Sylo" },
{ 0x0A830, 0x0A839, "Zyyy" },
{ 0x0A840, 0x0A877, "Phag" },
{ 0x0A880, 0x0A8C5, "Saur" },
{ 0x0A8CE, 0x0A8D9, "Saur" },
{ 0x0A8E0, 0x0A8FF, "Deva" },
{ 0x0A900, 0x0A92D, "Kali" },
{ 0x0A930, 0x0A953, "Rjng" },
{ 0x0A960, 0x0A97C, "Hang" },
{ 0x0A980, 0x0A9CD, "Java" },
{ 0x0A9D0, 0x0A9D9, "Java" },
{ 0x0A9DE, 0x0A9DF, "Java" },
{ 0x0A9E0, 0x0A9FE, "Mymr" },
{ 0x0AA00, 0x0AA36, "Cham" },
{ 0x0AA40, 0x0AA4D, "Cham" },
{ 0x0AA50, 0x0AA59, "Cham" },
{ 0x0AA5C, 0x0AA5F, "Cham" },
{ 0x0AA60, 0x0AA7F, "Mymr" },
{ 0x0AA80, 0x0AAC2, "Tavt" },
{ 0x0AADB, 0x0AADF, "Tavt" },
{ 0x0AAE0, 0x0AAF6, "Mtei" },
{ 0x0AB01, 0x0AB06, "Ethi" },
{ 0x0AB09, 0x0AB0E, "Ethi" },
{ 0x0AB11, 0x0AB16, "Ethi" },
{ 0x0AB20, 0x0AB26, "Ethi" },
{ 0x0AB28, 0x0AB2E, "Ethi" },
{ 0x0AB30, 0x0AB5A, "Latn" },
{ 0x0AB5C, 0x0AB64, "Latn" },
{ 0x0AB66, 0x0AB69, "Latn" },
{ 0x0AB6A, 0x0AB6B, "Zyyy" },
{ 0x0AB70, 0x0ABBF, "Cher" },
{ 0x0ABC0, 0x0ABED, "Mtei" },
{ 0x0ABF0, 0x0ABF9, "Mtei" },
{ 0x0AC00, 0x0D7A3, "Hang" },
{ 0x0D7B0, 0x0D7C6, "Hang" },
{ 0x0D7CB, 0x0D7FB, "Hang" },
{ 0x0F900, 0x0FA6D, "Hani" },
{ 0x0FA70, 0x0FAD9, "Hani" },
{ 0x0FB00, 0x0FB06, "Latn" },
{ 0x0FB13, 0x0FB17, "Armn" },
{ 0x0FB1D, 0x0FB36, "Hebr" },
{ 0x0FB38, 0x0FB3C, "Hebr" },
{ 0x0FB40, 0x0FB41, "Hebr" },
{ 0x0FB43, 0x0FB44, "Hebr" },
{ 0x0FB46, 0x0FB4F, "Hebr" },
{ 0x0FB50, 0x0FD3D, "Arab" },
{ 0x0FD3E, 0x0FD3F, "Zyyy" },
{ 0x0FD40, 0x0FDCF, "Arab" },
{ 0x0FDF0, 0x0FDFF, "Arab" },
{ 0x0FE00, 0x0FE0F, "Zinh" },
{ 0x0FE10, 0x0FE19, "Zyyy" },
{ 0x0FE20, 0x0FE2D, "Zinh" },
{ 0x0FE2E, 0x0FE2F, "Cyrl" },
{ 0x0FE30, 0x0FE52, "Zyyy" },
{ 0x0FE54, 0x0FE66, "Zyyy" },
{ 0x0FE68, 0x0FE6B, "Zyyy" },
{ 0x0FE70, 0x0FE74, "Arab" },
{ 0x0FE76, 0x0FEFC, "Arab" },
{ 0x0FF01, 0x0FF20, "Zyyy" },
{ 0x0FF21, 0x0FF3A, "Latn" },
{ 0x0FF3B, 0x0FF40, "Zyyy" },
{ 0x0FF41, 0x0FF5A, "Latn" },
{ 0x0FF5B, 0x0FF65, "Zyyy" },
{ 0x0FF66, 0x0FF6F, "Kana" },
{ 0x0FF71, 0x0FF9D, "Kana" },
{ 0x0FF9E, 0x0FF9F, "Zyyy" },
{ 0x0FFA0, 0x0FFBE, "Hang" },
{ 0x0FFC2, 0x0FFC7, "Hang" },
{ 0x0FFCA, 0x0FFCF, "Hang" },
{ 0x0FFD2, 0x0FFD7, "Hang" },
{ 0x0FFDA, 0x0FFDC, "Hang" },
{ 0x0FFE0, 0x0FFE6, "Zyyy" },
{ 0x0FFE8, 0x0FFEE, "Zyyy" },
{ 0x0FFF9, 0x0FFFD, "Zyyy" },
{ 0x10000, 0x1000B, "Linb" },
{ 0x1000D, 0x10026, "Linb" },
{ 0x10028, 0x1003A, "Linb" },
{ 0x1003C, 0x1003D, "Linb" },
{ 0x1003F, 0x1004D, "Linb" },
{ 0x10050, 0x1005D, "Linb" },
{ 0x10080, 0x100FA, "Linb" },
{ 0x10100, 0x10102, "Zyyy" },
{ 0x10107, 0x10133, "Zyyy" },
{ 0x10137, 0x1013F, "Zyyy" },
{ 0x10140, 0x1018E, "Grek" },
{ 0x10190, 0x1019C, "Zyyy" },
{ 0x101D0, 0x101FC, "Zyyy" },
{ 0x10280, 0x1029C, "Lyci" },
{ 0x102A0, 0x102D0, "Cari" },
{ 0x102E1, 0x102FB, "Zyyy" },
{ 0x10300, 0x10323, "Ital" },
{ 0x1032D, 0x1032F, "Ital" },
{ 0x10330, 0x1034A, "Goth" },
{ 0x10350, 0x1037A, "Perm" },
{ 0x10380, 0x1039D, "Ugar" },
{ 0x103A0, 0x103C3, "Xpeo" },
{ 0x103C8, 0x103D5, "Xpeo" },
{ 0x10400, 0x1044F, "Dsrt" },
{ 0x10450, 0x1047F, "Shaw" },
{ 0x10480, 0x1049D, "Osma" },
{ 0x104A0, 0x104A9, "Osma" },
{ 0x104B0, 0x104D3, "Osge" },
{ 0x104D8, 0x104FB, "Osge" },
{ 0x10500, 0x10527, "Elba" },
{ 0x10530, 0x10563, "Aghb" },
{ 0x10570, 0x1057A, "Vith" },
{ 0x1057C, 0x1058A, "Vith" },
{ 0x1058C, 0x10592, "Vith" },
{ 0x10594, 0x10595, "Vith" },
{ 0x10597, 0x105A1, "Vith" },
{ 0x105A3, 0x105B1, "Vith" },
{ 0x105B3, 0x105B9, "Vith" },
{ 0x105BB, 0x105BC, "Vith" },
{ 0x105C0, 0x105F3, "Todr" },
{ 0x10600, 0x10736, "Lina" },
{ 0x10740, 0x10755, "Lina" },
{ 0x10760, 0x10767, "Lina" },
{ 0x10780, 0x10785, "Latn" },
{ 0x10787, 0x107B0, "Latn" },
{ 0x107B2, 0x107BA, "Latn" },
{ 0x10800, 0x10805, "Cprt" },
{ 0x1080A, 0x10835, "Cprt" },
{ 0x10837, 0x10838, "Cprt" },
{ 0x10840, 0x10855, "Armi" },
{ 0x10857, 0x1085F, "Armi" },
{ 0x10860, 0x1087F, "Palm" },
{ 0x10880, 0x1089E, "Nbat" },
{ 0x108A7, 0x108AF, "Nbat" },
{ 0x108E0, 0x108F2, "Hatr" },
{ 0x108F4, 0x108F5, "Hatr" },
{ 0x108FB, 0x108FF, "Hatr" },
{ 0x10900, 0x1091B, "Phnx" },
{ 0x10920, 0x10939, "Lydi" },
{ 0x10940, 0x10959, "Sidt" },
{ 0x10980, 0x1099F, "Mero" },
{ 0x109A0, 0x109B7, "Merc" },
{ 0x109BC, 0x109CF, "Merc" },
{ 0x109D2, 0x109FF, "Merc" },
{ 0x10A00, 0x10A03, "Khar" },
{ 0x10A05, 0x10A06, "Khar" },
{ 0x10A0C, 0x10A13, "Khar" },
{ 0x10A15, 0x10A17, "Khar" },
{ 0x10A19, 0x10A35, "Khar" },
{ 0x10A38, 0x10A3A, "Khar" },
{ 0x10A3F, 0x10A48, "Khar" },
{ 0x10A50, 0x10A58, "Khar" },
{ 0x10A60, 0x10A7F, "Sarb" },
{ 0x10A80, 0x10A9F, "Narb" },
{ 0x10AC0, 0x10AE6, "Mani" },
{ 0x10AEB, 0x10AF6, "Mani" },
{ 0x10B00, 0x10B35, "Avst" },
{ 0x10B39, 0x10B3F, "Avst" },
{ 0x10B40, 0x10B55, "Prti" },
{ 0x10B58, 0x10B5F, "Prti" },
{ 0x10B60, 0x10B72, "Phli" },
{ 0x10B78, 0x10B7F, "Phli" },
{ 0x10B80, 0x10B91, "Phlp" },
{ 0x10B99, 0x10B9C, "Phlp" },
{ 0x10BA9, 0x10BAF, "Phlp" },
{ 0x10C00, 0x10C48, "Orkh" },
{ 0x10C80, 0x10CB2, "Hung" },
{ 0x10CC0, 0x10CF2, "Hung" },
{ 0x10CFA, 0x10CFF, "Hung" },
{ 0x10D00, 0x10D27, "Rohg" },
{ 0x10D30, 0x10D39, "Rohg" },
{ 0x10D40, 0x10D65, "Gara" },
{ 0x10D69, 0x10D85, "Gara" },
{ 0x10D8E, 0x10D8F, "Gara" },
{ 0x10E60, 0x10E7E, "Arab" },
{ 0x10E80, 0x10EA9, "Yezi" },
{ 0x10EAB, 0x10EAD, "Yezi" },
{ 0x10EB0, 0x10EB1, "Yezi" },
{ 0x10EC2, 0x10EC7, "Arab" },
{ 0x10ED0, 0x10ED8, "Arab" },
{ 0x10EFA, 0x10EFF, "Arab" },
{ 0x10F00, 0x10F27, "Sogo" },
{ 0x10F30, 0x10F59, "Sogd" },
{ 0x10F70, 0x10F89, "Ougr" },
{ 0x10FB0, 0x10FCB, "Chrs" },
{ 0x10FE0, 0x10FF6, "Elym" },
{ 0x11000, 0x1104D, "Brah" },
{ 0x11052, 0x11075, "Brah" },
{ 0x11080, 0x110C2, "Kthi" },
{ 0x110D0, 0x110E8, "Sora" },
{ 0x110F0, 0x110F9, "Sora" },
{ 0x11100, 0x11134, "Cakm" },
{ 0x11136, 0x11147, "Cakm" },
{ 0x11150, 0x11176, "Mahj" },
{ 0x11180, 0x111DF, "Shrd" },
{ 0x111E1, 0x111F4, "Sinh" },
{ 0x11200, 0x11211, "Khoj" },
{ 0x11213, 0x11241, "Khoj" },
{ 0x11280, 0x11286, "Mult" },
{ 0x1128A, 0x1128D, "Mult" },
{ 0x1128F, 0x1129D, "Mult" },
{ 0x1129F, 0x112A9, "Mult" },
{ 0x112B0, 0x112EA, "Sind" },
{ 0x112F0, 0x112F9, "Sind" },
{ 0x11300, 0x11303, "Gran" },
{ 0x11305, 0x1130C, "Gran" },
{ 0x1130F, 0x11310, "Gran" },
{ 0x11313, 0x11328, "Gran" },
{ 0x1132A, 0x11330, "Gran" },
{ 0x11332, 0x11333, "Gran" },
{ 0x11335, 0x11339, "Gran" },
{ 0x1133C, 0x11344, "Gran" },
{ 0x11347, 0x11348, "Gran" },
{ 0x1134B, 0x1134D, "Gran" },
{ 0x1135D, 0x11363, "Gran" },
{ 0x11366, 0x1136C, "Gran" },
{ 0x11370, 0x11374, "Gran" },
{ 0x11380, 0x11389, "Tutg" },
{ 0x11390, 0x113B5, "Tutg" },
{ 0x113B7, 0x113C0, "Tutg" },
{ 0x113C7, 0x113CA, "Tutg" },
{ 0x113CC, 0x113D5, "Tutg" },
{ 0x113D7, 0x113D8, "Tutg" },
{ 0x113E1, 0x113E2, "Tutg" },
{ 0x11400, 0x1145B, "Newa" },
{ 0x1145D, 0x11461, "Newa" },
{ 0x11480, 0x114C7, "Tirh" },
{ 0x114D0, 0x114D9, "Tirh" },
{ 0x11580, 0x115B5, "Sidd" },
{ 0x115B8, 0x115DD, "Sidd" },
{ 0x11600, 0x11644, "Modi" },
{ 0x11650, 0x11659, "Modi" },
{ 0x11660, 0x1166C, "Mong" },
{ 0x11680, 0x116B9, "Takr" },
{ 0x116C0, 0x116C9, "Takr" },
{ 0x116D0, 0x116E3, "Mymr" },
{ 0x11700, 0x1171A, "Ahom" },
{ 0x1171D, 0x1172B, "Ahom" },
{ 0x11730, 0x11746, "Ahom" },
{ 0x11800, 0x1183B, "Dogr" },
{ 0x118A0, 0x118F2, "Wara" },
{ 0x11900, 0x11906, "Diak" },
{ 0x1190C, 0x11913, "Diak" },
{ 0x11915, 0x11916, "Diak" },
{ 0x11918, 0x11935, "Diak" },
{ 0x11937, 0x11938, "Diak" },
{ 0x1193B, 0x11946, "Diak" },
{ 0x11950, 0x11959, "Diak" },
{ 0x119A0, 0x119A7, "Nand" },
{ 0x119AA, 0x119D7, "Nand" },
{ 0x119DA, 0x119E4, "Nand" },
{ 0x11A00, 0x11A47, "Zanb" },
{ 0x11A50, 0x11AA2, "Soyo" },
{ 0x11AB0, 0x11ABF, "Cans" },
{ 0x11AC0, 0x11AF8, "Pauc" },
{ 0x11B00, 0x11B09, "Deva" },
{ 0x11B60, 0x11B67, "Shrd" },
{ 0x11BC0, 0x11BE1, "Sunu" },
{ 0x11BF0, 0x11BF9, "Sunu" },
{ 0x11C00, 0x11C08, "Bhks" },
{ 0x11C0A, 0x11C36, "Bhks" },
{ 0x11C38, 0x11C45, "Bhks" },
{ 0x11C50, 0x11C6C, "Bhks" },
{ 0x11C70, 0x11C8F, "Marc" },
{ 0x11C92, 0x11CA7, "Marc" },
{ 0x11CA9, 0x11CB6, "Marc" },
{ 0x11D00, 0x11D06, "Gonm" },
{ 0x11D08, 0x11D09, "Gonm" },
{ 0x11D0B, 0x11D36, "Gonm" },
{ 0x11D3C, 0x11D3D, "Gonm" },
{ 0x11D3F, 0x11D47, "Gonm" },
{ 0x11D50, 0x11D59, "Gonm" },
{ 0x11D60, 0x11D65, "Gong" },
{ 0x11D67, 0x11D68, "Gong" },
{ 0x11D6A, 0x11D8E, "Gong" },
{ 0x11D90, 0x11D91, "Gong" },
{ 0x11D93, 0x11D98, "Gong" },
{ 0x11DA0, 0x11DA9, "Gong" },
{ 0x11DB0, 0x11DDB, "Tols" },
{ 0x11DE0, 0x11DE9, "Tols" },
{ 0x11EE0, 0x11EF8, "Maka" },
{ 0x11F00, 0x11F10, "Kawi" },
{ 0x11F12, 0x11F3A, "Kawi" },
{ 0x11F3E, 0x11F5A, "Kawi" },
{ 0x11FC0, 0x11FF1, "Taml" },
{ 0x12000, 0x12399, "Xsux" },
{ 0x12400, 0x1246E, "Xsux" },
{ 0x12470, 0x12474, "Xsux" },
{ 0x12480, 0x12543, "Xsux" },
{ 0x12F90, 0x12FF2, "Cpmn" },
{ 0x13000, 0x13455, "Egyp" },
{ 0x13460, 0x143FA, "Egyp" },
{ 0x14400, 0x14646, "Hluw" },
{ 0x16100, 0x16139, "Gukh" },
{ 0x16800, 0x16A38, "Bamu" },
{ 0x16A40, 0x16A5E, "Mroo" },
{ 0x16A60, 0x16A69, "Mroo" },
{ 0x16A6E, 0x16A6F, "Mroo" },
{ 0x16A70, 0x16ABE, "Tnsa" },
{ 0x16AC0, 0x16AC9, "Tnsa" },
{ 0x16AD0, 0x16AED, "Bass" },
{ 0x16AF0, 0x16AF5, "Bass" },
{ 0x16B00, 0x16B45, "Hmng" },
{ 0x16B50, 0x16B59, "Hmng" },
{ 0x16B5B, 0x16B61, "Hmng" },
{ 0x16B63, 0x16B77, "Hmng" },
{ 0x16B7D, 0x16B8F, "Hmng" },
{ 0x16D40, 0x16D79, "Krai" },
{ 0x16E40, 0x16E9A, "Medf" },
{ 0x16EA0, 0x16EB8, "Berf" },
{ 0x16EBB, 0x16ED3, "Berf" },
{ 0x16F00, 0x16F4A, "Plrd" },
{ 0x16F4F, 0x16F87, "Plrd" },
{ 0x16F8F, 0x16F9F, "Plrd" },
{ 0x16FE2, 0x16FE3, "Hani" },
{ 0x16FF0, 0x16FF6, "Hani" },
{ 0x17000, 0x18AFF, "Tang" },
{ 0x18B00, 0x18CD5, "Kits" },
{ 0x18D00, 0x18D1E, "Tang" },
{ 0x18D80, 0x18DF2, "Tang" },
{ 0x1AFF0, 0x1AFF3, "Kana" },
{ 0x1AFF5, 0x1AFFB, "Kana" },
{ 0x1AFFD, 0x1AFFE, "Kana" },
{ 0x1B001, 0x1B11F, "Hira" },
{ 0x1B120, 0x1B122, "Kana" },
{ 0x1B150, 0x1B152, "Hira" },
{ 0x1B164, 0x1B167, "Kana" },
{ 0x1B170, 0x1B2FB, "Nshu" },
{ 0x1BC00, 0x1BC6A, "Dupl" },
{ 0x1BC70, 0x1BC7C, "Dupl" },
{ 0x1BC80, 0x1BC88, "Dupl" },
{ 0x1BC90, 0x1BC99, "Dupl" },
{ 0x1BC9C, 0x1BC9F, "Dupl" },
{ 0x1BCA0, 0x1BCA3, "Zyyy" },
{ 0x1CC00, 0x1CCFC, "Zyyy" },
{ 0x1CD00, 0x1CEB3, "Zyyy" },
{ 0x1CEBA, 0x1CED0, "Zyyy" },
{ 0x1CEE0, 0x1CEF0, "Zyyy" },
{ 0x1CF00, 0x1CF2D, "Zinh" },
{ 0x1CF30, 0x1CF46, "Zinh" },
{ 0x1CF50, 0x1CFC3, "Zyyy" },
{ 0x1D000, 0x1D0F5, "Zyyy" },
{ 0x1D100, 0x1D126, "Zyyy" },
{ 0x1D129, 0x1D166, "Zyyy" },
{ 0x1D167, 0x1D169, "Zinh" },
{ 0x1D16A, 0x1D17A, "Zyyy" },
{ 0x1D17B, 0x1D182, "Zinh" },
{ 0x1D183, 0x1D184, "Zyyy" },
{ 0x1D185, 0x1D18B, "Zinh" },
{ 0x1D18C, 0x1D1A9, "Zyyy" },
{ 0x1D1AA, 0x1D1AD, "Zinh" },
{ 0x1D1AE, 0x1D1EA, "Zyyy" },
{ 0x1D200, 0x1D245, "Grek" },
{ 0x1D2C0, 0x1D2D3, "Zyyy" },
{ 0x1D2E0, 0x1D2F3, "Zyyy" },
{ 0x1D300, 0x1D356, "Zyyy" },
{ 0x1D360, 0x1D378, "Zyyy" },
{ 0x1D400, 0x1D454, "Zyyy" },
{ 0x1D456, 0x1D49C, "Zyyy" },
{ 0x1D49E, 0x1D49F, "Zyyy" },
{ 0x1D4A5, 0x1D4A6, "Zyyy" },
{ 0x1D4A9, 0x1D4AC, "Zyyy" },
{ 0x1D4AE, 0x1D4B9, "Zyyy" },
{ 0x1D4BD, 0x1D4C3, "Zyyy" },
{ 0x1D4C5, 0x1D505, "Zyyy" },
{ 0x1D507, 0x1D50A, "Zyyy" },
{ 0x1D50D, 0x1D514, "Zyyy" },
{ 0x1D516, 0x1D51C, "Zyyy" },
{ 0x1D51E, 0x1D539, "Zyyy" },
{ 0x1D53B, 0x1D53E, "Zyyy" },
{ 0x1D540, 0x1D544, "Zyyy" },
{ 0x1D54A, 0x1D550, "Zyyy" },
{ 0x1D552, 0x1D6A5, "Zyyy" },
{ 0x1D6A8, 0x1D7CB, "Zyyy" },
{ 0x1D7CE, 0x1D7FF, "Zyyy" },
{ 0x1D800, 0x1DA8B, "Sgnw" },
{ 0x1DA9B, 0x1DA9F, "Sgnw" },
{ 0x1DAA1, 0x1DAAF, "Sgnw" },
{ 0x1DF00, 0x1DF1E, "Latn" },
{ 0x1DF25, 0x1DF2A, "Latn" },
{ 0x1E000, 0x1E006, "Glag" },
{ 0x1E008, 0x1E018, "Glag" },
{ 0x1E01B, 0x1E021, "Glag" },
{ 0x1E023, 0x1E024, "Glag" },
{ 0x1E026, 0x1E02A, "Glag" },
{ 0x1E030, 0x1E06D, "Cyrl" },
{ 0x1E100, 0x1E12C, "Hmnp" },
{ 0x1E130, 0x1E13D, "Hmnp" },
{ 0x1E140, 0x1E149, "Hmnp" },
{ 0x1E14E, 0x1E14F, "Hmnp" },
{ 0x1E290, 0x1E2AE, "Toto" },
{ 0x1E2C0, 0x1E2F9, "Wcho" },
{ 0x1E4D0, 0x1E4F9, "Nagm" },
{ 0x1E5D0, 0x1E5FA, "Onao" },
{ 0x1E6C0, 0x1E6DE, "Tayo" },
{ 0x1E6E0, 0x1E6F5, "Tayo" },
{ 0x1E6FE, 0x1E6FF, "Tayo" },
{ 0x1E7E0, 0x1E7E6, "Ethi" },
{ 0x1E7E8, 0x1E7EB, "Ethi" },
{ 0x1E7ED, 0x1E7EE, "Ethi" },
{ 0x1E7F0, 0x1E7FE, "Ethi" },
{ 0x1E800, 0x1E8C4, "Mend" },
{ 0x1E8C7, 0x1E8D6, "Mend" },
{ 0x1E900, 0x1E94B, "Adlm" },
{ 0x1E950, 0x1E959, "Adlm" },
{ 0x1E95E, 0x1E95F, "Adlm" },
{ 0x1EC71, 0x1ECB4, "Zyyy" },
{ 0x1ED01, 0x1ED3D, "Zyyy" },
{ 0x1EE00, 0x1EE03, "Arab" },
{ 0x1EE05, 0x1EE1F, "Arab" },
{ 0x1EE21, 0x1EE22, "Arab" },
{ 0x1EE29, 0x1EE32, "Arab" },
{ 0x1EE34, 0x1EE37, "Arab" },
{ 0x1EE4D, 0x1EE4F, "Arab" },
{ 0x1EE51, 0x1EE52, "Arab" },
{ 0x1EE61, 0x1EE62, "Arab" },
{ 0x1EE67, 0x1EE6A, "Arab" },
{ 0x1EE6C, 0x1EE72, "Arab" },
{ 0x1EE74, 0x1EE77, "Arab" },
{ 0x1EE79, 0x1EE7C, "Arab" },
{ 0x1EE80, 0x1EE89, "Arab" },
{ 0x1EE8B, 0x1EE9B, "Arab" },
{ 0x1EEA1, 0x1EEA3, "Arab" },
{ 0x1EEA5, 0x1EEA9, "Arab" },
{ 0x1EEAB, 0x1EEBB, "Arab" },
{ 0x1EEF0, 0x1EEF1, "Arab" },
{ 0x1F000, 0x1F02B, "Zyyy" },
{ 0x1F030, 0x1F093, "Zyyy" },
{ 0x1F0A0, 0x1F0AE, "Zyyy" },
{ 0x1F0B1, 0x1F0BF, "Zyyy" },
{ 0x1F0C1, 0x1F0CF, "Zyyy" },
{ 0x1F0D1, 0x1F0F5, "Zyyy" },
{ 0x1F100, 0x1F1AD, "Zyyy" },
{ 0x1F1E6, 0x1F1FF, "Zyyy" },
{ 0x1F201, 0x1F202, "Zyyy" },
{ 0x1F210, 0x1F23B, "Zyyy" },
{ 0x1F240, 0x1F248, "Zyyy" },
{ 0x1F250, 0x1F251, "Zyyy" },
{ 0x1F260, 0x1F265, "Zyyy" },
{ 0x1F300, 0x1F6D8, "Zyyy" },
{ 0x1F6DC, 0x1F6EC, "Zyyy" },
{ 0x1F6F0, 0x1F6FC, "Zyyy" },
{ 0x1F700, 0x1F7D9, "Zyyy" },
{ 0x1F7E0, 0x1F7EB, "Zyyy" },
{ 0x1F800, 0x1F80B, "Zyyy" },
{ 0x1F810, 0x1F847, "Zyyy" },
{ 0x1F850, 0x1F859, "Zyyy" },
{ 0x1F860, 0x1F887, "Zyyy" },
{ 0x1F890, 0x1F8AD, "Zyyy" },
{ 0x1F8B0, 0x1F8BB, "Zyyy" },
{ 0x1F8C0, 0x1F8C1, "Zyyy" },
{ 0x1F8D0, 0x1F8D8, "Zyyy" },
{ 0x1F900, 0x1FA57, "Zyyy" },
{ 0x1FA60, 0x1FA6D, "Zyyy" },
{ 0x1FA70, 0x1FA7C, "Zyyy" },
{ 0x1FA80, 0x1FA8A, "Zyyy" },
{ 0x1FA8E, 0x1FAC6, "Zyyy" },
{ 0x1FACD, 0x1FADC, "Zyyy" },
{ 0x1FADF, 0x1FAEA, "Zyyy" },
{ 0x1FAEF, 0x1FAF8, "Zyyy" },
{ 0x1FB00, 0x1FB92, "Zyyy" },
{ 0x1FB94, 0x1FBFA, "Zyyy" },
{ 0x20000, 0x2A6DF, "Hani" },
{ 0x2A700, 0x2B81D, "Hani" },
{ 0x2B820, 0x2CEAD, "Hani" },
{ 0x2CEB0, 0x2EBE0, "Hani" },
{ 0x2EBF0, 0x2EE5D, "Hani" },
{ 0x2F800, 0x2FA1D, "Hani" },
{ 0x30000, 0x3134A, "Hani" },
{ 0x31350, 0x33479, "Hani" },
{ 0xE0020, 0xE007F, "Zyyy" },
{ 0xE0100, 0xE01EF, "Zinh" },
},
-- Scripts.txt gives full names; here we consider them aliases to save space.
aliases = {
Adlm = "Adlam",
Aghb = "Caucasian Albanian",
Ahom = "Ahom",
Arab = "Arabic",
Armi = "Imperial Aramaic",
Armn = "Armenian",
Avst = "Avestan",
Bali = "Balinese",
Bamu = "Bamum",
Bass = "Bassa Vah",
Batk = "Batak",
Beng = "Bengali",
Berf = "Beria Erfe",
Bhks = "Bhaiksuki",
Bopo = "Bopomofo",
Brah = "Brahmi",
Brai = "Braille",
Bugi = "Buginese",
Buhd = "Buhid",
Cakm = "Chakma",
Cans = "Canadian Aboriginal",
Cari = "Carian",
Cham = "Cham",
Cher = "Cherokee",
Chrs = "Chorasmian",
Copt = "Coptic",
Cpmn = "Cypro Minoan",
Cprt = "Cypriot",
Cyrl = "Cyrillic",
Deva = "Devanagari",
Diak = "Dives Akuru",
Dogr = "Dogra",
Dsrt = "Deseret",
Dupl = "Duployan",
Egyp = "Egyptian Hieroglyphs",
Elba = "Elbasan",
Elym = "Elymaic",
Ethi = "Ethiopic",
Gara = "Garay",
Geor = "Georgian",
Glag = "Glagolitic",
Gong = "Gunjala Gondi",
Gonm = "Masaram Gondi",
Goth = "Gothic",
Gran = "Grantha",
Grek = "Greek",
Gujr = "Gujarati",
Gukh = "Gurung Khema",
Guru = "Gurmukhi",
Hang = "Hangul",
Hani = "Han",
Hano = "Hanunoo",
Hatr = "Hatran",
Hebr = "Hebrew",
Hira = "Hiragana",
Hluw = "Anatolian Hieroglyphs",
Hmng = "Pahawh Hmong",
Hmnp = "Nyiakeng Puachue Hmong",
Hrkt = "Katakana Or Hiragana",
Hung = "Old Hungarian",
Ital = "Old Italic",
Java = "Javanese",
Kali = "Kayah Li",
Kana = "Katakana",
Kawi = "Kawi",
Khar = "Kharoshthi",
Khmr = "Khmer",
Khoj = "Khojki",
Kits = "Khitan Small Script",
Knda = "Kannada",
Krai = "Kirat Rai",
Kthi = "Kaithi",
Lana = "Tai Tham",
Laoo = "Lao",
Latn = "Latin",
Lepc = "Lepcha",
Limb = "Limbu",
Lina = "Linear A",
Linb = "Linear B",
Lisu = "Lisu",
Lyci = "Lycian",
Lydi = "Lydian",
Mahj = "Mahajani",
Maka = "Makasar",
Mand = "Mandaic",
Mani = "Manichaean",
Marc = "Marchen",
Medf = "Medefaidrin",
Mend = "Mende Kikakui",
Merc = "Meroitic Cursive",
Mero = "Meroitic Hieroglyphs",
Mlym = "Malayalam",
Modi = "Modi",
Mong = "Mongolian",
Mroo = "Mro",
Mtei = "Meetei Mayek",
Mult = "Multani",
Mymr = "Myanmar",
Nagm = "Nag Mundari",
Nand = "Nandinagari",
Narb = "Old North Arabian",
Nbat = "Nabataean",
Newa = "Newa",
Nkoo = "NKo",
Nshu = "Nushu",
Ogam = "Ogham",
Olck = "Ol Chiki",
Onao = "Ol Onal",
Orkh = "Old Turkic",
Orya = "Oriya",
Osge = "Osage",
Osma = "Osmanya",
Ougr = "Old Uyghur",
Palm = "Palmyrene",
Pauc = "Pau Cin Hau",
Perm = "Old Permic",
Phag = "Phags Pa",
Phli = "Inscriptional Pahlavi",
Phlp = "Psalter Pahlavi",
Phnx = "Phoenician",
Plrd = "Miao",
Prti = "Inscriptional Parthian",
Rjng = "Rejang",
Rohg = "Hanifi Rohingya",
Runr = "Runic",
Samr = "Samaritan",
Sarb = "Old South Arabian",
Saur = "Saurashtra",
Sgnw = "SignWriting",
Shaw = "Shavian",
Shrd = "Sharada",
Sidd = "Siddham",
Sidt = "Sidetic",
Sind = "Khudawadi",
Sinh = "Sinhala",
Sogd = "Sogdian",
Sogo = "Old Sogdian",
Sora = "Sora Sompeng",
Soyo = "Soyombo",
Sund = "Sundanese",
Sunu = "Sunuwar",
Sylo = "Syloti Nagri",
Syrc = "Syriac",
Tagb = "Tagbanwa",
Takr = "Takri",
Tale = "Tai Le",
Talu = "New Tai Lue",
Taml = "Tamil",
Tang = "Tangut",
Tavt = "Tai Viet",
Tayo = "Tai Yo",
Telu = "Telugu",
Tfng = "Tifinagh",
Tglg = "Tagalog",
Thaa = "Thaana",
Thai = "Thai",
Tibt = "Tibetan",
Tirh = "Tirhuta",
Tnsa = "Tangsa",
Todr = "Todhri",
Tols = "Tolong Siki",
Toto = "Toto",
Tutg = "Tulu Tigalari",
Ugar = "Ugaritic",
Vaii = "Vai",
Vith = "Vithkuqi",
Wara = "Warang Citi",
Wcho = "Wancho",
Xpeo = "Old Persian",
Xsux = "Cuneiform",
Yezi = "Yezidi",
Yiii = "Yi",
Zanb = "Zanabazar Square",
Zinh = "Inherited",
Zyyy = "Common",
Zzzz = "Unknown",
},
}
-- Required for binary search function in [[Module:Language/scripts]].
-- Cannot get length of module loaded with mw.loadData.
data.ranges.length = #data.ranges
data.rtl = {}
for _, script in ipairs(mw.loadData "Module:Lang/data".rtl_scripts) do
-- [[Module:Lang/data]] has script codes in lowercase;
-- this module has script codes with the first letter capitalized.
data.rtl[script:gsub("^%a", string.upper)] = true
end
return data
80pl7gb2np5bla0ghczssae2pylkrhq
Module:Exponential search
828
55811
392705
2026-09-02T01:00:17Z
MacTire02
219
Duillag crooit lesh: -- This module provides a generic exponential search algorithm. require[[strict]] local checkType = require('libraryUtil').checkType local floor = math.floor local function midPoint(lower, upper) return floor(lower + (upper - lower) / 2) end local function search(testFunc, i, lower, upper) if testFunc(i) then if i + 1 == upper then return i end lower = i if upper then i = midPoint(lower, upper) else i = i * 2 end return search(testFunc, i, lo...
392705
Scribunto
text/plain
-- This module provides a generic exponential search algorithm.
require[[strict]]
local checkType = require('libraryUtil').checkType
local floor = math.floor
local function midPoint(lower, upper)
return floor(lower + (upper - lower) / 2)
end
local function search(testFunc, i, lower, upper)
if testFunc(i) then
if i + 1 == upper then
return i
end
lower = i
if upper then
i = midPoint(lower, upper)
else
i = i * 2
end
return search(testFunc, i, lower, upper)
else
upper = i
i = midPoint(lower, upper)
return search(testFunc, i, lower, upper)
end
end
return function (testFunc, init)
checkType('Exponential search', 1, testFunc, 'function')
checkType('Exponential search', 2, init, 'number', true)
if init and (init < 1 or init ~= floor(init) or init == math.huge) then
error(string.format(
"invalid init value '%s' detected in argument #2 to " ..
"'Exponential search' (init value must be a positive integer)",
tostring(init)
), 2)
end
init = init or 2
if not testFunc(1) then
return nil
end
return search(testFunc, init, 1, nil)
end
jqqi8l27tb73lglksbukg2g3bzt3fmv
Module:Lang/configuration
828
55812
392720
2026-09-02T02:33:50Z
MacTire02
219
Duillag crooit lesh: --[[--------------------------< T E M P L A T E S _ T >-------------------------------------------------------- ]] local templates_t = { lang = 'Lang', langx = 'Langx', langxx = 'Lang-xx', transliteration = 'Transliteration', } --[[--------------------------< K N O W N _ P A R A M S >------------------------------------------------------ lists of all parameters known to {{lang}}, {{langx}}, {{lang-xx}} templates. Exception: |fn= is known to {{lang}} but is not...
392720
Scribunto
text/plain
--[[--------------------------< T E M P L A T E S _ T >--------------------------------------------------------
]]
local templates_t = {
lang = 'Lang',
langx = 'Langx',
langxx = 'Lang-xx',
transliteration = 'Transliteration',
}
--[[--------------------------< K N O W N _ P A R A M S >------------------------------------------------------
lists of all parameters known to {{lang}}, {{langx}}, {{lang-xx}} templates.
Exception: |fn= is known to {{lang}} but is not a 'lang' template; that parameter causes the module to call the
specified lang(), lang_xx_inherit(), or lang_xx_italic() function. These separate functions set |fn= to nill
and then do the known-param checking on the other template parameters
]]
local known_params_t = {
['common_params_all_t'] = { -- these parameters common to {{lang}}, {{langx}}, and {{lang-xx}}
['code'] = true,
['text'] = true,
['rtl'] = true,
['italic'] = true,
['italics'] = true,
['i'] = true,
['size'] = true,
['proto'] = true,
['nocat'] = true,
['cat'] = true,
['template'] = true, -- supplied by external templates to provide template name for error messaging ({{nihongo}}, etc)
},
['params_lang_t'] = { -- unique to {{lang}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
},
['params_x_t'] = { -- common to {{langx}} and {{lang-xx}}
['translit'] = true,
['translit-std'] = true,
['translit-script'] = true,
['translation'] = true,
['lit='] = true,
['label'] = true,
['link'] = true,
['links'] = true,
['lit'] = true,
['engvar'] = true,
},
['params_langx_t'] = { -- unique to {{langx}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
[3] = true, -- alias of |translit=
[4] = true, -- alias of |translation=
},
['params_lang_xx_t'] = { -- unique to {{lang-xx}}
[1] = true, -- alias of |text=
[2] = true, -- alias of |translit=
[3] = true, -- alias of |translation=
['script'] = true, -- these needed to override default params in {{lang-??}} templates
['region'] = true,
['variant'] = true,
},
}
--[[--------------------------< E N G _ V A R >----------------------------------------------------------------
Used at en.wiki so that spelling of 'romanized' (US, default) can be changed to 'romanised' to match the envar
specified by a {{Use xxx English}}. Not likely useful outside of en.wiki
This is accomplished by setting |engvar=gb; can, should be omitted in articles that use American English; no
need for the clutter.
]]
local engvar_sel_t = { -- select either UK English or US English
['au'] = 'gb_t', -- these match IANA region codes (except in lower case)
['ca'] = 'us_t',
['gb'] = 'gb_t',
['ie'] = 'gb_t',
['in'] = 'gb_t',
['nz'] = 'gb_t',
['us'] = 'us_t', -- default engvar
['za'] = 'gb_t'
};
local engvar_t = {
['gb_t'] = {
['romanisz_lc'] = 'romanisation', -- lower case
['romanisz_uc'] = 'Romanisation', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanised', -- past tense
},
['us_t'] = { -- default engvar
['romanisz_lc'] = 'romanization', -- lower case
['romanisz_uc'] = 'Romanization', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanized', -- past tense
}
}
local default_engvar = 'us_t';
--[[
=============================<< M E S S A G I N G T A B L E S >>=============================================
these tables are for internationalization. Messages or fragments thereof are mostly grouped by function name.
Some messages are shared by functions other than the function table that lists the message or fragment.
]]
--[[--------------------------< K E Y W O R D S _ T >----------------------------------------------------------
]]
local keywords_t = {
['affirmative'] = 'yes',
['negative'] = 'no',
['unset'] = 'unset',
['invert'] = 'invert',
['default'] = 'default',
}
--[[--------------------------< M I S C _ T E X T _ T >--------------------------------------------------------
]]
local misc_text_t = {
['error'] = 'Error', -- make_error_msg(), tag_from_name()
['language'] = 'language', -- make_translit(), lang_xx(), name_from_tag()
['help'] = 'help',
}
--[[--------------------------< M A K E _ E R R O R _ M S G _ T >----------------------------------------------
]]
local make_error_msg_t = {
['xlit_err_cat'] = 'Transliteration template errors',
['lang_err_cat'] = 'Lang and lang-xx template errors',
['undefined'] = 'undefined',
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local parameter_validate_t = {
['invalid_param'] = 'invalid parameter: |$1=', -- $1 is parameter name
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local validate_italic_t = {
['multi_italic'] = 'only one of |italic=, |italics=, or |i= can be specified',
}
--[[--------------------------< V A L I D A T E _ T E X T _ T >------------------------------------------------
]]
local validate_text_t = {
['no_text'] = 'no text',
['malformed_markup'] = 'text has malformed markup',
['italic_markup'] = 'text has italic markup',
}
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T _ T >------------------------------
]]
local text_script_match_test_t = {
['latn_txt_mismatch'] = 'Latn text/non-Latn script subtag mismatch',
['latn_scr_mismatch'] = 'Non-latn text (pos $1: $2)/Latn script subtag mismatch', -- $1 identifies offending character's position; $2 is the character
}
--[[--------------------------< L A N G _ T >------------------------------------------------------------------
]]
local lang_t = {
['conflict_n_param'] = 'conflicting: {{{$1}}} and |$2=', -- $1 is positional param number, $2 is named param; shared with _lang_xx()
['conflict_n_param_types'] = {
['code'] = 'code',
['text'] = 'text',
['translit'] = 'translit',
},
['invalid_proto'] = 'invalid |proto=: $1', -- _lang_xx also emits this message
}
--[[--------------------------< L A N G _ X X _ T >------------------------------------------------------------
]]
local lang_xx_t = {
['conflict_n_lit'] = 'conflicting: {{{$1}}} and |lit= or |translation=', -- $1 is positional parameter; can be either 3 ({{lang-??}}) or 4 ({{langx}})
['conflict_lit'] = 'conflicting: |lit= and |translation=',
['conflict_link'] = 'conflicting: |links= and |link=',
['invalid_xlit_std'] = 'invalid translit-std',
['romanization'] = 'Romanization of',
['translit_nonlatn'] = 'transliteration text not Latin script (pos $1: $2)', -- _xlit() also emits this message; $1 identifies offending character's position; $2 is the character
['xlit_of_latn'] = 'transliteration of latn script',
}
--[[--------------------------< T A G _ F R O M _ N A M E _ T >------------------------------------------------
]]
local tag_from_name_t = {
['lang_not_found'] = 'language: $1 not found', -- $1 is language name parameter value
['missing_lang_name'] = 'missing language name',
}
--[[--------------------------< T R A N S L _ T >--------------------------------------------------------------
]]
local transl_t = {
['unrecog_xlit_std'] = 'unrecognized transliteration standard: $1', -- $1 is |translit_std- parameter value
['no_text'] = 'no text',
['missing_lang_scr'] = 'missing language / script code',
['unrecog_lang_scr'] = 'unrecognized language / script code: $1', -- $1 is the language/script code
}
--[[--------------------------< G E T _ I E T F _ P A R T S _ T >----------------------------------------------
]]
local get_ietf_parts_t = {
['maint_promo_cat'] = 'Lang and lang-xx code promoted to ISO 639-1|$1', -- $1 is ISO 639-2/3 subtag
['maint_promo_msg'] = 'code: $1 promoted to code: $2', -- $1 is ISO 639-2/3 subtag, $2 is synonymous ISO 639-1 subtag
['missing_lang_tag'] = 'missing language tag', -- also used in _langx()
['redundant_scr'] = 'redundant script tag',
['redundant_reg'] = 'redundant region tag',
['redundant_var'] = 'redundant variant tag',
['unrecog_tag'] = 'unrecognized language tag: $1', -- $1 is the whole language tag
['unrecog_code'] = 'unrecognized language code: $1', -- $1 is code
['unrecog_reg_code'] = 'unrecognized region: $1 for code: $2', -- $1 is region, $2 is code
['unrecog_scr_code'] = 'unrecognized script: $1 for code: $2', -- $1 is script, $2 is code
['script_code'] = 'script: $1 not supported for code: $2', -- $1 is script, $2 is code
['unrecog_var'] = 'unrecognized variant: $1', -- $1 is variant
['unrecog_var_code'] = 'unrecognized variant: $1 for code: $2', -- $1 is variant, $2 is code
['unrecog_var_code_scr'] = 'unrecognized variant: $1 for code-script pair: $2-$3', -- $1 is variant, $2 is code, $3 is script
['unrecog_var_code_reg'] = 'unrecognized variant: $1 for code-region pair: $2-$3', -- $1 is variant, $2 is code, $3 is region
['unrecog_pri'] = 'unrecognized private tag: $1', -- $1 is private tag
}
--[[--------------------------< L A N G U A G E _ N A M E _ G E T _ T >----------------------------------------
]]
local language_name_get_t = {
['deprecated_cat'] = 'Lang and langx using deprecated ISO 639 codes|$1', -- $1 is deprecated ISO 639 subtag
['deprecated_msg'] = 'code: $1 is deprecated', -- $1 is deprecated ISO 639 subtag
}
--[[--------------------------< H T M L _ T I T L E _ T E X T _ T >--------------------------------------------
]]
local make_text_html_t = {
['zxx'] = 'text', -- for zxx no linguistic content
['collective'] = 'collective text', -- for collective languages
['individual'] = 'language text', -- for individual languages
}
--[[--------------------------< T R A N S L A T I O N _ M A K E _ T >------------------------------------------
]]
local translation_make_t = {
['lit_xlation'] = 'Literal translation', -- article title fragment and HTML title attribute
['lit_abbr'] = 'lit.',
}
--[[--------------------------< M A K E _ C A T E G O R Y _ T >------------------------------------------------
]]
local make_category_t = {
['collective_cat'] = 'Category:Articles with text in', -- for collective languages
['cat_prefix'] = 'Category:Articles containing', -- prefix for explicitly cited and individual languages
['explicit_cat'] = 'explicitly cited', -- for explicitly citing this wiki's language
['cat_postfix'] = 'language text', -- postfix for individual languages
}
--[[--------------------------< M A K E _ T R A N S L I T _ T >------------------------------------------------
]]
local make_translit_t = {
['script'] = 'script',
['transliteration'] = 'transliteration',
}
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
known_params_t = known_params_t,
templates_t = templates_t,
default_engvar = default_engvar, -- engvar support not likely useful outside of en.wiki
engvar_t = engvar_t,
engvar_sel_t = engvar_sel_t,
get_ietf_parts_t = get_ietf_parts_t, -- messaging tables
keywords_t = keywords_t,
lang_t = lang_t,
lang_xx_t = lang_xx_t,
language_name_get_t = language_name_get_t,
make_category_t = make_category_t,
make_error_msg_t = make_error_msg_t,
make_text_html_t = make_text_html_t,
make_translit_t = make_translit_t,
misc_text_t = misc_text_t,
parameter_validate_t = parameter_validate_t,
tag_from_name_t = tag_from_name_t,
text_script_match_test_t = text_script_match_test_t,
transl_t = transl_t,
translation_make_t = translation_make_t,
validate_italic_t = validate_italic_t,
validate_text_t = validate_text_t,
}
0grapkhfltfc8vltv99ir6fmysp0gia
392726
392720
2026-09-02T02:56:05Z
MacTire02
219
++
392726
Scribunto
text/plain
--[[--------------------------< T E M P L A T E S _ T >--------------------------------------------------------
]]
local templates_t = {
lang = 'Lang',
langx = 'Langx',
langxx = 'Lang-xx',
transliteration = 'Transliteration',
}
--[[--------------------------< K N O W N _ P A R A M S >------------------------------------------------------
lists of all parameters known to {{lang}}, {{langx}}, {{lang-xx}} templates.
Exception: |fn= is known to {{lang}} but is not a 'lang' template; that parameter causes the module to call the
specified lang(), lang_xx_inherit(), or lang_xx_italic() function. These separate functions set |fn= to nill
and then do the known-param checking on the other template parameters
]]
local known_params_t = {
['common_params_all_t'] = { -- these parameters common to {{lang}}, {{langx}}, and {{lang-xx}}
['code'] = true,
['text'] = true,
['rtl'] = true,
['italic'] = true,
['italics'] = true,
['i'] = true,
['size'] = true,
['proto'] = true,
['nocat'] = true,
['cat'] = true,
['template'] = true, -- supplied by external templates to provide template name for error messaging ({{nihongo}}, etc)
},
['params_lang_t'] = { -- unique to {{lang}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
},
['params_x_t'] = { -- common to {{langx}} and {{lang-xx}}
['translit'] = true,
['translit-std'] = true,
['translit-script'] = true,
['translation'] = true,
['lit='] = true,
['label'] = true,
['link'] = true,
['links'] = true,
['lit'] = true,
['engvar'] = true,
},
['params_langx_t'] = { -- unique to {{langx}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
[3] = true, -- alias of |translit=
[4] = true, -- alias of |translation=
},
['params_lang_xx_t'] = { -- unique to {{lang-xx}}
[1] = true, -- alias of |text=
[2] = true, -- alias of |translit=
[3] = true, -- alias of |translation=
['script'] = true, -- these needed to override default params in {{lang-??}} templates
['region'] = true,
['variant'] = true,
},
}
--[[--------------------------< E N G _ V A R >----------------------------------------------------------------
Used at en.wiki so that spelling of 'romanized' (US, default) can be changed to 'romanised' to match the envar
specified by a {{Use xxx English}}. Not likely useful outside of en.wiki
This is accomplished by setting |engvar=gb; can, should be omitted in articles that use American English; no
need for the clutter.
]]
local engvar_sel_t = { -- select either UK English or US English
['au'] = 'gb_t', -- these match IANA region codes (except in lower case)
['ca'] = 'us_t',
['gb'] = 'gb_t',
['ie'] = 'gb_t',
['in'] = 'gb_t',
['nz'] = 'gb_t',
['us'] = 'us_t', -- default engvar
['za'] = 'gb_t'
};
local engvar_t = {
['gb_t'] = {
['romanisz_lc'] = 'romanisation', -- lower case
['romanisz_uc'] = 'Romanisation', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanised', -- past tense
},
['us_t'] = { -- default engvar
['romanisz_lc'] = 'romanization', -- lower case
['romanisz_uc'] = 'Romanization', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanized', -- past tense
}
}
local default_engvar = 'us_t';
--[[
=============================<< M E S S A G I N G T A B L E S >>=============================================
these tables are for internationalization. Messages or fragments thereof are mostly grouped by function name.
Some messages are shared by functions other than the function table that lists the message or fragment.
]]
--[[--------------------------< K E Y W O R D S _ T >----------------------------------------------------------
]]
local keywords_t = {
['affirmative'] = 'yes',
['negative'] = 'no',
['unset'] = 'unset',
['invert'] = 'invert',
['default'] = 'default',
}
--[[--------------------------< M I S C _ T E X T _ T >--------------------------------------------------------
]]
local misc_text_t = {
['error'] = 'Error', -- make_error_msg(), tag_from_name()
['language'] = 'language', -- make_translit(), lang_xx(), name_from_tag()
['help'] = 'help',
}
--[[--------------------------< M A K E _ E R R O R _ M S G _ T >----------------------------------------------
]]
local make_error_msg_t = {
['xlit_err_cat'] = 'Transliteration template errors',
['lang_err_cat'] = 'Lang and lang-xx template errors',
['undefined'] = 'undefined',
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local parameter_validate_t = {
['invalid_param'] = 'invalid parameter: |$1=', -- $1 is parameter name
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local validate_italic_t = {
['multi_italic'] = 'only one of |italic=, |italics=, or |i= can be specified',
}
--[[--------------------------< V A L I D A T E _ T E X T _ T >------------------------------------------------
]]
local validate_text_t = {
['no_text'] = 'no text',
['malformed_markup'] = 'text has malformed markup',
['italic_markup'] = 'text has italic markup',
}
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T _ T >------------------------------
]]
local text_script_match_test_t = {
['latn_txt_mismatch'] = 'Latn text/non-Latn script subtag mismatch',
['latn_scr_mismatch'] = 'Non-latn text (pos $1: $2)/Latn script subtag mismatch', -- $1 identifies offending character's position; $2 is the character
}
--[[--------------------------< L A N G _ T >------------------------------------------------------------------
]]
local lang_t = {
['conflict_n_param'] = 'conflicting: {{{$1}}} and |$2=', -- $1 is positional param number, $2 is named param; shared with _lang_xx()
['conflict_n_param_types'] = {
['code'] = 'code',
['text'] = 'text',
['translit'] = 'translit',
},
['invalid_proto'] = 'invalid |proto=: $1', -- _lang_xx also emits this message
}
--[[--------------------------< L A N G _ X X _ T >------------------------------------------------------------
]]
local lang_xx_t = {
['conflict_n_lit'] = 'conflicting: {{{$1}}} and |lit= or |translation=', -- $1 is positional parameter; can be either 3 ({{lang-??}}) or 4 ({{langx}})
['conflict_lit'] = 'conflicting: |lit= and |translation=',
['conflict_link'] = 'conflicting: |links= and |link=',
['invalid_xlit_std'] = 'invalid translit-std',
['romanization'] = 'Romanization of',
['translit_nonlatn'] = 'transliteration text not Latin script (pos $1: $2)', -- _xlit() also emits this message; $1 identifies offending character's position; $2 is the character
['xlit_of_latn'] = 'transliteration of latn script',
}
--[[--------------------------< T A G _ F R O M _ N A M E _ T >------------------------------------------------
]]
local tag_from_name_t = {
['lang_not_found'] = 'language: $1 not found', -- $1 is language name parameter value
['missing_lang_name'] = 'missing language name',
}
--[[--------------------------< T R A N S L _ T >--------------------------------------------------------------
]]
local transl_t = {
['unrecog_xlit_std'] = 'unrecognized transliteration standard: $1', -- $1 is |translit_std- parameter value
['no_text'] = 'no text',
['missing_lang_scr'] = 'missing language / script code',
['unrecog_lang_scr'] = 'unrecognized language / script code: $1', -- $1 is the language/script code
}
--[[--------------------------< G E T _ I E T F _ P A R T S _ T >----------------------------------------------
]]
local get_ietf_parts_t = {
['maint_promo_cat'] = 'Lang and lang-xx code promoted to ISO 639-1|$1', -- $1 is ISO 639-2/3 subtag
['maint_promo_msg'] = 'code: $1 promoted to code: $2', -- $1 is ISO 639-2/3 subtag, $2 is synonymous ISO 639-1 subtag
['missing_lang_tag'] = 'missing language tag', -- also used in _langx()
['redundant_scr'] = 'redundant script tag',
['redundant_reg'] = 'redundant region tag',
['redundant_var'] = 'redundant variant tag',
['unrecog_tag'] = 'unrecognized language tag: $1', -- $1 is the whole language tag
['unrecog_code'] = 'unrecognized language code: $1', -- $1 is code
['unrecog_reg_code'] = 'unrecognized region: $1 for code: $2', -- $1 is region, $2 is code
['unrecog_scr_code'] = 'unrecognized script: $1 for code: $2', -- $1 is script, $2 is code
['script_code'] = 'script: $1 not supported for code: $2', -- $1 is script, $2 is code
['unrecog_var'] = 'unrecognized variant: $1', -- $1 is variant
['unrecog_var_code'] = 'unrecognized variant: $1 for code: $2', -- $1 is variant, $2 is code
['unrecog_var_code_scr'] = 'unrecognized variant: $1 for code-script pair: $2-$3', -- $1 is variant, $2 is code, $3 is script
['unrecog_var_code_reg'] = 'unrecognized variant: $1 for code-region pair: $2-$3', -- $1 is variant, $2 is code, $3 is region
['unrecog_pri'] = 'unrecognized private tag: $1', -- $1 is private tag
}
--[[--------------------------< L A N G U A G E _ N A M E _ G E T _ T >----------------------------------------
]]
local language_name_get_t = {
['deprecated_cat'] = 'Lang and langx using deprecated ISO 639 codes|$1', -- $1 is deprecated ISO 639 subtag
['deprecated_msg'] = 'code: $1 is deprecated', -- $1 is deprecated ISO 639 subtag
}
--[[--------------------------< H T M L _ T I T L E _ T E X T _ T >--------------------------------------------
]]
local make_text_html_t = {
['zxx'] = 'text', -- for zxx no linguistic content
['collective'] = 'collective text', -- for collective languages
['individual'] = 'language text', -- for individual languages
}
--[[--------------------------< T R A N S L A T I O N _ M A K E _ T >------------------------------------------
]]
local translation_make_t = {
['lit_xlation'] = 'Literal translation', -- article title fragment and HTML title attribute
['lit_abbr'] = 'lit.',
}
--[[--------------------------< M A K E _ C A T E G O R Y _ T >------------------------------------------------
]]
local make_category_t = {
['collective_cat'] = 'Ronney:Artyn goaill stiagh teks ayns', -- for collective languages
['cat_prefix'] = 'Ronney:Artyn goaill stiagh', -- prefix for explicitly cited and individual languages
['explicit_cat'] = 'symnit dy jarroo', -- for explicitly citing this wiki's language
['cat_postfix'] = 'teks', -- postfix for individual languages
}
--[[--------------------------< M A K E _ T R A N S L I T _ T >------------------------------------------------
]]
local make_translit_t = {
['script'] = 'script',
['transliteration'] = 'transliteration',
}
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
known_params_t = known_params_t,
templates_t = templates_t,
default_engvar = default_engvar, -- engvar support not likely useful outside of en.wiki
engvar_t = engvar_t,
engvar_sel_t = engvar_sel_t,
get_ietf_parts_t = get_ietf_parts_t, -- messaging tables
keywords_t = keywords_t,
lang_t = lang_t,
lang_xx_t = lang_xx_t,
language_name_get_t = language_name_get_t,
make_category_t = make_category_t,
make_error_msg_t = make_error_msg_t,
make_text_html_t = make_text_html_t,
make_translit_t = make_translit_t,
misc_text_t = misc_text_t,
parameter_validate_t = parameter_validate_t,
tag_from_name_t = tag_from_name_t,
text_script_match_test_t = text_script_match_test_t,
transl_t = transl_t,
translation_make_t = translation_make_t,
validate_italic_t = validate_italic_t,
validate_text_t = validate_text_t,
}
dr8xvoz8i5kszwsmxncpnsjmt1yt38t
392727
392726
2026-09-02T03:00:37Z
MacTire02
219
++
392727
Scribunto
text/plain
--[[--------------------------< T E M P L A T E S _ T >--------------------------------------------------------
]]
local templates_t = {
lang = 'Lang',
langx = 'Langx',
langxx = 'Lang-xx',
transliteration = 'Transliteration',
}
--[[--------------------------< K N O W N _ P A R A M S >------------------------------------------------------
lists of all parameters known to {{lang}}, {{langx}}, {{lang-xx}} templates.
Exception: |fn= is known to {{lang}} but is not a 'lang' template; that parameter causes the module to call the
specified lang(), lang_xx_inherit(), or lang_xx_italic() function. These separate functions set |fn= to nill
and then do the known-param checking on the other template parameters
]]
local known_params_t = {
['common_params_all_t'] = { -- these parameters common to {{lang}}, {{langx}}, and {{lang-xx}}
['code'] = true,
['text'] = true,
['rtl'] = true,
['italic'] = true,
['italics'] = true,
['i'] = true,
['size'] = true,
['proto'] = true,
['nocat'] = true,
['cat'] = true,
['template'] = true, -- supplied by external templates to provide template name for error messaging ({{nihongo}}, etc)
},
['params_lang_t'] = { -- unique to {{lang}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
},
['params_x_t'] = { -- common to {{langx}} and {{lang-xx}}
['translit'] = true,
['translit-std'] = true,
['translit-script'] = true,
['translation'] = true,
['lit='] = true,
['label'] = true,
['link'] = true,
['links'] = true,
['lit'] = true,
['engvar'] = true,
},
['params_langx_t'] = { -- unique to {{langx}}
[1] = true, -- alias of |code=
[2] = true, -- alias of |text=
[3] = true, -- alias of |translit=
[4] = true, -- alias of |translation=
},
['params_lang_xx_t'] = { -- unique to {{lang-xx}}
[1] = true, -- alias of |text=
[2] = true, -- alias of |translit=
[3] = true, -- alias of |translation=
['script'] = true, -- these needed to override default params in {{lang-??}} templates
['region'] = true,
['variant'] = true,
},
}
--[[--------------------------< E N G _ V A R >----------------------------------------------------------------
Used at en.wiki so that spelling of 'romanized' (US, default) can be changed to 'romanised' to match the envar
specified by a {{Use xxx English}}. Not likely useful outside of en.wiki
This is accomplished by setting |engvar=gb; can, should be omitted in articles that use American English; no
need for the clutter.
]]
local engvar_sel_t = { -- select either UK English or US English
['au'] = 'gb_t', -- these match IANA region codes (except in lower case)
['ca'] = 'us_t',
['gb'] = 'gb_t',
['ie'] = 'gb_t',
['in'] = 'gb_t',
['nz'] = 'gb_t',
['us'] = 'us_t', -- default engvar
['za'] = 'gb_t'
};
local engvar_t = {
['gb_t'] = {
['romanisz_lc'] = 'romanisation', -- lower case
['romanisz_uc'] = 'Romanisation', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanised', -- past tense
},
['us_t'] = { -- default engvar
['romanisz_lc'] = 'romanization', -- lower case
['romanisz_uc'] = 'Romanization', -- upper case; unused can be deleted
['romanisz_pt'] = 'romanized', -- past tense
}
}
local default_engvar = 'us_t';
--[[
=============================<< M E S S A G I N G T A B L E S >>=============================================
these tables are for internationalization. Messages or fragments thereof are mostly grouped by function name.
Some messages are shared by functions other than the function table that lists the message or fragment.
]]
--[[--------------------------< K E Y W O R D S _ T >----------------------------------------------------------
]]
local keywords_t = {
['affirmative'] = 'yes',
['negative'] = 'no',
['unset'] = 'unset',
['invert'] = 'invert',
['default'] = 'default',
}
--[[--------------------------< M I S C _ T E X T _ T >--------------------------------------------------------
]]
local misc_text_t = {
['error'] = 'Error', -- make_error_msg(), tag_from_name()
['language'] = 'language', -- make_translit(), lang_xx(), name_from_tag()
['help'] = 'help',
}
--[[--------------------------< M A K E _ E R R O R _ M S G _ T >----------------------------------------------
]]
local make_error_msg_t = {
['xlit_err_cat'] = 'Transliteration template errors',
['lang_err_cat'] = 'Lang and lang-xx template errors',
['undefined'] = 'undefined',
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local parameter_validate_t = {
['invalid_param'] = 'invalid parameter: |$1=', -- $1 is parameter name
}
--[[--------------------------< V A L I D A T E _ I T A L I C _ T >--------------------------------------------
]]
local validate_italic_t = {
['multi_italic'] = 'only one of |italic=, |italics=, or |i= can be specified',
}
--[[--------------------------< V A L I D A T E _ T E X T _ T >------------------------------------------------
]]
local validate_text_t = {
['no_text'] = 'no text',
['malformed_markup'] = 'text has malformed markup',
['italic_markup'] = 'text has italic markup',
}
--[[--------------------------< T E X T _ S C R I P T _ M A T C H _ T E S T _ T >------------------------------
]]
local text_script_match_test_t = {
['latn_txt_mismatch'] = 'Latn text/non-Latn script subtag mismatch',
['latn_scr_mismatch'] = 'Non-latn text (pos $1: $2)/Latn script subtag mismatch', -- $1 identifies offending character's position; $2 is the character
}
--[[--------------------------< L A N G _ T >------------------------------------------------------------------
]]
local lang_t = {
['conflict_n_param'] = 'conflicting: {{{$1}}} and |$2=', -- $1 is positional param number, $2 is named param; shared with _lang_xx()
['conflict_n_param_types'] = {
['code'] = 'code',
['text'] = 'text',
['translit'] = 'translit',
},
['invalid_proto'] = 'invalid |proto=: $1', -- _lang_xx also emits this message
}
--[[--------------------------< L A N G _ X X _ T >------------------------------------------------------------
]]
local lang_xx_t = {
['conflict_n_lit'] = 'conflicting: {{{$1}}} and |lit= or |translation=', -- $1 is positional parameter; can be either 3 ({{lang-??}}) or 4 ({{langx}})
['conflict_lit'] = 'conflicting: |lit= and |translation=',
['conflict_link'] = 'conflicting: |links= and |link=',
['invalid_xlit_std'] = 'invalid translit-std',
['romanization'] = 'Romanization of',
['translit_nonlatn'] = 'transliteration text not Latin script (pos $1: $2)', -- _xlit() also emits this message; $1 identifies offending character's position; $2 is the character
['xlit_of_latn'] = 'transliteration of latn script',
}
--[[--------------------------< T A G _ F R O M _ N A M E _ T >------------------------------------------------
]]
local tag_from_name_t = {
['lang_not_found'] = 'language: $1 not found', -- $1 is language name parameter value
['missing_lang_name'] = 'missing language name',
}
--[[--------------------------< T R A N S L _ T >--------------------------------------------------------------
]]
local transl_t = {
['unrecog_xlit_std'] = 'unrecognized transliteration standard: $1', -- $1 is |translit_std- parameter value
['no_text'] = 'no text',
['missing_lang_scr'] = 'missing language / script code',
['unrecog_lang_scr'] = 'unrecognized language / script code: $1', -- $1 is the language/script code
}
--[[--------------------------< G E T _ I E T F _ P A R T S _ T >----------------------------------------------
]]
local get_ietf_parts_t = {
['maint_promo_cat'] = 'Lang and lang-xx code promoted to ISO 639-1|$1', -- $1 is ISO 639-2/3 subtag
['maint_promo_msg'] = 'code: $1 promoted to code: $2', -- $1 is ISO 639-2/3 subtag, $2 is synonymous ISO 639-1 subtag
['missing_lang_tag'] = 'missing language tag', -- also used in _langx()
['redundant_scr'] = 'redundant script tag',
['redundant_reg'] = 'redundant region tag',
['redundant_var'] = 'redundant variant tag',
['unrecog_tag'] = 'unrecognized language tag: $1', -- $1 is the whole language tag
['unrecog_code'] = 'unrecognized language code: $1', -- $1 is code
['unrecog_reg_code'] = 'unrecognized region: $1 for code: $2', -- $1 is region, $2 is code
['unrecog_scr_code'] = 'unrecognized script: $1 for code: $2', -- $1 is script, $2 is code
['script_code'] = 'script: $1 not supported for code: $2', -- $1 is script, $2 is code
['unrecog_var'] = 'unrecognized variant: $1', -- $1 is variant
['unrecog_var_code'] = 'unrecognized variant: $1 for code: $2', -- $1 is variant, $2 is code
['unrecog_var_code_scr'] = 'unrecognized variant: $1 for code-script pair: $2-$3', -- $1 is variant, $2 is code, $3 is script
['unrecog_var_code_reg'] = 'unrecognized variant: $1 for code-region pair: $2-$3', -- $1 is variant, $2 is code, $3 is region
['unrecog_pri'] = 'unrecognized private tag: $1', -- $1 is private tag
}
--[[--------------------------< L A N G U A G E _ N A M E _ G E T _ T >----------------------------------------
]]
local language_name_get_t = {
['deprecated_cat'] = 'Lang and langx using deprecated ISO 639 codes|$1', -- $1 is deprecated ISO 639 subtag
['deprecated_msg'] = 'code: $1 is deprecated', -- $1 is deprecated ISO 639 subtag
}
--[[--------------------------< H T M L _ T I T L E _ T E X T _ T >--------------------------------------------
]]
local make_text_html_t = {
['zxx'] = 'text', -- for zxx no linguistic content
['collective'] = 'collective text', -- for collective languages
['individual'] = 'language text', -- for individual languages
}
--[[--------------------------< T R A N S L A T I O N _ M A K E _ T >------------------------------------------
]]
local translation_make_t = {
['lit_xlation'] = 'Literal translation', -- article title fragment and HTML title attribute
['lit_abbr'] = 'lit.',
}
--[[--------------------------< M A K E _ C A T E G O R Y _ T >------------------------------------------------
]]
local make_category_t = {
['collective_cat'] = 'Ronney:Artyn lesh teks ayns',
['cat_prefix'] = 'Ronney:Artyn lesh teks ayns',
['explicit_cat'] = 'as eh symnit dy jarroo',
['cat_postfix'] = ''
}
--[[--------------------------< M A K E _ T R A N S L I T _ T >------------------------------------------------
]]
local make_translit_t = {
['script'] = 'script',
['transliteration'] = 'transliteration',
}
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
known_params_t = known_params_t,
templates_t = templates_t,
default_engvar = default_engvar, -- engvar support not likely useful outside of en.wiki
engvar_t = engvar_t,
engvar_sel_t = engvar_sel_t,
get_ietf_parts_t = get_ietf_parts_t, -- messaging tables
keywords_t = keywords_t,
lang_t = lang_t,
lang_xx_t = lang_xx_t,
language_name_get_t = language_name_get_t,
make_category_t = make_category_t,
make_error_msg_t = make_error_msg_t,
make_text_html_t = make_text_html_t,
make_translit_t = make_translit_t,
misc_text_t = misc_text_t,
parameter_validate_t = parameter_validate_t,
tag_from_name_t = tag_from_name_t,
text_script_match_test_t = text_script_match_test_t,
transl_t = transl_t,
translation_make_t = translation_make_t,
validate_italic_t = validate_italic_t,
validate_text_t = validate_text_t,
}
283s5n9nrdj88cii0x24i8k2y35fy7b
Module:Lang/data/is latn data
828
55813
392721
2026-09-02T02:39:49Z
MacTire02
219
Duillag crooit lesh: --[[--------------------------< S I N G L E S _ T >----------------------------------------------------------- list of Latn and Zyyy (common) codepoints that are not included in <ranges_t> taken from Module:Unicode data/scripts and a local copy of https://www.unicode.org/Public/17.0.0/ucd/ScriptExtensions.txt using Module:Lang/data/make is latn data ]] local singles_t = { [170] = true, -- 00AA [186] = true, -- 00BA [215] = true,...
392721
Scribunto
text/plain
--[[--------------------------< S I N G L E S _ T >-----------------------------------------------------------
list of Latn and Zyyy (common) codepoints that are not included in <ranges_t> taken from Module:Unicode data/scripts
and a local copy of https://www.unicode.org/Public/17.0.0/ucd/ScriptExtensions.txt using Module:Lang/data/make is latn data
]]
local singles_t = {
[170] = true, -- 00AA
[186] = true, -- 00BA
[215] = true, -- 00D7
[247] = true, -- 00F7
[787] = true, -- 0313
[856] = true, -- 0358
[862] = true, -- 035E
[884] = true, -- 0374
[894] = true, -- 037E
[901] = true, -- 0385
[903] = true, -- 0387
[1541] = true, -- 0605
[1548] = true, -- 060C
[1563] = true, -- 061B
[1567] = true, -- 061F
[1600] = true, -- 0640
[1757] = true, -- 06DD
[2274] = true, -- 08E2
[3647] = true, -- 0E3F
[4347] = true, -- 10FB
[6149] = true, -- 1805
[7379] = true, -- 1CD3
[7393] = true, -- 1CE1
[7418] = true, -- 1CFA
[7672] = true, -- 1DF8
[8305] = true, -- 2071
[8319] = true, -- 207F
[8432] = true, -- 20F0
[8498] = true, -- 2132
[8526] = true, -- 214E
[12294] = true, -- 3006
[12448] = true, -- 30A0
[12783] = true, -- 31EF
[13055] = true, -- 32FF
[43310] = true, -- A92E
[43471] = true, -- A9CF
[43867] = true, -- AB5B
[65279] = true, -- FEFF
[65392] = true, -- FF70
[119970] = true, -- 1D4A2
[119995] = true, -- 1D4BB
[120134] = true, -- 1D546
[129008] = true, -- 1F7F0
[129736] = true, -- 1FAC8
[917505] = true, -- E0001
}
--[[--------------------------< R A N G E S _ T >-------------------------------------------------------------
list of Latn and Zyyy (common) codepoints taken from Module:Unicode data/scripts and a local copy of
https://www.unicode.org/Public/16.0.0/ucd/ScriptExtensions.txt
]]
local ranges_t = {
{0, 169}, -- 0000..00A9
{171, 185}, -- 00AB..00B9
{187, 214}, -- 00BB..00D6
{216, 246}, -- 00D8..00F6
{248, 745}, -- 00F8..02E9
{748, 782}, -- 02EC..030E
{784, 785}, -- 0310..0311
{803, 805}, -- 0323..0325
{813, 814}, -- 032D..032E
{816, 817}, -- 0330..0331
{867, 879}, -- 0363..036F
{1157, 1158}, -- 0485..0486
{2385, 2386}, -- 0951..0952
{2404, 2405}, -- 0964..0965
{4053, 4056}, -- 0FD5..0FD8
{5867, 5869}, -- 16EB..16ED
{5941, 5942}, -- 1735..1736
{6146, 6147}, -- 1802..1803
{7401, 7404}, -- 1CE9..1CEC
{7406, 7411}, -- 1CEE..1CF3
{7413, 7415}, -- 1CF5..1CF7
{7424, 7461}, -- 1D00..1D25
{7468, 7516}, -- 1D2C..1D5C
{7522, 7525}, -- 1D62..1D65
{7531, 7543}, -- 1D6B..1D77
{7545, 7614}, -- 1D79..1DBE
{7680, 7935}, -- 1E00..1EFF
{8192, 8203}, -- 2000..200B
{8206, 8292}, -- 200E..2064
{8294, 8304}, -- 2066..2070
{8308, 8318}, -- 2074..207E
{8320, 8334}, -- 2080..208E
{8336, 8348}, -- 2090..209C
{8352, 8385}, -- 20A0..20C1
{8448, 8485}, -- 2100..2125
{8487, 8497}, -- 2127..2131
{8499, 8525}, -- 2133..214D
{8527, 8587}, -- 214F..218B
{8592, 9257}, -- 2190..2429
{9280, 9290}, -- 2440..244A
{9312, 10239}, -- 2460..27FF
{10496, 11123}, -- 2900..2B73
{11126, 11263}, -- 2B76..2BFF
{11360, 11391}, -- 2C60..2C7F
{11776, 11869}, -- 2E00..2E5D
{12272, 12292}, -- 2FF0..3004
{12296, 12320}, -- 3008..3020
{12336, 12343}, -- 3030..3037
{12348, 12351}, -- 303C..303F
{12443, 12444}, -- 309B..309C
{12539, 12540}, -- 30FB..30FC
{12688, 12703}, -- 3190..319F
{12736, 12773}, -- 31C0..31E5
{12832, 12895}, -- 3220..325F
{12927, 13007}, -- 327F..32CF
{13144, 13311}, -- 3358..33FF
{19904, 19967}, -- 4DC0..4DFF
{42752, 42972}, -- A700..A7DC
{42993, 43007}, -- A7F1..A7FF
{43056, 43065}, -- A830..A839
{43824, 43866}, -- AB30..AB5A
{43868, 43876}, -- AB5C..AB64
{43878, 43883}, -- AB66..AB6B
{64256, 64262}, -- FB00..FB06
{64830, 64831}, -- FD3E..FD3F
{65040, 65049}, -- FE10..FE19
{65072, 65106}, -- FE30..FE52
{65108, 65126}, -- FE54..FE66
{65128, 65131}, -- FE68..FE6B
{65281, 65381}, -- FF01..FF65
{65438, 65439}, -- FF9E..FF9F
{65504, 65510}, -- FFE0..FFE6
{65512, 65518}, -- FFE8..FFEE
{65529, 65533}, -- FFF9..FFFD
{65792, 65794}, -- 10100..10102
{65799, 65843}, -- 10107..10133
{65847, 65855}, -- 10137..1013F
{65936, 65948}, -- 10190..1019C
{66000, 66044}, -- 101D0..101FC
{66273, 66299}, -- 102E1..102FB
{67456, 67461}, -- 10780..10785
{67463, 67504}, -- 10787..107B0
{67506, 67514}, -- 107B2..107BA
{113824, 113827}, -- 1BCA0..1BCA3
{117760, 118012}, -- 1CC00..1CCFC
{118016, 118451}, -- 1CD00..1CEB3
{118458, 118480}, -- 1CEBA..1CED0
{118496, 118512}, -- 1CEE0..1CEF0
{118608, 118723}, -- 1CF50..1CFC3
{118784, 119029}, -- 1D000..1D0F5
{119040, 119078}, -- 1D100..1D126
{119081, 119142}, -- 1D129..1D166
{119146, 119162}, -- 1D16A..1D17A
{119171, 119172}, -- 1D183..1D184
{119180, 119209}, -- 1D18C..1D1A9
{119214, 119274}, -- 1D1AE..1D1EA
{119488, 119507}, -- 1D2C0..1D2D3
{119520, 119539}, -- 1D2E0..1D2F3
{119552, 119638}, -- 1D300..1D356
{119648, 119672}, -- 1D360..1D378
{119808, 119892}, -- 1D400..1D454
{119894, 119964}, -- 1D456..1D49C
{119966, 119967}, -- 1D49E..1D49F
{119973, 119974}, -- 1D4A5..1D4A6
{119977, 119980}, -- 1D4A9..1D4AC
{119982, 119993}, -- 1D4AE..1D4B9
{119997, 120003}, -- 1D4BD..1D4C3
{120005, 120069}, -- 1D4C5..1D505
{120071, 120074}, -- 1D507..1D50A
{120077, 120084}, -- 1D50D..1D514
{120086, 120092}, -- 1D516..1D51C
{120094, 120121}, -- 1D51E..1D539
{120123, 120126}, -- 1D53B..1D53E
{120128, 120132}, -- 1D540..1D544
{120138, 120144}, -- 1D54A..1D550
{120146, 120485}, -- 1D552..1D6A5
{120488, 120779}, -- 1D6A8..1D7CB
{120782, 120831}, -- 1D7CE..1D7FF
{122624, 122654}, -- 1DF00..1DF1E
{122661, 122666}, -- 1DF25..1DF2A
{126065, 126132}, -- 1EC71..1ECB4
{126209, 126269}, -- 1ED01..1ED3D
{126976, 127019}, -- 1F000..1F02B
{127024, 127123}, -- 1F030..1F093
{127136, 127150}, -- 1F0A0..1F0AE
{127153, 127167}, -- 1F0B1..1F0BF
{127169, 127183}, -- 1F0C1..1F0CF
{127185, 127221}, -- 1F0D1..1F0F5
{127232, 127405}, -- 1F100..1F1AD
{127462, 127487}, -- 1F1E6..1F1FF
{127489, 127490}, -- 1F201..1F202
{127504, 127547}, -- 1F210..1F23B
{127552, 127560}, -- 1F240..1F248
{127568, 127569}, -- 1F250..1F251
{127584, 127589}, -- 1F260..1F265
{127744, 128728}, -- 1F300..1F6D8
{128732, 128748}, -- 1F6DC..1F6EC
{128752, 128764}, -- 1F6F0..1F6FC
{128768, 128985}, -- 1F700..1F7D9
{128992, 129003}, -- 1F7E0..1F7EB
{129024, 129035}, -- 1F800..1F80B
{129040, 129095}, -- 1F810..1F847
{129104, 129113}, -- 1F850..1F859
{129120, 129159}, -- 1F860..1F887
{129168, 129197}, -- 1F890..1F8AD
{129200, 129211}, -- 1F8B0..1F8BB
{129216, 129217}, -- 1F8C0..1F8C1
{129232, 129240}, -- 1F8D0..1F8D8
{129280, 129623}, -- 1F900..1FA57
{129632, 129645}, -- 1FA60..1FA6D
{129648, 129660}, -- 1FA70..1FA7C
{129664, 129674}, -- 1FA80..1FA8A
{129678, 129734}, -- 1FA8E..1FAC6
{129741, 129756}, -- 1FACD..1FADC
{129759, 129770}, -- 1FADF..1FAEA
{129775, 129784}, -- 1FAEF..1FAF8
{129792, 129938}, -- 1FB00..1FB92
{129940, 130042}, -- 1FB94..1FBFA
{917536, 917631}, -- E0020..E007F
}
--[[--------------------------< S P E C I A L S _ T >---------------------------------------------------------
list of individual language-specific non-Latn and non-Zyyy codepoints; these codepoints commonly used in
transliterations. This list is manually currated so is most likely incomplete.
keys to <specials_t> are decimal codepoints; other keys are language tags (always lowercase) of language
transliterations that use these non-Latn codepoints.
]]
local specials_t = {
[788] = { -- U+0314: COMBINING REVERSED COMMA ABOVE
["hy"] = true, -- Armenian
},
[794] = { -- U+031A: COMBINING LEFT ANGLE ABOVE
["ltc"] = true, -- Middle Chinese; is this really IPA?
},
[795] = { -- U+031B: COMBINING HORN
["th"] = true, -- Thai
},
[806] = { -- U+0326: COMBINING COMMA BELOW
["ab"] = true, -- Abkhaz
["kca"] = true, -- Khanty
["xal"] = true, -- Kalmyk or Oirat
},
[807] = { -- U+0327: COMBINING CEDILLA
["fa"] = true, -- Persian
},
[809] = { -- U+0329: COMBINING VERTICAL LINE BELOW
["ab"] = true, -- Abkhaz
["sa"] = true, -- Sanskrit
},
[815] = { -- U+032F: COMBINING INVERTED BREVE BELOW
["mong"] = true, -- Mongolian
["xsc"] = true, -- Scythian
},
[818] = { -- U+0332: COMBINING LOW LINE
["ar"] = true, -- Arabic
["hbo"] = true, -- Ancient Hebrew
["he"] = true, -- Hebrew
["jpa"] = true, -- Jewish Palestinian Aramaic
["mdh"] = true, -- Maguindanaon
["otk"] = true, -- Old Turkish
},
[831] = { -- U+033F: COMBINING DOUBLE OVERLINE
["mnp"] = true, -- Northern Min Chinese, Jian'ou dialect
},
[855] = { -- U+0357: COMBINING RIGHT HALF RING ABOVE
["egy"] = true, -- Ancient Egyptian
},
[863] = { -- U+035F: COMBINING DOUBLE MACRON BELOW
["am"] = true, -- Amharic
["ar"] = true, -- Arabic
["dv"] = true, -- Dhivehi, Divehi, or Maldivian
["fa"] = true, -- Persian
["hi"] = true, -- Hindi
["inc"] = true, -- Indic languages
["ur"] = true, -- Urdu
},
[864] = { -- U+0360: COMBINING DOUBLE TILDE
["hi"] = true, -- Hindi
},
[865] = { -- U+0361: COMBINING DOUBLE INVERTED BREVE
["be"] = true, -- Belarusian
["ltc"] = true, -- Middle Chinese; is this really IPA?
["ru"] = true, -- Russian
["rue"] = true, -- Rusyn
["sem"] = true, -- Semitic languages
["sit"] = true, -- Sino-Tibetan languages
["tt"] = true, -- Tatar
},
[916] = { -- U+0394: GREEK CAPITAL LETTER DELTA
["xsc"] = true, -- Scythian
["xsc-x-pontic"] = true, -- Pontic Scythian
},
[920] = { -- U+0398: GREEK CAPITAL LETTER THETA
["ae"] = true, -- Avestan
},
[934] = { -- U+03A6: GREEK CAPITAL LETTER PHI
["xle"] = true, -- Lemnian
},
[945] = { -- U+03B1: GREEK SMALL LETTER ALPHA
["apc"] = true, -- Levantine Arabic
},
[946] = { -- U+03B2: GREEK SMALL LETTER BETA
["ae"] = true, -- Avestan
["gha"] = true, -- Ghadamès
["ougr"] = true, -- Old Uyghur
["sem"] = true, -- Semitic languages
["syc"] = true, -- Classical Syriac
["wuu"] = true, -- Shanghainese variety of Wu Chinese
},
[947] = { -- U+03B3: GREEK SMALL LETTER GAMMA
["ae"] = true, -- Avestan
["ltc"] = true, -- Late Middle Chinese
["mn"] = true, -- Mongolian
["och"] = true, -- Old Chinese
["ougr"] = true, -- Old Uyghur
["pal"] = true, -- Middle Persian
["syc"] = true, -- Classical Syriac
["syr"] = true, -- Syriac
["xal"] = true, -- Kalmyk or Oirat
["xng"] = true, -- Middle Mongolian
["xsc"] = true, -- Scythian
["ydg"] = true, -- Yidgha
["mong"] = true, -- Mongolian
},
[948] = { -- U+03B4: GREEK SMALL LETTER DELTA
["ae"] = true, -- Avestan
["ougr"] = true, -- Old Uyghur
["sog"] = true, -- Sogdian
["sogd"] = true, -- Sogdian
["syc"] = true, -- Classical Syriac
["xpr"] = true, -- Parthian
["xsc"] = true, -- Scythian
["xsc-x-pontic"] = true, -- Pontic Scythian
},
[952] = { -- U+03B8: GREEK SMALL LETTER THETA
["ae"] = true, -- Avestan
["ba"] = true, -- Bashkir
["cms"] = true, -- Messapic
["ett"] = true, -- Etruscan
["hur"] = true, -- Halkomelem
["ira"] = true, -- Iranian languages
["my"] = true, -- Burmese
["pal"] = true, -- Middle Persian (Pahlavi)
["peo"] = true, -- Old Persian
["sa"] = true, -- Sanskrit
["sem"] = true, -- Semitic languages
["syc"] = true, -- Classical Syriac
["syr"] = true, -- Syriac
["xme"] = true, -- Median
["xpg"] = true, -- Phrygian
["xpr"] = true, -- Parthian
["xsc"] = true, -- Scythian
},
[955] = { -- U+03BB: GREEK SMALL LETTER LAMDA
["xcr"] = true, -- Carian
["xld"] = true, -- Lydian
},
[963] = { -- U+03C3: GREEK SMALL LETTER SIGMA
["ett"] = true, -- Etruscan
},
[964] = { -- U+03C4: GREEK SMALL LETTER TAU
["xld"] = true, -- Lydian
},
[966] = { -- U+03C6: GREEK SMALL LETTER PHI
["ett"] = true, -- Etruscan
},
[967] = { -- U+03C7: GREEK SMALL LETTER CHI
["ett"] = true, -- Etruscan
["gem"] = true, -- Germanic languages
["hur"] = true, -- Halkomelem
["kbd"] = true, -- Kabardian
["ltc"] = true, -- Late Middle Chinese
["och"] = true, -- Old Chinese
["xlc"] = true, -- Lycian
["xle"] = true, -- Lemnian
},
[968] = { -- U+03C8: GREEK SMALL LETTER PSI
["ett"] = true, -- Etruscan
},
[977] = { -- U+03D1: GREEK THETA SYMBOL (cursive form)
["ae"] = true, -- Avestan
["ira"] = true, -- Iranian languages
["peo"] = true, -- Old Persian
["xme"] = true, -- Median
["xsc"] = true, -- Scythian
["xsc-x-pontic"] = true, -- Pontic Scythian
},
[1098] = { -- U+044A: CYRILLIC SMALL LETTER HARD SIGN
["ady"] = true, -- Adyghe
["cu"] = true, -- Church Slavic
["zls"] = true, -- South Slavic languages
},
[1100] = { -- U+044C: CYRILLIC SMALL LETTER SOFT SIGN
["az"] = true, -- Azerbaijani
["cu"] = true, -- Church Slavonic
["dng"] = true, -- Dungan
["ru"] = true, -- Russian
["tt"] = true, -- Tatar
["tyv"] = true, -- Tuvinian
},
[1278] = { -- U+04FE: CYRILLIC CAPITAL LETTER HA WITH STROKE
["av"] = true, -- Avar
},
[1279] = { -- U+04FF: CYRILLIC SMALL LETTER HA WITH STROKE
["av"] = true, -- Avar
},
[8113] = { -- U+1FB1: GREEK SMALL LETTER ALPHA WITH MACRON
["apc"] = true, -- Levantine Arabic
},
[8190] = { -- U+1FFE: GREEK DASIA
["ar"] = true, -- Arabic (Ayin)
["xcl"] = true, -- Classical Armenian
},
[19978] = { -- U+4E0A: [CJK Unified Ideographs]
["wuu"] = true, -- Wu Chinese tone marker
},
[20837] = { -- U+5165: [CJK Unified Ideographs]
["wuu"] = true, -- Wu Chinese tone marker
},
[21435] = { -- U+53BB: [CJK Unified Ideographs]
["wuu"] = true, -- Wu Chinese tone marker
},
[24179] = { -- U+5E73: [CJK Unified Ideographs]
["wuu"] = true, -- Wu Chinese tone marker
},
[38451] = { -- U+9633: [CJK Unified Ideographs] (Yang)
["wuu"] = true, -- Suzhou dialect of Wu Chinese tone marker --[[Suzhou dialect#Tones]]
},
[38452] = { -- U+9634: [CJK Unified Ideographs] (Yin)
["wuu"] = true, -- Suzhou dialect of Wu Chinese tone marker --[[Suzhou dialect#Tones]]
},
[65056] = { -- U+FE20: COMBINING LIGATURE LEFT HALF
["ru"] = true, -- Russian
},
[65057] = { -- U+FE21: COMBINING LIGATURE RIGHT HALF
["ru"] = true, -- Russian
},
}
--[[--------------------------< E X P O R T S >---------------------------------------------------------------
]]
return {
ranges_t = ranges_t,
singles_t = singles_t,
specials_t = specials_t,
sizeof_ranges_t = #ranges_t,
}
dc83p4l9k8mwwdqbirq3l5ieeolwkb8
Module:Lang/langx
828
55814
392722
2026-09-02T02:40:32Z
MacTire02
219
Duillag crooit lesh: --[[--------------------------< R T L _ T >-------------------------------------------------------------------- table of language tags that render text right-to-left Data in this table scraped from {{lang-xx}} templates that set |rtl=yes keys (tags) in this table must be lowercase. TODO: in the long run, do we need this table? Can't {{langx}} apply dir="rtl" attribute automatically? ]] local rtl_t = { ----------< I S O 6 3 9 - 1 >---------- ['ae'] = true, ['ar'...
392722
Scribunto
text/plain
--[[--------------------------< R T L _ T >--------------------------------------------------------------------
table of language tags that render text right-to-left
Data in this table scraped from {{lang-xx}} templates that set |rtl=yes
keys (tags) in this table must be lowercase.
TODO: in the long run, do we need this table? Can't {{langx}} apply dir="rtl" attribute automatically?
]]
local rtl_t = {
----------< I S O 6 3 9 - 1 >----------
['ae'] = true,
['ar'] = true,
['fa'] = true,
['he'] = true,
['ku'] = true,
['ps'] = true,
['sd'] = true,
['ur'] = true,
['yi'] = true,
----------< I S O 6 3 9 - 2 , - 3 >----------
['acm'] = true,
['aeb'] = true,
['aec'] = true,
['afb'] = true,
['aii'] = true,
['aij'] = true,
['aiq'] = true,
['ajp'] = true,
['amw'] = true,
['apc'] = true,
['arb'] = true,
['arc'] = true,
['arq'] = true,
['ary'] = true,
['arz'] = true,
['ayn'] = true,
['bal'] = true,
['bdz'] = true,
['bej'] = true,
['bgn'] = true,
['bqi'] = true,
['brh'] = true,
['bsk'] = true,
['ckb'] = true,
['cld'] = true,
['deh'] = true,
['gay'] = true,
['gbz'] = true,
['glk'] = true,
['hac'] = true,
['haz'] = true,
['hbo'] = true,
['hnd'] = true,
['hno'] = true,
['jog'] = true,
['jrb'] = true,
['jye'] = true,
['khw'] = true,
['kls'] = true,
['kvx'] = true,
['lrc'] = true,
['lss'] = true,
['luz'] = true,
['mey'] = true,
['mid'] = true,
['mki'] = true,
['mnj'] = true,
['mwr'] = true,
['myz'] = true,
['mzb'] = true,
['mzn'] = true,
['nlm'] = true,
['nqo'] = true,
['oru'] = true,
['ota'] = true,
['otk'] = true,
['pal'] = true,
['pes'] = true,
['prs'] = true,
['prx'] = true,
['rif'] = true,
['rys'] = true,
['sbn'] = true,
['scl'] = true,
['sgh'] = true,
['siz'] = true,
['skr'] = true,
['sqo'] = true,
['sqr'] = true,
['srh'] = true,
['syc'] = true,
['syr'] = true,
['tru'] = true,
['ttt'] = true,
['wbl'] = true,
['wne'] = true,
['xaa'] = true,
['xdm'] = true,
['xhe'] = true,
['xqa'] = true,
['ydg'] = true,
}
--[[--------------------------< S C R I P T _ T >--------------------------------------------------------------
table of language tags that use script subtags
Data in this table scraped from {{lang-xx}} templates that set |script=<script tag>
keys (tags) in this table must be lowercase.
]]
local script_t = {
----------< I S O 6 3 9 - 1 >----------
['ce'] = 'Cyrl',
['ff'] = 'Latn',
['sh'] = 'Latn',
----------< I S O 6 3 9 - 2 , - 3 >----------
['bft'] = 'Aran',
['brx'] = 'Deva',
['bsk'] = 'Aran',
['chr'] = 'Cher',
['dgo'] = 'Deva',
['dng'] = 'Cyrl',
['dyu'] = 'Latn',
['ess'] = 'Latn',
['evn'] = 'Cyrl',
['sat'] = 'Olck',
['shn'] = 'Mymr',
}
--[[--------------------------< S I Z E _ T >------------------------------------------------------------------
table of language tags that use |size=
Data in this table scraped from {{lang-xx}} templates that set |size=<size>
keys (tags) in this table must be lowercase.
]]
local size_t = {
['bft'] = '125%',
}
--[[--------------------------< L I N K _ T >------------------------------------------------------------------
table of language tags that use |link=
Data in this table scraped from {{lang-xx}} templates that set |link=
keys (tags) in this table must be lowercase.
]]
local link_t = {
['en'] = 'no',
}
--[[--------------------------< U N S U P P O R T E D _ T >----------------------------------------------------
these are language tags from {{lang-??}} templates that should not be converted to {{langx}} during the transition
from {{lang-??}} to {{langx|??}}.
this table used to add a category when {{langx}} templates are encountered with these language tags.
initial contents of this table copied from Wikipedia:Templates_for_discussion/Log/2024_September_27/lang-%3F%3F_templates#excluded_templates
2024-11-15: now that the conversion of the {{lang-??}} templates is complete, and User:Monkbot/task 20 has
completed its work, and now that Module:Lang detects unsupported parameters, those valid IETF tags listed here
can be stricken so that valid use of those tags with {{langx|<tag>|...}} can be allowed.
]]
local unsupported_t = {
['bcs'] = true, -- bcs is IANA Kohumono language not Bosnian/Croatian/Serbian grouped under tag sh
['crh3'] = true, -- being deleted; convert to something like {{lang-sr-latn-cyrl}}?
['est-sea'] = true, -- {{Language with name}} wrapper; convert to private use tag: et-x-seto?
['fra-frc'] = true, -- {{Language with name}} wrapper; convert to private use tag: fr-x-frainc?
['grc-gre'] = true, -- currently (2024-11-15) being discussed for deletion
['my-name-mlcts'] = true, -- wrapper around {{lang-my-Mymr}} to render a {{lang-??}}-like result
['sq-definite'] = true, -- definiteness is a linguistic construct
['su-fonts'] = true, -- styling
['uniturk'] = true, -- a writing system
['1ca'] = true, -- uses {{lang}} and trk-Arab-TR; add that tag to ~/data for Old Anatolian Turkish?
-- ['ast-leo'] = true, -- deleted; use ast-es
-- ['lmo-cr'] = true, -- deleted; use lmo-x-cremish
-- ['lmo-it'] = true, -- deleted; use lmo-x-berg
-- ['pun'] = true, -- deleted; was a template dab
-- ['sa2'] = true, -- deleted; use {{lang}}
-- ['bcs-latn-cyrl'] = true, -- {{lang-x2}} template wrappers; these tags not valid
-- ['cnr-cyrl-latn'] = true,
-- ['cnr-latn-cyrl'] = true,
-- ['sh-cyrl-latn'] = true,
-- ['sh-latn-cyrl'] = true,
-- ['sr-cyrl-latn'] = true,
-- ['sr-latn-cyrl'] = true,
-- ['uz-cyrl-latn'] = true,
-- ['uz-latn-cyrl'] = true,
-- ['cnr-cyrl'] = true, -- valid IETF tags; no reason to prevent their use with {{langx}}
-- ['cnr-latn'] = true,
-- ['hmd'] = true,
-- ['ka'] = true,
-- ['ku-arab'] = true,
-- ['mnc'] = true,
-- ['my-mymr'] = true,
-- ['rus'] = true, -- sort of valid IETF tag; should be promoted to 'ru'
-- ['sh-cyrl'] = true,
-- ['sh-latn'] = true,
-- ['sr'] = true, -- per Template_talk:Lang#tracking_sr_usage_with_issues; discussion died nothing being done
-- ['sr-cyrl'] = true,
-- ['sr-latn'] = true,
-- ['uz-latn'] = true,
-- ['zh'] = true,
-- Moldovan Cyrillic -- now a redirect to Lang-ro-Cyrl
-- ['vi-chunom'] = true, -- now a redirect to {{Chunom}}
-- ['vi-hantu'] = true, -- now a redirect to {{Chuhan}}
}
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
link_t = link_t,
rtl_t = rtl_t,
script_t = script_t,
size_t = size_t,
unsupported_t = unsupported_t,
}
gwqe7k12n9zu6mivhd6gqfmpab6pi7r