Wikiwordbōc
angwiktionary
https://ang.wiktionary.org/wiki/H%C4%93afodtramet
MediaWiki 1.47.0-wmf.22
case-sensitive
Media
Syndrig
Mōtung
Brūcend
Brūcendmōtung
Wikiwordbōc
Wikiwordbōcmōtung
Ymele
Ymelmōtung
MediaWiki
MediaWikimōtung
Bysen
Bysenmōtung
Help
Helpmōtung
Flocc
Floccmōtung
Ætēaca
Ætēacmōtung
TimedText
TimedText talk
Module
Module talk
Event
Event talk
beard
0
2013
54948
53640
2026-09-30T03:15:10Z
Deadend0914
7211
54948
wikitext
text/x-wiki
=={{sprǣc|ang}}==
===Rihtstefn===
* IPA: /bæɑrd/
===Fruma===
===Nama===
{{ang-noun|m}}
#þæt [[hār]] þe grēwþ on þǣre ānsīene manna
====Wendunga====
*[[Hebrēisc]]: {{Wendung|he|זקן}}
*[[Nīwenglisc]]: {{Wendung|en|beard}}
*[[Þēodisc]]: {{Wendung|de|Bart}}
[[Flocc:Englisc nama]]
[[Category:Englisc werlic nama]]
[[Category:Englisc bodigdǣl]]
=={{sprǣc|en}}==
===Rihtstefn===
* IPA: //
===Fruma===
*Ofgangen of Engliscum '''[[beard]]'''.
===Nama===
{{en-noun}}
# [[beard]]
[[Flocc:Nīwenglisce naman]]
[[Flocc:Nīwe Englisc bodigdǣl]]
rsrv8dlsq8f1zs2dov0ft0f4ai482e1
54949
54948
2026-09-30T03:15:23Z
Deadend0914
7211
54949
wikitext
text/x-wiki
=={{sprǣc|ang}}==
===Rihtstefn===
* IPA: /bæɑrd/
===Fruma===
===Nama===
{{ang-noun|m}}
#þæt [[hār]] þe grēwþ on þǣre ānsīene manna
====Wendunga====
*[[Hebrēisc]]: {{Wendung|he|זקן}}
*[[Nīwenglisc]]: {{Wendung|en|beard}}
*[[Þēodisc]]: {{Wendung|de|Bart}}
[[Flocc:Englisc nama]]
[[Category:Englisc werlic nama]]
[[Category:Englisc bodigdǣl]]
=={{sprǣc|en}}==
===Rihtstefn===
* IPA: //
===Fruma===
*Ofgangen of Engliscum '''[[beard]]'''.
===Nama===
{{en-noun}}
# [[beard]]
iaruwjlo206mhqso5cmp4fsfksqrb41
þrīe
0
3133
54953
54659
2026-09-30T03:20:40Z
Deadend0914
7211
/* {{Wordcynn|Getæl}} */
54953
wikitext
text/x-wiki
=={{sprǣc|ang}}==
=== Wordstǣr ===
[[Englisc]] ''þreo'', of [[Germanisc]]um ''*þrijiz'', of [[w:Indo-European languages|PIE]] ''*treyes''. Mǣgcūþ tō [[Þēodisc]]um ''drei'', [[Frencisc]]um ''trois'', [[Grēcisc]]um ''τρεις'', [[Russisc]]um ''три''.
=== Hēafodgetæl ===
=== {{Wordcynn|Getæl}} ===
{{Getæl-Tabule|
Hwā oþþe hwæt? (Werlic)=þrīe
|Hwā oþþe hwæt? (Wīflic)=[[þrēo]]
|Hwā oþþe hwæt? (Nāhwæðer)=[[þrēo]]
|Hwæs? (Eall)=þrēora
|Hwǣm? (Eall)=þrim
|Hwȳ? (Eall)=þrim
|Hwone? (Werlic)=þrīe
|Hwone? (Wīflic)=[[þrēo]]
|Hwone? (Nāhwæðer)=[[þrēo]]
}}
{{head|ang|numeral|head=þrīe}}
*[[w:Arabic Numerals|Arabisc getalu]]: 3
*[[w:Chinese numerals|Cīnisc getalu]]: 叄, 三
*[[w:Roman numerals|Rōmānisc getalu]]: III
**Beforan: [[twēgen]], 2
**Æfter: [[fēower]], 4
#[[Ān]] and [[twēgen]]. Þæt regollice getæl dǣla in mǣstum [[monocot]]iscum [[blōstm]]um. Endebyrdlic: [[þridda]]. Ēac gebrocen swā tōgeīecendlic word.
#: ''Þrīe weras wǣron in þǣm hūse.''
#: ''Þrīe wulfas wǣron in þǣm wuda.''
==== Wendunga ====
{| border=0 width=100%
|-
|bgcolor="#FFFFE0" valign=top width=48%|
{|
<!--languages from A to K go here-->
*Albanian: [[tre]] ''m'', [[tri]] ''f''
*[[Apache]] (Western): [[táági]]
*Arabic: [[ثلاثة]] (θalaːθa)
*[[Aymara]]: [[quimsa]]
*[[Basque]]: [[hiru]]
*[[Belarusian]]: [[тры]]
*Bosnian: [[tri#Bosnian|tri]]
*[[Breton]]: [[tri]] ''m'', [[teir]] ''f''
*[[Catalan]]: [[tres]]
*[[Cornish]]: [[tri]] ''m'', [[teyr]] ''f''
*Chinese: [[三]]
*Czech: [[tři]]
*Danish: [[tre]]
*Dutch: [[drie]]
*[[Esperanto]]: [[tri]]
*Estonian: [[kolm]]
*Farsi: [[سِه]] (se)
*Fijian: [[tolu]] ([[:fj:tolu|Vosa Vaka Viti]])
*Finnish: [[kolme]] ([[:fi:kolme|Suomi]])
*French: [[trois]]
*[[Frisian]]: [[trije]]
*[[Ga]]: {{IPAchar|[[etɛ̃]], [[etɛ]]}}
*German: [[drei]]
*Georgian: [[სამი]] (sami)
*Greek: [[τρείς]] (tris), [[τρία]] (tria)
*[[Guarani]]: [[mbohapy]]
*Hebrew: [[שלוש]] ''f'' (Used in counting)
*Hindi: [[तीन]] (tīn)
*Hungarian: [[három]]
*Icelandic: [[þrír]] ''m'', [[þrjár]] ''f'', [[þrjú]] ''n''
*Indonesian: [[tiga]]
*[[Ido]]: [[tri]]
*[[Interlingua]]: [[tres]]
*Irish: [[trí]]
*Italian: [[tre]]
*Japanese: [[三]] ([[さん]], san; [[み]], mi), [[三つ]] ([[みっつ]], mittsu)
*Jèrriais: [[trais]]
*[[Kalaallisut]]: [[pingasut]]
*Korean: [[셋]] (set')/[[세]] (se)/[[석]] (seok); [[삼]] ([[三]]; sam)
*Koryese: hot
*Kurdish: [[سيَ]] (sê)
|}
| width=1% |
|bgcolor="#FFFFE0" valign=top width=48%|
{|
<!--languages from L to Z go here-->
*Latin: [[tres]]
*[[Lojban]]: [[ci]]
*Malagasy: telo
*[[Manchu]]: [[ilan]]
*Manx: [[#Manx|three]]
*Marathi: तीन (tīn)
*[[Maricopa]]: [[xmokk]]
*[[Marshallese]]: [[jilu]]
*[[Nahuatl]]: [[yei]]
*Norwegian: [[tre]]
*[[O'odham]]: [[vaik]]
*Old English: [[þrie]], [[þreo]]
*Polish: [[trzy]]
*Portuguese: [[três]]
*Quechua: kinsa
*Rapanui: ka toru
*Romanian: [[trei]]
*Russian: [[три]]
*Saami: golbma
*[[Sanskrit]]: [[त्रि]] (tri), [[त्रयं]] (traya)
*Serbian:
*:Cyrillic: [[три#Serbian|три]]
*:Latin: [[tri#Serbian|tri]]
*Slovak: [[tri#Slovak|tri]], [[traja#Slovak|traja]]
*[[Slovio]]: [[tri]]
*Spanish: [[tres]]
*Swediah: [[tre]] ([[:sv:tre|Svenska]])
*Tagalog: [[tatlo]]
*Thai: [[สาม]] (s̄ām)
*[[Tok Pisin]]: [[tripela]]
*[[Tupinambá]]: [[mosapyr]]
*Turkish: [[üç]]
*Ukrainian: [[три#Ukrainian|три]]
*Vietnamese: [[ba#Vietnamese|ba]]
*Welsh: [[tri]] ''m'', [[tair]] ''f''
|}
|}
=== {{Wordcynn|Nama}} ===
{{Getæl-Naman-Tabule|
Hwá oþþe hwæt? (Werlic)=þrīe
|Hwá oþþe hwæt? (Wīflic)=[[þrēo]]
|Hwæs? (Werlic)=þrēora
|Hwæs? (Wīflic)=þrēora
|Hwǽm? (Werlic)=þrim
|Hwǽm? (Wīflic)=þrim
|Hwý? (Werlic)=þrim
|Hwý? (Wīflic)=þrim
|Hwone? (Werlic)=þrīe
|Hwone? (Wīflic)=[[þrēo]]
}}
'''þrīe''' ''werlic''
#Þæt getæl/ansīen 3, gebrocen on stede werlicra namena.
#: ''Þrīe wǣron in þǣm hūse.''
=== Wendunga ===
{| border=0 width=100%
|-
|bgcolor="#FFFFE0" valign=top width=48%|
{|
<!--languages from A to K go here-->
*Denisc: [[tretal]] ''nāhwæðer''
*Finnisc: [[kolmonen]]
*Frencisc: [[trois]] ''werlic''
*Hebrēisc: [[שלוש]] ''wīflic''
*Polisc: [[trójka]] ''wīflic''
|}
| width=1% |
|bgcolor="#FFFFE0" valign=top width=48%|
{|
<!--languages from L to Z go here-->
*Rōmānisc: [[trei]] ''m''
*Slovacisc: [[trojka#Slovak|trojka]] ''wīflic''
*Spēonisc: [[número]] [[tres]] ''werlic''
*Swēonisc: [[trea]]
*[[Tok Pisin]]: [[tri]]
*Þēodisc: [[Drei]] ''wīflic''
*Vietnamisc: [[số ba]]
|}
|}
[[Category:Hēafodgetalu]]
[[Category:200 Engliscra grundworda]]
j1wk0o1gfx6a3tayr1bwd9hoxi81adk
dēaþ
0
6423
54946
54915
2026-09-30T03:12:44Z
Deadend0914
7211
54946
wikitext
text/x-wiki
=={{sprǣc|ang}}==
===Āwendednessa===
* deað
* dǣþ
===Rihtstefn===
* /dæːɑθ/
===Wordstǣr===
Of {{inh|ang|gmw-pro|*dauþu}}, of {{inh|ang|gem-pro|*dauþuz}}, of {{inh|ang|ine-pro|*dʰautus}}.
====Sweostorword====
*Denisc: {{Wendung|da|død}}
*[[Fresisc]]: {{Wendung|fy|dea}} ''wr''
*Īslendisc: {{Wendung|is|dauði}} ''wr''
*Niðerlendisc: {{Wendung|nl|dood}} ''wr''
*Norþwegisc: {{Wendung|no|død}} ''wr''
*[[Seaxisc]]: {{Wendung|nds|Dood}} ''wr''
*Swēonisc: {{Wendung|sv|död}} ''gm''
*Þēodisc: {{Wendung|de|Tod}} ''wr''
===Werlīc Nama===
{{ang-noun|m|head=dēaþ}}
# Þæs līfes ende.
#: '''''Dēaþ''' nis nān belimp on līfe. '''Dēaðes''' man ne gebītt. Gif man ēcnesse understent nā tō endelēasre tīdlengðe, ac tō tīdlēasnesse, þonne leofaþ sē on ēcnesse þe leofaþ on andweardnesse. Ūre līf is endelēas ealswā ūre gesihtfeld gemǣrelēas biþ.''
====Nīwenglisc Andgiet====
# [[death]]
====Declīnung====
{{ang-decl-noun-a-m|dēaþ}}
====Gesetnyssum====
[[ær]]-dēaþ - early death, death before one's time, premature death <br>
dēaþ-[[bēam]] "wr" - death tree <br>
dēaþ-[[bedd]] "nw" - death bed, grave, bed of death, <br>
dēaþ-[[cwalu]] "wf" - plague death, violent death, <br>
dēaþ-[[dæg]] "wr" - death day, day of death, <br>
dēaþ-denu "wf" - valley of death, <br>
fær-dēaþ, dēaþ-ræs "wr" - sudden death, <br>
dēaþ-scūa "wr", dēaþ-scufa "wr" - death shadow, shadow of death, <br>
dēaþ-[[scyld]] "wf" - crime worthy of death <br>
dēaþ-stede "wr" - place of death <br>
dēaþ-[[wang]] "wr" - death plain, <br>
dēaþ-wīc "nw" - death's place, dwelling of the dead, <br>
dēaþ-[[wyrd]] "wf" - death fate, fate of death <br>
[[ende]]-dēað -death as the end of life <br>
[[gúð]]-dēað - battle death, death in battle <br>
[[mere]]-dēaþ - sea death, death at sea, <br>
[[swylt]]-dēaþ - death (die-death) <br>
[[wæl]]-dēaþ - death in battle, <br>
[[wundor]]-dēaþ - wondrous death <br>
====Wendunga====
*Frencisc: {{Wendung|fr|mort}} ''wf''
*Grēcisc: {{Wendung|el|θάνατος}} [ˈθa.na.to̞s] ''wr'', {{Wendung|el|θανατάς}} [θa.na.ˈtas] ''wr'',
{{Wendung|el|πεθαμός}} [pe̞.θa.ˈmo̞s] ''wr'', {{Wendung|el|αποθαμός}} [a.po̞.θa.ˈmo̞s] {{m}}, {{Wendung|el|χάρος}} [ˈxa.ro̞s] ''wr''
*Hebrēisc: {{Wendung|he|מוות}} (mavet) ''wf''
*Italisc: {{Wendung|it|morte}} ''wf''
*Lǣden: {{Wendung|la|mors}} ''wf'', {{Wendung|la|exitium}} ''nā'', {{Wendung|la|quietus}} ''wr''
*Persisc: {{Wendung|fa|مرگ}}
*Scyttisc Gǣlisc: {{Wendung|gd|bàs}} ''wr''
n4gzj0bs0kva2u9juoc18pgep09s3x2
Module:languages/data/3/a
828
7873
54941
54723
2026-09-30T02:48:05Z
Deadend0914
7211
54941
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["aaa"] = {
"Ghotuo",
35463,
"alv-yek",
"Latn",
}
m["aab"] = {
"Alumu-Tesu",
35034,
"nic-alu",
"Latn",
}
m["aac"] = {
"Ari",
1811224,
"ngf-gsu",
"Latn",
}
m["aad"] = {
"Amal",
56708,
"paa-sep",
"Latn",
}
-- "aae" is treated as "sq", see [[WT:LT]]
m["aaf"] = {
"Aranadan",
3507928,
"dra-mal",
"Mlym",
-- Mlym translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
m["aag"] = {
"Ambrak",
4741706,
"paa-pal",
"Latn",
}
m["aah"] = {
"Abu'",
4670715,
"paa-ara",
"Latn",
}
m["aai"] = {
"Arifama-Miniafia",
4790560,
"poz-ocw",
"Latn",
}
m["aak"] = {
"Ankave",
3446690,
"ngf-ata",
"Latn",
}
m["aal"] = {
"Afade",
56434,
"cdc-cbm",
"Latn",
}
m["aan"] = {
"Anambé",
3507873,
"tup-gua",
"Latn",
}
m["aap"] = {
"Arára (Pará)",
56807,
"sai-pek",
"Latn",
}
m["aaq"] = {
"Penobscot",
3515185,
"alg-abp",
"Latn",
}
m["aas"] = {
"Aasax",
56620,
"cus-sou",
"Latn",
}
-- "aat" is treated as "sq", see [[WT:LT]]
m["aau"] = {
"Abau",
3073568,
"paa-sep",
"Latn",
}
m["aaw"] = {
"Solong",
7558834,
"poz-ocw",
"Latn",
}
m["aax"] = {
"Upper Mandobo",
12636156,
"ngf-dum",
"Latn",
}
m["aaz"] = {
"Amarasi",
4740192,
"poz-tim",
"Latn",
}
m["aba"] = {
"Abé",
34833,
"alv-lag",
"Latn",
}
m["abb"] = {
"Bankon",
34860,
"bnt-bsa",
"Latn",
}
m["abc"] = {
"Ambala Ayta",
3448896,
"phi",
"Latn",
}
m["abd"] = {
"Camarines Norte Agta",
3399682,
"phi",
"Latn",
}
m["abe"] = {
"Abenaki",
17502788,
"alg-abp",
"Latn",
}
m["abf"] = {
"Abai Sungai",
4663287,
"poz-san",
"Latn",
}
m["abg"] = {
"Abaga",
3507954,
"ngf-kya",
"Latn",
}
m["abh"] = {
"Tajiki Arabic",
56833,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["abi"] = {
"Abidji",
34781,
"alv-lag",
"Latn",
}
m["abj"] = {
"Aka-Bea",
2356391,
"qfa-ads",
"Latn",
}
m["abl"] = {
"Abung",
49215,
"poz-lgx",
"Latn",
}
m["abm"] = {
"Abanyom",
7502,
"nic-eko",
"Latn",
}
m["abn"] = {
"Abua",
34835,
"nic-cde",
"Latn",
}
m["abo"] = {
"Abon",
35121,
"nic-tvn",
"Latn",
}
m["abp"] = {
"Abenlen Ayta",
3436621,
"phi",
"Latn",
}
m["abq"] = {
"Abaza",
27567,
"cau-abz",
"Cyrl, Latn",
translit = {
Cyrl = "abq-translit"
},
override_translit = true,
display_text = {
Cyrl = s["cau-Cyrl-displaytext"]
},
strip_diacritics = {
Cyrl = s["cau-Cyrl-stripdiacritics"],
Latn = s["cau-Latn-stripdiacritics"],
},
sort_key = {
Cyrl = {
from = {
"гъв", "гъь", "гӏв", "джв", "джь", "къв", "къь", "кӏв", "кӏь", "хъв", "хӏв", "чӏв", -- 3 chars
"гв", "гъ", "гь", "гӏ", "дж", "дз", "ё", "жв", "жь", "кв", "къ", "кь", "кӏ", "ль", "лӏ", "пӏ", "тл", "тш", "тӏ", "фӏ", "хв", "хъ", "хь", "хӏ", "цӏ", "чв", "чӏ", "шв", "шӏ" -- 2 chars
},
to = {
"г" .. p[3], "г" .. p[4], "г" .. p[7], "д" .. p[2], "д" .. p[3], "к" .. p[3], "к" .. p[4], "к" .. p[7], "к" .. p[8], "х" .. p[3], "х" .. p[6], "ч" .. p[3],
"г" .. p[1], "г" .. p[2], "г" .. p[5], "г" .. p[6], "д" .. p[1], "д" .. p[4], "е" .. p[1], "ж" .. p[1], "ж" .. p[2], "к" .. p[1], "к" .. p[2], "к" .. p[5], "к" .. p[6], "л" .. p[1], "л" .. p[2], "п" .. p[1], "т" .. p[1], "т" .. p[2], "т" .. p[3], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "х" .. p[5], "ц" .. p[1], "ч" .. p[1], "ч" .. p[2], "ш" .. p[1], "ш" .. p[2]
}
},
},
}
-- "abr" Abron is treated as "ak" Akan, see [[WT:LT]]
m["abs"] = {
"Ambonese Malay",
3124354,
"crp",
"Latn",
ancestors = "ms",
}
m["abt"] = {
"Ambulas",
3508015,
"paa-nnd",
"Latn",
}
m["abu"] = {
"Abure",
34767,
"alv-ptn",
"Latn",
}
m["abv"] = {
"Baharna Arabic",
56576,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["abw"] = {
"Pal",
7126121,
"ngf-omo",
"Latn",
}
m["abx"] = {
"Inabaknon",
2820163,
"poz-sbj",
"Latn",
}
m["aby"] = {
"Aneme Wake",
3508107,
"ngf-yar",
"Latn",
}
m["abz"] = {
"Abui",
2822110,
"paa-alp",
"Latn",
}
m["aca"] = {
"Achagua",
2822982,
"awd",
"Latn",
}
m["acb"] = {
"Áncá",
11130787,
"nic-mom",
"Latn",
}
m["acd"] = {
"Gikyode",
35256,
"alv-gng",
"Latn",
}
m["ace"] = {
"Acehnese",
27683,
"cmc",
"Latn, Arab",
standard_chars = {
Latn = "AaBbCcDdEeÉéÈèËëFfGgHhIiJjKkLlMmNnOoÔôÖöPpQqRrSsTtUuVvWwXxYyZz", -- current orthography (not yet add Arab)
c.punc
},
}
m["ach"] = {
"Acholi",
34926,
"sdv-los",
"Latn",
}
m["aci"] = {
"Aka-Cari",
2670418,
"qfa-adn",
"Latn",
}
m["ack"] = {
"Aka-Kora",
3433680,
"qfa-adn",
"Latn",
}
m["acl"] = {
"Akar-Bale",
3436825,
"qfa-ads",
"Latn",
}
m["acm"] = {
"Iraqi Arabic",
56232,
"sem-arb",
"Arab, Hebr",
strip_diacritics = {
Arab = "ar-stripdiacritics",
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["acn"] = {
"Achang",
56582,
"tbq-brm",
"Latn",
}
m["acp"] = {
"Eastern Acipa",
5329945,
"nic-kmk",
"Latn",
}
m["acr"] = {
"Achi",
34774,
"myn",
"Latn",
}
m["acs"] = {
"Acroá",
2829146,
"sai-cje",
"Latn",
}
m["acu"] = {
"Achuar",
2823170,
"sai-jiv",
"Latn",
}
m["acv"] = {
"Achumawi",
56661,
"nai-pal",
"Latn",
}
m["acw"] = {
"Hijazi Arabic",
56608,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["acx"] = {
"Omani Arabic",
56630,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["acy"] = {
"Cypriot Arabic",
56416,
"sem-arb",
"Latn, Grek",
ancestors = "acm",
strip_diacritics = {
Latn = {remove_diacritics = c.grave .. c.acute .. c.breve},
},
-- Grek display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
standard_chars = {
Latn = "AaBbCcDdΔδEeFfGgĠġĊċIiJjKkLlMmNnOoPpΘθRrSsTtUuVvWwXxYyZzŞş",
c.punc
},
}
m["acz"] = {
"Acheron",
34769,
"alv-tal",
"Latn",
}
m["ada"] = {
"Adangme",
35141,
"alv-gda",
"Latn",
}
m["adb"] = {
"Atauran",
125421255,
"poz-cet",
"Latn",
}
m["add"] = {
"Dzodinka",
35266,
"nic-nka",
"Latn",
}
m["ade"] = {
"Adele",
27740,
"alv-ntg",
"Latn",
}
m["adf"] = {
"Dhofari Arabic",
56565,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["adg"] = {
"Andegerebinha",
3508123,
"aus-rnd",
"Latn",
}
m["adh"] = {
"Adhola",
1971400,
"sdv-los",
"Latn",
}
m["adi"] = {
"Adi",
56440,
"sit-tan",
"Latn",
}
m["adj"] = {
"Adioukrou",
34738,
"alv-lag",
"Latn",
}
m["adl"] = {
"Galo",
2857892,
"sit-tan",
"Latn",
}
m["adn"] = {
"Adang",
3398276,
"paa-alp",
"Latn",
}
m["ado"] = {
"Abu",
56659,
"paa-por",
"Latn",
}
m["adp"] = {
"Adap",
3512402,
"sit-tib",
"Tibt",
ancestors = "dz",
override_translit = true,
-- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["adq"] = {
"Adangbe",
34730,
"alv-gda",
"Latn",
ancestors = "ada",
}
m["adr"] = {
"Adonara",
4684505,
"poz-cet",
"Latn",
}
m["ads"] = {
"Adamorobe Sign Language",
27709,
"sgn",
"Latn", -- when documented
}
m["adt"] = {
"Adnyamathanha",
2225391,
"aus-psw",
"Latn",
}
m["adu"] = {
"Aduge",
34734,
"alv-nwd",
"Latn",
ancestors = "opa",
}
m["adw"] = {
"Amondawa",
12626847,
"tup-gua",
"Latn",
}
m["ady"] = {
"West Circassian",
27776,
"cau-cir",
"Cyrl, Latn, Arab",
translit = {
Cyrl = "cau-cir-translit",
Arab = "ar-translit",
},
override_translit = true,
display_text = {
Cyrl = s["cau-Cyrl-displaytext"]
},
strip_diacritics = {
Cyrl = s["cau-Cyrl-stripdiacritics"],
Latn = s["cau-Latn-stripdiacritics"],
},
sort_key = {
Cyrl = {
from = {
"кхъу", "къӏу", -- 4 chars
"гъу", "джу", "дзу", "жъу", "къу", "кхъ", "къӏ", "кӏу", "кӏь", "лъу", "лӏу", "пӏу", "сӏу", "тӏу", "фӏу", "хъу", "цӏу", "чъу", "чӏу", "шъу", "шӏу", "щӏу", -- 3 chars
"гу", "гъ", "гь", "дж", "дз", "ё", "жъ", "жь", "ку", "къ", "кь", "кӏ", "лъ", "ль", "лӏ", "пӏ", "сӏ", "тӏ", "фӏ", "ху", "хъ", "хь", "цу", "цӏ", "чу", "чъ", "чӏ", "шъ", "шӏ", "щӏ", "ӏу", "ӏь" -- 2 chars
},
to = {
"к" .. p[5], "к" .. p[7],
"г" .. p[3], "д" .. p[2], "д" .. p[4], "ж" .. p[2], "к" .. p[3], "к" .. p[4], "к" .. p[6], "к" .. p[10], "к" .. p[11], "л" .. p[2], "л" .. p[5], "п" .. p[2], "с" .. p[2], "т" .. p[2], "ф" .. p[2], "х" .. p[3], "ц" .. p[3], "ч" .. p[3], "ч" .. p[5], "ш" .. p[2], "ш" .. p[4], "щ" .. p[2],
"г" .. p[1], "г" .. p[2], "г" .. p[4], "д" .. p[1], "д" .. p[3], "е" .. p[1], "ж" .. p[1], "ж" .. p[3], "к" .. p[1], "к" .. p[2], "к" .. p[8], "к" .. p[9], "л" .. p[1], "л" .. p[3], "л" .. p[4], "п" .. p[1], "с" .. p[1], "т" .. p[1], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "ц" .. p[1], "ц" .. p[2], "ч" .. p[1], "ч" .. p[2], "ч" .. p[4], "ш" .. p[1], "ш" .. p[3], "щ" .. p[1], "ӏ" .. p[1], "ӏ" .. p[2]
}
},
},
}
m["adz"] = {
"Adzera",
3327445,
"poz-ocw",
"Latn",
}
m["aea"] = {
"Areba",
3509129,
"aus-pam",
"Latn",
}
m["aeb"] = {
"Tunisian Arabic",
56240,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["aed"] = {
"Argentine Sign Language",
3322073,
"sgn",
"Latn", -- when documented
}
m["aee"] = {
"Northeast Pashayi",
12642198,
"inc-pas",
"Arab, Latn",
}
m["aek"] = {
"Haeke",
5638166,
"poz-cln",
"Latn",
}
m["ael"] = {
"Ambele",
34818,
"nic-grf",
"Latn",
}
m["aem"] = {
"Arem",
3507920,
"mkh-vie",
"Latn",
}
m["aen"] = {
"Armenian Sign Language",
3446604,
"sgn",
}
m["aeq"] = {
"Aer",
3246741,
"inc-wes",
"Arab",
}
m["aer"] = {
"Eastern Arrernte",
10728232,
"aus-rnd",
"Latn",
}
m["aes"] = {
"Alsea",
2395641,
nil,
"Latn",
}
m["aeu"] = {
"Akeu",
4700657,
"tbq-sil",
"Latn",
}
m["aew"] = {
"Ambakich",
56642,
"paa-eke",
"Latn",
}
m["aey"] = {
"Amele",
3508025,
"ngf-gum",
"Latn",
}
m["aez"] = {
"Aeka",
16110528,
"ngf-oro",
"Latn",
}
m["afb"] = {
"Gulf Arabic",
56385,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["afd"] = {
"Andai",
4753480,
"paa-arf",
"Latn",
}
m["afe"] = {
"Putukwam",
3914930,
"nic-ben",
"Latn",
}
m["afg"] = {
"Afghan Sign Language",
4689093,
"sgn",
}
m["afh"] = {
"Afrihili",
384707,
"art",
"Latn",
type = "appendix-constructed",
}
m["afi"] = {
"Akrukay",
57003,
"paa-tam",
"Latn",
}
m["afk"] = {
"Nanubae",
6964416,
"paa-arf",
"Latn",
}
m["afn"] = {
"Defaka",
35174,
"nic",
"Latn",
}
m["afo"] = {
"Eloyi",
3914066,
"nic-plt",
"Latn",
}
m["afp"] = {
"Tapei",
16887371,
"paa-arf",
"Latn",
}
m["afs"] = {
"Afro-Seminole Creole",
27867,
"crp",
"Latn",
ancestors = "en",
}
m["aft"] = {
"Afitti",
3400829,
"sdv-nyi",
"Latn",
}
m["afu"] = {
"Awutu",
34847,
"alv-gng",
"Latn",
}
m["afz"] = {
"Obokuitai",
7075258,
"paa-clp",
"Latn",
}
m["agb"] = {
"Legbo",
35584,
"nic-uce",
"Latn",
}
m["agc"] = {
"Agatu",
34732,
"alv-ido",
"Latn",
}
m["agd"] = {
"Agarabi",
3399642,
"ngf-gau",
"Latn",
}
m["age"] = {
"Angal",
10951553,
"ngf-ank",
"Latn",
}
m["agf"] = {
"Arguni",
12473346,
"poz-cet",
"Latn",
}
m["agg"] = {
"Angor",
3508100,
"paa-sng",
"Latn",
}
m["agh"] = {
"Ngelima",
7022266,
"bnt-bta",
"Latn",
}
m["agj"] = {
"Argobba",
29292,
"sem-eth",
"Ethi",
}
m["agk"] = {
"Isarog Agta",
6078982,
"phi",
"Latn",
}
m["agl"] = {
"Fembe",
372927,
"ngf-est",
"Latn",
}
m["agm"] = {
"Angaataha",
3508001,
"ngf-ang",
"Latn",
}
m["agn"] = {
"Agutaynen",
3399717,
"phi-kal",
"Latn",
}
m["ago"] = {
"Tainae",
7676186,
"ngf-taa",
"Latn",
}
m["agq"] = {
"Aghem",
34737,
"nic-rnw",
"Latn",
}
m["agr"] = {
"Aguaruna",
1526530,
"sai-jiv",
"Latn",
}
m["ags"] = {
"Esimbi",
35260,
"nic-bds",
"Latn",
}
m["agt"] = {
"Central Cagayan Agta",
5017296,
"phi",
"Latn",
}
m["agu"] = {
"Aguacateca",
35091,
"myn",
"Latn",
}
m["agv"] = {
"Remontado Agta",
3508085,
"phi",
"Latn",
}
m["agw"] = {
"Kahua",
3191906,
"poz-sls",
"Latn",
}
m["agx"] = {
"Aghul",
36498,
"cau-esm",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
sort_key = {
from = {"аь", "гъ", "гь", "гӏ", "дж", "ё", "къ", "кь", "кӏ", "оь", "пӏ", "тӏ", "уь", "хъ", "хь", "хӏ", "цӏ", "чӏ"},
to = {"а" .. p[1], "г" .. p[1], "г" .. p[2], "г" .. p[3], "д" .. p[1], "е" .. p[1], "к" .. p[1], "к" .. p[2], "к" .. p[3], "о" .. p[1], "п" .. p[1], "т" .. p[1], "у" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[3], "ц" .. p[1], "ч" .. p[1]}
},
}
m["agy"] = {
"Southern Alta",
7569611,
"phi",
"Latn",
}
m["agz"] = {
"Mount Iriga Agta",
6921432,
"phi",
"Latn",
}
m["aha"] = {
"Ahanta",
34729,
"alv-ctn",
"Latn",
}
m["ahb"] = {
"Axamb",
2874710,
"poz-vnc",
"Latn",
}
m["ahg"] = {
"Qimant",
35663,
"cus-cen",
"Latn",
}
m["ahh"] = {
"Aghu",
3436645,
"ngf-awy",
"Latn",
}
m["ahi"] = {
"Tiagba",
3400073,
"kro-aiz",
"Latn",
}
m["ahk"] = {
"Akha",
56643,
"tbq-han",
"Latn, Mymr, Thai",
sort_key = {
Thai = {
from = {"[%pๆ]", "[็-๎]", "([เแโใไ])([ก-ฮ])"},
to = {"", "", "%2%1"}
},
},
}
m["ahl"] = {
"Igo",
35412,
"alv-ktg",
"Latn",
}
m["ahm"] = {
"Mobu",
35967,
"kro-aiz",
"Latn",
}
m["ahn"] = {
"Àhàn",
34723,
"alv-aah",
"Latn",
}
m["aho"] = {
"Ahom",
34778,
"tai-swe",
"Ahom",
translit = "Ahom-translit",
}
m["ahp"] = {
"Apro",
34810,
"alv-kwa",
"Latn",
}
m["ahr"] = {
"Ahirani",
15549890,
"raj",
"Deva",
translit = "mr-translit",
}
m["ahs"] = {
"Ashe",
34823,
"nic-plc",
"Latn",
}
m["aht"] = {
"Ahtna",
21058,
"ath-nor",
"Latn",
}
m["aia"] = {
"Arosi",
2863483,
"poz-sls",
"Latn",
}
m["aib"] = {
"Äynu",
27927,
"qfa-mix",
"Arab, Latn",
ancestors = "ug, fa"
}
m["aic"] = {
"Ainbai",
3332149,
"paa-bew",
"Latn",
}
m["aid"] = {
"Alngith",
3279409,
"aus-pmn",
"Latn",
}
m["aie"] = {
"Amara",
2841180,
"poz-ocw",
"Latn",
}
m["aif"] = {
"Agi",
3331491,
"paa-wpa",
"Latn",
}
m["aig"] = {
"Antigua and Barbuda Creole English",
3244184,
"crp",
"Latn",
ancestors = "en",
}
m["aih"] = {
"Ai-Cham",
2827749,
"qfa-kms",
"Latn, Hani",
sort_key = {
Hani = "Hani-sortkey"
},
}
m["aii"] = {
"Assyrian Neo-Aramaic",
29440,
"sem-nna",
"Syrc",
translit = "aii-translit",
strip_diacritics = "Syrc-stripdiacritics",
}
m["aij"] = {
"Lishanid Noshan",
3436467,
"sem-nna",
"Hebr",
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["aik"] = {
"Ake",
34808,
"nic-pls",
"Latn",
}
m["ail"] = {
"Aimele",
3327418,
"ngf-bos",
"Latn",
}
m["aim"] = {
"Aimol",
4697175,
"tbq-kuk",
"Latn, Beng",
}
m["ain"] = {
"Ainu",
27969,
"qfa-ain",
"Kana, Latn, Cyrl",
sort_key = {
Kana = "Kana-sortkey"
},
}
m["aio"] = {
"Aiton",
3399725,
"tai-swe",
"Mymr",
translit = "aio-phk-translit",
display_text = s["aio-displaytext"],
strip_diacritics = s["aio-stripdiacritics"],
}
m["aip"] = {
"Burumakok",
5000984,
"ngf-wok",
"Latn",
}
m["air"] = {
"Airoran",
3321131,
"paa-saa",
"Latn",
}
m["ait"] = {
"Arikem",
3446679,
"tup",
"Latn",
}
m["aiw"] = {
"Aari",
7495,
"omv-aro",
"Latn",
}
m["aix"] = {
"Aighon",
3504287,
"poz-ocw",
"Latn",
}
m["aiy"] = {
"Ali",
34814,
"gba-eas",
"Latn",
}
m["aja"] = {
"Aja (East Africa)",
3237491,
"csu-bkr",
"Latn",
}
m["ajg"] = {
"Aja (West Africa)",
35035,
"alv-gbe",
"Latn",
}
m["aji"] = {
"Ajië",
2828867,
"poz-cln",
"Latn",
}
m["ajn"] = {
"Andajin",
16111302,
"aus-wor",
"Latn",
}
m["ajp"] = {
"South Levantine Arabic",
55633582,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ajs"] = {
"Algerian Jewish Sign Language",
5555709,
"sgn",
}
-- m["ajt"] Judeo-Tunisian Arabic now included in Tunisian Arabic
-- m["aju"] Judeo-Moroccan Arabic now included in Moroccan Arabic
m["ajw"] = {
"Ajawa",
56645,
"cdc-wst",
"Latn",
}
m["ajz"] = {
"Amri Karbi",
3508092,
"tbq-kuk",
"Latn",
ancestors = "mjw",
}
m["akb"] = {
"Angkola Batak",
2640686,
"btk",
"Latn, Batk",
}
m["akc"] = {
"Mpur",
3327139,
"qfa-iso", -- Papuan; based on Palmer (2018), Ethnologue and Glottolog
"Latn",
}
m["akd"] = {
"Ukpet-Ehom",
36618,
"nic-ucr",
"Latn",
}
m["ake"] = {
"Akawaio",
28059,
"sai-pem",
"Latn",
}
m["akf"] = {
"Akpa",
34801,
"alv-ido",
"Latn",
}
m["akg"] = {
"Anakalangu",
4750964,
"poz-cet",
"Latn",
}
m["akh"] = {
"Angal Heneng",
10950354,
"ngf-ank",
"Latn",
}
m["aki"] = {
"Aiome",
56735,
"paa-aia",
"Latn",
}
m["akj"] = {
"Jeru",
2919121,
"qfa-adn",
"Latn, Deva",
}
m["akk"] = {
"Akkadian",
35518,
"sem-eas",
"Xsux, Latn",
}
m["akl"] = {
"Aklanon",
8773,
"phi",
"Latn",
}
m["akm"] = {
"Aka-Bo",
35361,
"qfa-adn",
"Latn",
}
m["ako"] = {
"Akurio",
56650,
"sai-tar",
"Latn",
}
m["akp"] = {
"Siwu",
36470,
"alv-ntg",
"Latn",
}
m["akq"] = {
"Ak",
56654,
"paa-sep",
"Latn",
}
m["akr"] = {
"Araki",
2699882,
"poz-vnn",
"Latn",
}
m["aks"] = {
"Akaselem",
34817,
"nic-grm",
"Latn",
}
m["akt"] = {
"Akolet",
3330162,
"poz-ocw",
"Latn",
}
m["aku"] = {
"Akum",
34799,
"nic-ykb",
"Latn",
}
m["akv"] = {
"Akhvakh",
56423,
"cau-and",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
}
m["akw"] = {
"Akwa",
34802,
"bnt-mbo",
"Latn",
}
m["akx"] = {
"Aka-Kede",
3436816,
"qfa-adc",
"Latn",
}
m["aky"] = {
"Aka-Kol",
3436784,
"qfa-adc",
"Latn",
}
m["akz"] = {
"Alabama",
1815020,
"nai-mus",
"Latn",
}
m["ala"] = {
"Alago",
34813,
"alv-ido",
"Latn",
}
m["alc"] = {
"Kawésqar",
56544,
"aqa",
"Latn",
}
m["ald"] = {
"Alladian",
34837,
"alv-lag",
"Latn",
}
m["ale"] = {
"Aleut",
27210,
"esx",
"Latn, Cyrl",
}
m["alf"] = {
"Alege",
34815,
"nic-ben",
"Latn",
}
m["alh"] = {
"Alawa",
2147917,
"aus-gun",
"Latn",
}
m["ali"] = {
"Amaimon",
3327427,
"ngf-mad",
"Latn",
}
m["alj"] = {
"Alangan",
3327423,
"phi",
"Latn",
}
m["alk"] = {
"Alak",
2714690,
"mkh",
"Latn",
}
m["all"] = {
"Allar",
3393634,
"dra-mal",
"Mlym",
-- Mlym translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
-- "aln" is treated as "sq", see [[WT:LT]]
m["alm"] = {
"Amblong",
11022615,
"poz-vnn",
"Latn",
}
m["alo"] = {
"Larike-Wakasihu",
3217929,
"poz-cma",
"Latn",
}
m["alp"] = {
"Alune",
3327367,
"poz-cet",
"Latn",
}
m["alq"] = {
"Algonquin",
28092,
"alg",
"Latn, Cans",
ancestors = "oj",
}
m["alr"] = {
"Alutor",
28213,
"qfa-ckn",
"Cyrl",
strip_diacritics = {
from = {"['’]"},
to = {"ʼ"}
},
sort_key = {
from = {"вʼ", "гʼ", "ғ", "ә", "ё", "ӄ", "ӈ"},
to = {"в" .. p[1], "г" .. p[1], "г" .. p[2], "е" .. p[1], "е" .. p[2], "к" .. p[1], "н" .. p[1]}
},
}
m["alt"] = {
"Southern Altai",
1991779,
"trk-kkp",
"Cyrl",
translit = "Altai-translit",
sort_key = {
from = {"ј", "ё", "ҥ", "ӧ", "ӱ"},
to = {"д" .. p[1], "е" .. p[1], "н" .. p[1], "о" .. p[1], "у" .. p[1]}
},
}
m["alu"] = {
"'Are'are",
5160,
"poz-sls",
"Latn",
}
m["alw"] = {
"Alaba",
56652,
"cus-hec",
"Latn",
}
m["alx"] = {
"Amol",
3504260,
"paa-pal",
"Latn",
}
m["aly"] = {
"Alyawarr",
3327389,
"aus-rnd",
"Latn",
}
m["alz"] = {
"Alur",
56507,
"sdv-los",
"Latn",
}
m["ama"] = {
"Amanayé",
3508053,
"tup-gua",
"Latn",
}
m["amb"] = {
"Ambo",
3450142,
"nic-tvn",
"Latn",
}
m["amc"] = {
"Amahuaca",
2669150,
"sai-pan",
"Latn",
}
m["ame"] = {
"Yanesha'",
3088540,
"awd",
"Latn",
}
m["amf"] = {
"Hamer-Banna",
35764,
"omv-aro",
"Latn, Ethi",
sort_key = "amf-utilities"
}
m["amg"] = {
"Amurdag",
3360016,
"aus-wdj",
"Latn",
}
m["ami"] = {
"Amis",
35132,
"map",
"Latn",
}
m["amj"] = {
"Amdang",
28335,
"ssa-fur",
"Latn",
}
m["amk"] = {
"Ambai",
1875885,
"poz-hce",
"Latn",
}
m["aml"] = {
"War-Jaintia",
56321,
"aav-khs",
"Latn",
}
m["amm"] = {
"Ama",
3446626,
"paa-lma",
"Latn",
}
m["amn"] = {
"Amanab",
3327399,
"paa-war",
"Latn",
}
m["amo"] = {
"Amo",
34826,
"nic-kne",
"Latn",
}
m["amp"] = {
"Alamblak",
56688,
"paa-sep",
"Latn",
}
m["amq"] = {
"Amahai",
3327384,
"poz-cma",
"Latn",
}
m["amr"] = {
"Amarakaeri",
35128,
"sai-har",
"Latn",
}
m["ams"] = {
"Southern Amami Ōshima",
2840986,
"jpx-nry",
"Jpan",
translit = s["jpx-translit"],
display_text = s["jpx-displaytext"],
strip_diacritics = s["jpx-stripdiacritics"],
sort_key = s["jpx-sortkey"],
}
m["amt"] = {
"Amto",
56517,
"paa-amu",
"Latn",
}
m["amu"] = {
"Guerrero Amuzgo",
3501942,
"omq",
"Latn",
}
m["amv"] = {
"Ambelau",
2669214,
"poz-cma",
"Latn",
}
m["amw"] = {
"Western Neo-Aramaic",
34226,
"sem-arw",
"Armi, Syrc, Latn",
strip_diacritics = {
Syrc = "Syrc-stripdiacritics"
},
}
m["amx"] = {
"Anmatyerre",
10412317,
"aus-rnd",
"Latn",
}
m["amy"] = {
"Ami",
10408315,
"aus-dal",
"Latn",
}
m["amz"] = {
"Atampaya",
3446651,
"aus-pam",
"Latn",
}
m["ana"] = {
"Andaqui",
2846078,
nil,
"Latn",
}
m["anb"] = {
"Andoa",
2846171,
"sai-zap",
"Latn",
}
m["anc"] = {
"Ngas",
35999,
"cdc-wst",
"Latn",
}
m["and"] = {
"Ansus",
3513300,
"poz-hce",
"Latn",
}
m["ane"] = {
"Xârâcùù",
3571097,
"poz-cln",
"Latn",
}
m["anf"] = {
"Animere",
34783,
"alv-ktg",
"Latn",
}
m["ang"] = {
"Old English",
42365,
"gmw-ang",
"Latn, Runr",
translit = {
Runr = "Runr-translit"
},
strip_diacritics = {
Latn = {
remove_diacritics = c.acute .. c.circ .. c.macron .. c.breve .. c.dotabove .. c.diaer .. c.dotbelow,
from = {"[Ƿƿ]"},
to = {{
["Ƿ"] = "W", ["ƿ"] = "w",
}},
},
},
sort_key = {
Latn = {
remove_diacritics = c.acute .. c.circ .. c.macron .. c.breve .. c.dotabove .. c.diaer .. c.dotbelow,
from = {"[æƀꝺðꝼᵹȝłœꞃꞅꞇþꝥꝧƿ]"},
to = {{
["æ"] = "ae", ["ƀ"] = "b", ["ꝺ"] = "d", ["ð"] = "d" .. p[1], ["ꝼ"] = "f",
["ᵹ"] = "g", ["ȝ"] = "g" .. p[1], ["ł"] = "l", ["œ"] = "oe", ["ꞃ"] = "r",
["ꞅ"] = "s", ["ꞇ"] = "t", ["þ"] = "t" .. p[1], ["ꝥ"] = "t" .. p[1],
["ꝧ"] = "t" .. p[1], ["ƿ"] = "w",
}},
},
},
standard_chars = {
Latn = "AaÆæBbCcDdÐðEeFfGgHhIiLlMmNnOoŒœPpRrSsTtÞþUuWwXxYy◌̄ĒēǢǣ",
c.punc,
},
}
m["anh"] = {
"Nend",
6991554,
"ngf-wso",
"Latn",
}
m["ani"] = {
"Andi",
34849,
"cau-and",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
}
m["anj"] = {
"Anor",
56458,
"paa-aia",
"Latn",
}
m["ank"] = {
"Goemai",
35272,
"cdc-wst",
"Latn",
}
m["anl"] = {
"Anu",
4777679,
"sit-mru",
"Latn",
}
m["anm"] = {
"Anāl",
56235,
"tbq-kuk",
"Latn",
}
m["ann"] = {
"Obolo",
36614,
"nic-lcr",
"Latn",
}
m["ano"] = {
"Andoque",
2669225,
"qfa-iso",
"Latn",
}
m["anp"] = {
"Angika",
28378,
"inc-bih",
"Deva, Kthi",
translit = {
Deva = "hi-translit",
Kthi = "bho-Kthi-translit",
},
}
m["anq"] = {
"Jarawa",
2475526,
"qfa-ong",
"Latn",
}
m["anr"] = {
"Andh",
4754314,
"inc-sou",
"Deva",
}
m["ans"] = {
"Anserma",
3446613,
"sai-chc",
"Latn",
}
m["ant"] = {
"Antakarinya",
921304,
"aus-psw",
"Latn",
}
m["anu"] = {
"Anuak",
56677,
"sdv-lon",
"Latn",
}
m["anv"] = {
"Denya",
35187,
"nic-mam",
"Latn",
}
m["anw"] = {
"Anaang",
2845320,
"nic-ief",
"Latn",
}
m["anx"] = {
"Andra-Hus",
2846195,
"poz-aay",
"Latn",
}
m["any"] = {
"Anyi",
28395,
"alv-ctn",
"Latn",
}
m["anz"] = {
"Anem",
56512,
"qfa-dis", -- Papuan; might be an isolate or in a putative West New Britain family
"Latn",
}
m["aoa"] = {
"Angolar",
34994,
"crp",
"Latn",
ancestors = "pt",
}
m["aob"] = {
"Abom",
3446647,
"qfa-dis", -- Papuan; possibly a divergent Tirio language (Anim family), or a top-level TNG node
"Latn",
}
m["aoc"] = {
"Pemon",
10729616,
"sai-pem",
"Latn",
}
m["aod"] = {
"Andarum",
3507888,
"paa-ata",
"Latn",
}
m["aoe"] = {
"Angal Enen",
10951638,
"ngf-ank",
"Latn",
}
m["aof"] = {
"Bragat",
3507977,
"paa-pal",
"Latn",
}
m["aog"] = {
"Angoram",
56366, -- cf 6754745 for merged dialect
"paa-lse",
"Latn",
}
m["aoi"] = {
"Anindilyakwa",
2714654,
"aus-arn",
"Latn",
}
m["aoj"] = {
"Mufian",
3507881,
"paa-ara",
"Latn",
}
m["aok"] = {
"Arhö",
4790086,
"poz-cln",
"Latn",
}
m["aol"] = {
"Alorese",
3332062,
"poz",
"Latn",
}
m["aom"] = {
"Ömie",
8078975,
"ngf-koi",
"Latn",
}
m["aon"] = {
"Bumbita Arapesh",
3508044,
"paa-ara",
"Latn",
}
m["aor"] = {
"Aore",
12627129,
"poz-vnn",
"Latn",
}
m["aos"] = {
"Taikat",
7676018,
"paa-taa",
"Latn",
}
m["aot"] = {
"Atong (India)",
5646,
"tbq-bdg",
"Latn, Beng",
}
m["aou"] = {
"A'ou",
16109994,
"gio",
"Latn", -- also Hani?
}
m["aox"] = {
"Atorada",
3507932,
"awd",
"Latn",
}
m["aoz"] = {
"Uab Meto",
3441962,
"poz-tim",
"Latn",
}
m["apb"] = {
"Sa'a",
36294,
"poz-sls",
"Latn",
}
m["apc"] = {
"North Levantine Arabic",
22809485,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["apd"] = {
"Sudanese Arabic",
56573,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ape"] = {
"Bukiyip",
3507895,
"paa-ara",
"Latn",
}
m["apf"] = {
"Pahanan Agta",
7135432,
"phi",
"Latn",
}
m["apg"] = {
"Ampanang",
4748035,
"poz",
"Latn",
}
m["aph"] = {
"Athpare",
3449126,
"sit-kie",
"Deva, Latn",
}
m["api"] = {
"Apiaká",
3507941,
"tup-gua",
"Latn",
}
m["apj"] = {
"Jicarilla",
28277,
"apa",
"Latn",
}
m["apk"] = {
"Plains Apache",
27861,
"apa",
"Latn",
}
m["apl"] = {
"Lipan",
28269,
"apa",
"Latn",
}
m["apm"] = {
"Chiricahua",
13368,
"apa",
"Latn",
}
m["apn"] = {
"Apinayé",
2858311,
"sai-nje",
"Latn",
}
m["apo"] = {
"Ambul",
12627135,
"poz-ocw",
"Latn",
}
m["app"] = {
"Apma",
2669188,
"poz-vnn",
"Latn",
}
m["apq"] = {
"A-Pucikwar",
28466,
"qfa-adc",
"Latn",
}
m["apr"] = {
"Arop-Lokep",
2863482,
"poz-ocw",
"Latn",
}
m["aps"] = {
"Arop-Sissano",
12627242,
"poz-ocw",
"Latn",
}
m["apt"] = {
"Apatani",
56306,
"sit-tan",
"Latn",
}
m["apu"] = {
"Apurinã",
2859081,
"awd",
"Latn",
}
m["apv"] = {
"Alapmunte",
16110782,
"sai-nmk",
"Latn",
}
m["apw"] = {
"Western Apache",
28060,
"apa",
"Latn",
}
m["apx"] = {
"Aputai",
12473343,
"poz-tim",
"Latn",
}
m["apy"] = {
"Apalaí",
2736980,
"sai-gui",
"Latn",
}
m["apz"] = {
"Safeyoka",
7398693,
"ngf-woj",
"Latn",
}
m["aqc"] = {
"Archi",
34915,
"cau-lzg",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
sort_key = {
from = {
"ккъӏв", "ххьӏв", -- 5 chars
"гъӏв", "ёоӏ", "ккъӏ", "ккъв", "къӏв", "ллъв", "ххьӏ", "хъӏв", "хьӏв", "ццӏв", "ччӏв", -- 4 chars
"ааӏ", "гӏв", "гъӏ", "гъв", "гьв", "ееӏ", "ёӏ", "ёо", "ииӏ", "кӏв", "ккв", "ккъ", "къӏ", "къв", "кьв", "лӏв", "ллъ", "лъв", "льв", "ооӏ", "пӏв", "ппв", "ссв", "тӏв", "ттв", "ууӏ", "хӏв", "ххв", "хъӏ", "хъв", "хьӏ", "цӏв", "ццӏ", "ццв", "чӏв", "ччӏ", "ээӏ", "юуӏ", "яаӏ", -- 3 chars
"аӏ", "аа", "гӏ", "гв", "гъ", "гь", "дв", "еӏ", "ее", "ё", "жв", "зв", "иӏ", "ии", "кӏ", "кв", "кк", "къ", "кь", "лӏ", "лв", "лъ", "ль", "оӏ", "оо", "пӏ", "пв", "пп", "св", "сс", "тӏ", "тв", "тт", "уӏ", "уу", "фв", "хӏ", "хв", "хх", "хъ", "цӏ", "цв", "цц", "чӏ", "чв", "шв", "щв", "эӏ", "ээ", "юӏ", "юу", "яӏ", "яа" -- 2 chars
},
to = {
"к" .. p[8], "х" .. p[7],
"г" .. p[6], "е" .. p[7], "к" .. p[7], "к" .. p[9], "к" .. p[12], "л" .. p[5], "х" .. p[6], "х" .. p[10], "х" .. p[13], "ц" .. p[6], "ч" .. p[5],
"а" .. p[3], "г" .. p[2], "г" .. p[5], "г" .. p[7], "г" .. p[9], "е" .. p[3], "е" .. p[5], "е" .. p[6], "и" .. p[3], "к" .. p[2], "к" .. p[5], "к" .. p[6], "к" .. p[11], "к" .. p[13], "к" .. p[15], "л" .. p[2], "л" .. p[4], "л" .. p[7], "л" .. p[9], "о" .. p[3], "п" .. p[2], "п" .. p[5], "с" .. p[3], "т" .. p[2], "т" .. p[5], "у" .. p[3], "х" .. p[2], "х" .. p[5], "х" .. p[9], "х" .. p[11], "х" .. p[12], "ц" .. p[2], "ц" .. p[5], "ц" .. p[7], "ч" .. p[2], "ч" .. p[4], "э" .. p[3], "ю" .. p[3], "я" .. p[3],
"а" .. p[1], "а" .. p[2], "г" .. p[1], "г" .. p[3], "г" .. p[4], "г" .. p[8], "д" .. p[1], "е" .. p[1], "е" .. p[2], "е" .. p[4], "ж" .. p[1], "з" .. p[1], "и" .. p[1], "и" .. p[2], "к" .. p[1], "к" .. p[3], "к" .. p[4], "к" .. p[10], "к" .. p[14], "л" .. p[1], "л" .. p[3], "л" .. p[6], "л" .. p[8], "о" .. p[1], "о" .. p[2], "п" .. p[1], "п" .. p[3], "п" .. p[4], "с" .. p[1], "с" .. p[2], "т" .. p[1], "т" .. p[3], "т" .. p[4], "у" .. p[1], "у" .. p[2], "ф" .. p[1], "х" .. p[1], "х" .. p[3], "х" .. p[4], "х" .. p[8], "ц" .. p[1], "ц" .. p[3], "ц" .. p[4], "ч" .. p[1], "ч" .. p[3], "ш" .. p[1], "щ" .. p[1], "э" .. p[1], "э" .. p[2], "ю" .. p[1], "ю" .. p[2], "я" .. p[1], "я" .. p[2]
}
},
}
m["aqd"] = {
"Ampari Dogon",
4748057,
"nic-dgw",
"Latn",
}
m["aqg"] = {
"Arigidi",
34829,
"alv-von",
"Latn",
}
m["aqm"] = {
"Atohwaim",
11732297,
"paa-kay",
"Latn",
}
m["aqn"] = {
"Northern Alta",
7058116,
"phi",
"Latn",
}
m["aqp"] = {
"Atakapa",
10975683,
"qfa-iso",
"Latn",
}
m["aqr"] = {
"Arhâ",
4790085,
"poz-cln",
"Latn",
}
m["aqt"] = {
"Angaité",
15736037,
"sai-mas",
"Latn",
}
m["aqz"] = {
"Akuntsu",
4701960,
"tup",
"Latn",
}
m["arc"] = {
"Aramaic",
28602,
"sem-ara",
"Hebr, Armi, Syrc, Palm, Nbat, Phnx, Mand, Samr, Hatr, Elym",
translit = {
Armi = "Armi-translit",
Palm = "Palm-translit",
},
strip_diacritics = {
-- The first three were added by [[User:Wikitiki89]] in 2015 for use with Syriac, which has diacritics that look
-- like a diaeresis (syāmē) and macrons above and below (mṭalqānā); see Wikipedia [[w:Syriac alphabet]]. But
-- I don't know if they are actually represented using these diacritics.
Syrc = {remove_diacritics = c.macron .. c.diaer .. c.macronbelow .. u(0x0730) .. "-" .. u(0x0748)},
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
-- Samr strip_diacritics, sort_key in [[Module:scripts/data]]; previously no sort_key for Samr, presumably a mistake
-- Phnx translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
m["ard"] = {
"Arabana",
3507959,
"aus-kar",
"Latn",
}
m["are"] = {
"Western Arrernte",
12645549,
"aus-rnd",
"Latn",
}
m["arh"] = {
"Arhuaco",
2640621,
"cba",
"Latn",
}
m["ari"] = {
"Arikara",
56539,
"cdd",
"Latn",
strip_diacritics = {remove_diacritics = c.acute},
}
m["arj"] = {
"Arapaso",
9627356,
"sai-tuc",
"Latn",
}
m["ark"] = {
"Arikapú",
3446640,
"sai-mje",
"Latn",
}
m["arl"] = {
"Arabela",
2591221,
"sai-zap",
"Latn",
}
m["arn"] = {
"Mapudungun",
33730,
"sai-ara",
"Latn",
}
m["aro"] = {
"Araona",
958414,
"sai-tac",
"Latn",
}
m["arp"] = {
"Arapaho",
56417,
"alg-ara",
"Latn",
}
m["arq"] = {
"Algerian Arabic",
56499,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["arr"] = {
"Arara-Karo",
35539,
"tup",
"Latn",
}
m["ars"] = {
"Najdi Arabic",
56574,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["aru"] = {
"Arua",
2746221,
"auf",
"Latn",
}
m["arv"] = {
"Arbore",
56883,
"cus-eas",
"Latn",
}
m["arw"] = {
"Lokono",
2655664,
"awd-taa",
"Latn",
}
m["arx"] = {
"Aruá",
3507907,
"tup",
"Latn",
}
m["ary"] = {
"Moroccan Arabic",
56426,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["arz"] = {
"Egyptian Arabic",
29919,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["asa"] = {
"Pare",
36403,
"bnt-par",
"Latn",
}
m["asb"] = {
"Assiniboine",
2591288,
"sio-dkt",
"Latn",
}
m["asc"] = {
"Casuarina Coast Asmat",
11732046,
"ngf-asm",
"Latn",
}
m["ase"] = {
"American Sign Language",
14759,
"sgn-asl",
"Sgnw",
}
m["asf"] = {
"Auslan",
29525,
"sgn",
"Latn", -- when documented
}
m["asg"] = {
"Cishingini",
35199,
"nic-kam",
"Latn",
}
m["ash"] = {
"Abishira",
2871740,
"qfa-dis", -- extinct, poorly documented; isolate or in a proposed Tequiraca-Canichana family by Kaufman (1994)
"Latn",
}
m["asi"] = {
"Buruwai",
5001031,
"ngf-sab",
"Latn",
}
m["asj"] = {
"Nsari",
36418,
"nic-bbe",
"Latn",
}
m["ask"] = {
"Ashkun",
29379,
"nur-sou",
"Arab, Latn",
}
m["asl"] = {
"Asilulu",
12473347,
"poz-cma",
"Latn",
}
m["asn"] = {
"Xingú Asuriní",
8044571,
"tup-gua",
"Latn",
}
m["aso"] = {
"Dano",
5220979,
"ngf-gah",
"Latn",
}
m["asp"] = {
"Algerian Sign Language",
3135421,
"sgn",
}
m["asq"] = {
"Austrian Sign Language",
36668,
"sgn",
"Latn", -- when documented
}
m["asr"] = {
"Asuri",
3504321,
"mun",
"Latn", -- when documented
}
m["ass"] = {
"Ipulo",
35408,
"nic-tvc",
"Latn",
}
m["ast"] = {
"Asturian",
29507,
"roa-asl",
"Latn",
}
m["asu"] = {
"Tocantins Asurini",
32041490,
"tup-gua",
"Latn",
}
m["asv"] = {
"Asoa",
56296,
"csu-maa",
"Latn",
}
m["asw"] = {
"Australian Aboriginal Sign Language",
955216,
"sgn",
"Latn", -- when documented
}
m["asx"] = {
"Muratayak",
11732766,
"ngf-war",
"Latn",
}
m["asy"] = {
"Yaosakor Asmat",
16113158,
"ngf-asm",
"Latn",
}
m["asz"] = {
"As",
2866218,
"poz-hce",
"Latn",
}
m["ata"] = {
"Pele-Ata",
56511,
"qfa-dis", -- Papuan; possibly in a putative West New Britain family, or an isolate
"Latn",
}
m["atb"] = {
"Zaiwa",
56594,
"tbq-brm",
"Latn, Lisu", -- also Hani?
-- Lisu translit, sort_key in [[Module:scripts/data]]
}
m["atc"] = {
"Atsahuaca",
4817730,
"sai-pan",
"Latn",
}
m["atd"] = {
"Ata Manobo",
12627315,
"mno",
"Latn",
}
m["ate"] = {
"Atemble",
4813055,
"ngf-wso",
"Latn",
}
m["atg"] = {
"Okpela",
7082551,
"alv-yek",
"Latn",
}
m["ati"] = {
"Attié",
34844,
"alv-lag",
"Latn",
}
m["atj"] = {
"Atikamekw",
56590,
"alg",
"Latn",
ancestors = "cr",
}
m["atk"] = {
"Ati",
3217458,
"phi",
"Latn",
}
m["atl"] = {
"Mount Iraya Agta",
6921430,
"phi",
"Latn",
}
m["atm"] = {
"Ata",
4812603,
"phi",
"Latn",
}
m["ato"] = {
"Atong (Cameroon)",
34824,
"nic-grs",
"Latn",
}
m["atp"] = {
"Pudtol Atta",
12640726,
"phi",
"Latn",
}
m["atq"] = {
"Aralle-Tabulahan",
4783889,
"poz-ssw",
"Latn",
}
m["atr"] = {
"Waimiri-Atroari",
56865,
"sai-car",
"Latn",
}
m["ats"] = {
"Gros Ventre",
56628,
"alg-ara",
"Latn",
}
m["att"] = {
"Pamplona Atta",
12639245,
"phi",
"Latn",
}
m["atu"] = {
"Reel",
7306882,
"sdv-dnu",
"Latn",
}
m["atv"] = {
"Northern Altai",
2640863,
"trk-ssb",
"Cyrl",
translit = "Altai-translit",
}
m["atw"] = {
"Atsugewi",
56718,
"nai-pal",
"Latn",
}
m["atx"] = {
"Arutani",
56609,
nil,
"Latn",
}
m["aty"] = {
"Aneityum",
2379113,
"poz-vns",
"Latn",
}
m["atz"] = {
"Arta",
3508067,
"phi",
"Latn",
}
m["aua"] = {
"Asumboa",
4811870,
"poz-tem",
"Latn",
}
m["aub"] = {
"Alugu",
12626798,
"tbq-urp",
"Latn", -- also Hani?
}
m["auc"] = {
"Huaorani",
758570,
"qfa-iso",
"Latn",
}
m["aud"] = {
"Anuta",
35326,
"poz-pnp",
"Latn",
}
m["aug"] = {
"Aguna",
34733,
"alv-gbe",
"Latn",
}
m["auh"] = {
"Aushi",
2872082,
"bnt-sbi",
"Latn",
}
m["aui"] = {
"Anuki",
3508132,
"poz-ocw",
"Latn",
}
m["auj"] = {
"Awjila",
56398,
"ber",
"Latn, Arab, Tfng",
}
m["auk"] = {
"Heyo",
3504295,
"paa-hya",
"Latn",
}
m["aul"] = {
"Aulua",
427300,
"poz-vnc",
"Latn",
}
m["aum"] = {
"Asu",
34798,
"alv-ngb",
"Latn",
}
m["aun"] = {
"Molmo One",
12637224,
"paa-trr",
"Latn",
}
m["auo"] = {
"Auyokawa",
56247,
"cdc-wst",
"Latn",
}
m["aup"] = {
"Makayam",
6738863,
"paa-tir",
"Latn",
}
m["auq"] = {
"Anus",
23855,
"poz-ocw",
"Latn",
}
m["aur"] = {
"Aruek",
3504279,
"paa-kom",
"Latn",
}
m["aut"] = {
"Austral",
2669261,
"poz-pep",
"Latn",
}
m["auu"] = {
"Auye",
4827334,
"ngf-pan",
"Latn",
}
m["auw"] = {
"Awyi",
3513326,
"paa-taa",
"Latn",
}
m["aux"] = {
"Aurá",
3507995,
"tup-gua",
"Latn",
}
m["auy"] = {
"Auyana",
2873211,
"ngf-gau",
"Latn",
}
m["auz"] = {
"Uzbeki Arabic",
3399507,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["avb"] = {
"Avau",
12627412,
"poz-ocw",
"Latn",
}
m["avd"] = {
"Alviri-Vidari",
3327357,
"xme",
"Arab",
ancestors = "xme-mid",
}
m["avi"] = {
"Avikam",
34840,
"alv-lag",
"Latn",
}
m["avk"] = {
"Kotava",
1377116,
"art",
"Latn",
type = "appendix-constructed",
}
m["avm"] = {
"Angkamuthi",
62603022,
"aus-pmn",
"Latn",
}
m["avn"] = {
"Avatime",
34796,
"alv-ktg",
"Latn",
}
-- avo Agavotaguerra retired
m["avs"] = {
"Aushiri",
3409318,
"sai-zap",
"Latn",
}
m["avt"] = {
"Au",
3446608,
"paa-wap",
"Latn",
}
m["avu"] = {
"Avokaya",
56685,
"csu-mma",
"Latn",
}
m["avv"] = {
"Avá-Canoeiro",
4829584,
"tup-gua",
"Latn",
}
m["awa"] = {
"Awadhi",
29579,
"inc-hie",
"Deva, Kthi, Aran",
translit = {
Deva = "hi-translit"
},
}
m["awb"] = {
"Awa (New Guinea)",
2874650,
"ngf-gau",
"Latn",
}
m["awc"] = {
"Cicipu",
35193,
"nic-kam",
"Latn",
}
m["awe"] = {
"Awetí",
4830038,
"tup",
"Latn",
}
m["awg"] = {
"Anguthimri",
4764288,
"aus-pam",
"Latn",
}
m["awh"] = {
"Awbono",
3446684,
"paa-baa",
"Latn",
}
m["awi"] = {
"Aekyom",
3399691,
"paa-kae",
"Latn",
}
m["awk"] = {
"Awabakal",
3449138,
"aus-pam",
"Latn",
}
m["awm"] = {
"Arawum",
4784537,
"ngf-rai",
"Latn",
}
m["awn"] = {
"Awngi",
34934,
"cus-cen",
"Ethi",
}
m["awo"] = {
"Awak",
3446643,
"alv-wjk",
"Latn",
}
m["awr"] = {
"Awera",
56379,
"paa-flp",
"Latn",
}
m["aws"] = {
"South Awyu",
12633986,
"ngf-awy",
"Latn",
}
m["awt"] = {
"Araweté",
4784535,
"tup-gua",
"Latn",
}
m["awu"] = {
"Central Awyu",
12628801,
"ngf-awy",
"Latn",
}
m["awv"] = {
"Jair Awyu",
16110177,
"ngf-awy",
"Latn",
}
m["aww"] = {
"Awun",
56369,
"paa-sep",
"Latn",
}
m["awx"] = {
"Awara",
2874670,
"ngf-waa",
"Latn",
}
m["awy"] = {
"Edera Awyu",
12630425,
"ngf-awy",
"Latn",
}
m["axb"] = {
"Abipón",
11252539,
"sai-guc",
"Latn",
}
m["axe"] = {
"Ayerrerenge",
16112737,
"aus-pam",
"Latn",
}
m["axg"] = {
"Arára (Mato Grosso)",
3446660,
nil,
"Latn",
}
m["axk"] = {
"Aka (Central Africa)",
11010149,
"bnt-ngn",
"Latn",
}
m["axl"] = {
"Lower Southern Aranda",
6693295,
"aus-rnd",
"Latn",
}
m["axm"] = {
"Middle Armenian",
4438498,
"hyx",
"Armn",
ancestors = "xcl",
-- Armn translit in [[Module:scripts/data]]
override_translit = true,
strip_diacritics = {
remove_diacritics = "՞՜՛՟",
from = {"եւ", "ՙ", "՚"},
to = {"և", "ʻ", "’"}
}
}
m["axx"] = {
"Xârâgurè",
8045635,
"poz-cln",
"Latn",
}
m["aya"] = {
"Awar",
56876,
"paa-baw",
"Latn",
}
m["ayb"] = {
"Ayizo",
34841,
"alv-pph",
"Latn",
}
m["ayd"] = {
"Ayabadhu",
3509164,
"aus-pmn",
"Latn",
}
m["aye"] = {
"Ayere",
34788,
"alv-aah",
"Latn",
}
m["ayg"] = {
"Nyanga (Togo)",
35446,
"alv-gng",
"Latn",
}
m["ayi"] = {
"Leyigha",
3914492,
"nic-uce",
"Latn",
}
m["ayk"] = {
"Akuku",
3450179,
"alv-nwd",
"Latn",
}
m["ayl"] = {
"Libyan Arabic",
56503,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ayn"] = {
"Yemeni Arabic",
1686766,
"sem-arb",
"Arab, Hebr",
strip_diacritics = {
Arab = "ar-stripdiacritics",
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["ayo"] = {
"Ayoreo",
56634,
"sai-zam",
"Latn",
}
m["ayp"] = {
"North Mesopotamian Arabic",
56577,
"sem-arb",
"Arab",
ancestors = "acm",
strip_diacritics = "ar-stripdiacritics",
}
m["ayq"] = {
"Ayi",
56449,
"paa-sep",
"Latn",
}
m["ays"] = {
"Sorsogon Ayta",
7563752,
"phi",
"Latn",
}
m["ayt"] = {
"Bataan Ayta",
4921648,
"phi",
"Latn",
}
m["ayu"] = {
"Ayu",
34786,
"alv",
"Latn",
}
-- ayy deleted and removed from ISO; per the removal request, "no linguistic data exists for any [Ayta] language that the
-- ancestors of this group might have once spoken. And thus, there is no evidence that this group ever had a language
-- distinct from any other Philippine language." [Lobel]
m["ayz"] = {
"Maybrat",
4830892,
"paa-may",
-- either an isolate; grouped with Abun and the West Bird's Head family; or in the putative West Papuan family
"Latn",
}
m["aza"] = {
"Azha",
4832486,
"tbq-axi",
"Latn",
}
m["azd"] = {
"Eastern Durango Nahuatl",
16115449,
"azc-dur",
"Latn",
}
m["azg"] = {
"San Pedro Amuzgos Amuzgo",
35092,
"omq",
"Latn",
}
m["azm"] = {
"Ipalapa Amuzgo",
12633013,
"omq",
"Latn",
}
m["azn"] = {
"Western Durango Nahuatl",
12645553,
"azc-dur",
"Latn",
}
m["azo"] = {
"Awing",
34856,
"nic-nge",
"Latn",
}
m["azt"] = {
"Faire Atta",
12630884,
"phi",
"Latn",
}
m["azz"] = {
"Highland Puebla Nahuatl",
12953754,
"azc-nah",
"Latn",
}
return require("Module:languages").finalizeData(m, "language")
30vfuixy3udt4pq0rygc65jk98tw17j
54952
54941
2026-09-30T03:20:26Z
Deadend0914
7211
54952
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["aaa"] = {
"Ghotuo",
35463,
"alv-yek",
"Latn",
}
m["aab"] = {
"Alumu-Tesu",
35034,
"nic-alu",
"Latn",
}
m["aac"] = {
"Ari",
1811224,
"ngf-gsu",
"Latn",
}
m["aad"] = {
"Amal",
56708,
"paa-sep",
"Latn",
}
-- "aae" is treated as "sq", see [[WT:LT]]
m["aaf"] = {
"Aranadan",
3507928,
"dra-mal",
"Mlym",
-- Mlym translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
m["aag"] = {
"Ambrak",
4741706,
"paa-pal",
"Latn",
}
m["aah"] = {
"Abu'",
4670715,
"paa-ara",
"Latn",
}
m["aai"] = {
"Arifama-Miniafia",
4790560,
"poz-ocw",
"Latn",
}
m["aak"] = {
"Ankave",
3446690,
"ngf-ata",
"Latn",
}
m["aal"] = {
"Afade",
56434,
"cdc-cbm",
"Latn",
}
m["aan"] = {
"Anambé",
3507873,
"tup-gua",
"Latn",
}
m["aap"] = {
"Arára (Pará)",
56807,
"sai-pek",
"Latn",
}
m["aaq"] = {
"Penobscot",
3515185,
"alg-abp",
"Latn",
}
m["aas"] = {
"Aasax",
56620,
"cus-sou",
"Latn",
}
-- "aat" is treated as "sq", see [[WT:LT]]
m["aau"] = {
"Abau",
3073568,
"paa-sep",
"Latn",
}
m["aaw"] = {
"Solong",
7558834,
"poz-ocw",
"Latn",
}
m["aax"] = {
"Upper Mandobo",
12636156,
"ngf-dum",
"Latn",
}
m["aaz"] = {
"Amarasi",
4740192,
"poz-tim",
"Latn",
}
m["aba"] = {
"Abé",
34833,
"alv-lag",
"Latn",
}
m["abb"] = {
"Bankon",
34860,
"bnt-bsa",
"Latn",
}
m["abc"] = {
"Ambala Ayta",
3448896,
"phi",
"Latn",
}
m["abd"] = {
"Camarines Norte Agta",
3399682,
"phi",
"Latn",
}
m["abe"] = {
"Abenaki",
17502788,
"alg-abp",
"Latn",
}
m["abf"] = {
"Abai Sungai",
4663287,
"poz-san",
"Latn",
}
m["abg"] = {
"Abaga",
3507954,
"ngf-kya",
"Latn",
}
m["abh"] = {
"Tajiki Arabic",
56833,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["abi"] = {
"Abidji",
34781,
"alv-lag",
"Latn",
}
m["abj"] = {
"Aka-Bea",
2356391,
"qfa-ads",
"Latn",
}
m["abl"] = {
"Abung",
49215,
"poz-lgx",
"Latn",
}
m["abm"] = {
"Abanyom",
7502,
"nic-eko",
"Latn",
}
m["abn"] = {
"Abua",
34835,
"nic-cde",
"Latn",
}
m["abo"] = {
"Abon",
35121,
"nic-tvn",
"Latn",
}
m["abp"] = {
"Abenlen Ayta",
3436621,
"phi",
"Latn",
}
m["abq"] = {
"Abaza",
27567,
"cau-abz",
"Cyrl, Latn",
translit = {
Cyrl = "abq-translit"
},
override_translit = true,
display_text = {
Cyrl = s["cau-Cyrl-displaytext"]
},
strip_diacritics = {
Cyrl = s["cau-Cyrl-stripdiacritics"],
Latn = s["cau-Latn-stripdiacritics"],
},
sort_key = {
Cyrl = {
from = {
"гъв", "гъь", "гӏв", "джв", "джь", "къв", "къь", "кӏв", "кӏь", "хъв", "хӏв", "чӏв", -- 3 chars
"гв", "гъ", "гь", "гӏ", "дж", "дз", "ё", "жв", "жь", "кв", "къ", "кь", "кӏ", "ль", "лӏ", "пӏ", "тл", "тш", "тӏ", "фӏ", "хв", "хъ", "хь", "хӏ", "цӏ", "чв", "чӏ", "шв", "шӏ" -- 2 chars
},
to = {
"г" .. p[3], "г" .. p[4], "г" .. p[7], "д" .. p[2], "д" .. p[3], "к" .. p[3], "к" .. p[4], "к" .. p[7], "к" .. p[8], "х" .. p[3], "х" .. p[6], "ч" .. p[3],
"г" .. p[1], "г" .. p[2], "г" .. p[5], "г" .. p[6], "д" .. p[1], "д" .. p[4], "е" .. p[1], "ж" .. p[1], "ж" .. p[2], "к" .. p[1], "к" .. p[2], "к" .. p[5], "к" .. p[6], "л" .. p[1], "л" .. p[2], "п" .. p[1], "т" .. p[1], "т" .. p[2], "т" .. p[3], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "х" .. p[5], "ц" .. p[1], "ч" .. p[1], "ч" .. p[2], "ш" .. p[1], "ш" .. p[2]
}
},
},
}
-- "abr" Abron is treated as "ak" Akan, see [[WT:LT]]
m["abs"] = {
"Ambonese Malay",
3124354,
"crp",
"Latn",
ancestors = "ms",
}
m["abt"] = {
"Ambulas",
3508015,
"paa-nnd",
"Latn",
}
m["abu"] = {
"Abure",
34767,
"alv-ptn",
"Latn",
}
m["abv"] = {
"Baharna Arabic",
56576,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["abw"] = {
"Pal",
7126121,
"ngf-omo",
"Latn",
}
m["abx"] = {
"Inabaknon",
2820163,
"poz-sbj",
"Latn",
}
m["aby"] = {
"Aneme Wake",
3508107,
"ngf-yar",
"Latn",
}
m["abz"] = {
"Abui",
2822110,
"paa-alp",
"Latn",
}
m["aca"] = {
"Achagua",
2822982,
"awd",
"Latn",
}
m["acb"] = {
"Áncá",
11130787,
"nic-mom",
"Latn",
}
m["acd"] = {
"Gikyode",
35256,
"alv-gng",
"Latn",
}
m["ace"] = {
"Acehnese",
27683,
"cmc",
"Latn, Arab",
standard_chars = {
Latn = "AaBbCcDdEeÉéÈèËëFfGgHhIiJjKkLlMmNnOoÔôÖöPpQqRrSsTtUuVvWwXxYyZz", -- current orthography (not yet add Arab)
c.punc
},
}
m["ach"] = {
"Acholi",
34926,
"sdv-los",
"Latn",
}
m["aci"] = {
"Aka-Cari",
2670418,
"qfa-adn",
"Latn",
}
m["ack"] = {
"Aka-Kora",
3433680,
"qfa-adn",
"Latn",
}
m["acl"] = {
"Akar-Bale",
3436825,
"qfa-ads",
"Latn",
}
m["acm"] = {
"Iraqi Arabic",
56232,
"sem-arb",
"Arab, Hebr",
strip_diacritics = {
Arab = "ar-stripdiacritics",
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["acn"] = {
"Achang",
56582,
"tbq-brm",
"Latn",
}
m["acp"] = {
"Eastern Acipa",
5329945,
"nic-kmk",
"Latn",
}
m["acr"] = {
"Achi",
34774,
"myn",
"Latn",
}
m["acs"] = {
"Acroá",
2829146,
"sai-cje",
"Latn",
}
m["acu"] = {
"Achuar",
2823170,
"sai-jiv",
"Latn",
}
m["acv"] = {
"Achumawi",
56661,
"nai-pal",
"Latn",
}
m["acw"] = {
"Hijazi Arabic",
56608,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["acx"] = {
"Omani Arabic",
56630,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["acy"] = {
"Cypriot Arabic",
56416,
"sem-arb",
"Latn, Grek",
ancestors = "acm",
strip_diacritics = {
Latn = {remove_diacritics = c.grave .. c.acute .. c.breve},
},
-- Grek display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
standard_chars = {
Latn = "AaBbCcDdΔδEeFfGgĠġĊċIiJjKkLlMmNnOoPpΘθRrSsTtUuVvWwXxYyZzŞş",
c.punc
},
}
m["acz"] = {
"Acheron",
34769,
"alv-tal",
"Latn",
}
m["ada"] = {
"Adangme",
35141,
"alv-gda",
"Latn",
}
m["adb"] = {
"Atauran",
125421255,
"poz-cet",
"Latn",
}
m["add"] = {
"Dzodinka",
35266,
"nic-nka",
"Latn",
}
m["ade"] = {
"Adele",
27740,
"alv-ntg",
"Latn",
}
m["adf"] = {
"Dhofari Arabic",
56565,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["adg"] = {
"Andegerebinha",
3508123,
"aus-rnd",
"Latn",
}
m["adh"] = {
"Adhola",
1971400,
"sdv-los",
"Latn",
}
m["adi"] = {
"Adi",
56440,
"sit-tan",
"Latn",
}
m["adj"] = {
"Adioukrou",
34738,
"alv-lag",
"Latn",
}
m["adl"] = {
"Galo",
2857892,
"sit-tan",
"Latn",
}
m["adn"] = {
"Adang",
3398276,
"paa-alp",
"Latn",
}
m["ado"] = {
"Abu",
56659,
"paa-por",
"Latn",
}
m["adp"] = {
"Adap",
3512402,
"sit-tib",
"Tibt",
ancestors = "dz",
override_translit = true,
-- Tibt translit, display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["adq"] = {
"Adangbe",
34730,
"alv-gda",
"Latn",
ancestors = "ada",
}
m["adr"] = {
"Adonara",
4684505,
"poz-cet",
"Latn",
}
m["ads"] = {
"Adamorobe Sign Language",
27709,
"sgn",
"Latn", -- when documented
}
m["adt"] = {
"Adnyamathanha",
2225391,
"aus-psw",
"Latn",
}
m["adu"] = {
"Aduge",
34734,
"alv-nwd",
"Latn",
ancestors = "opa",
}
m["adw"] = {
"Amondawa",
12626847,
"tup-gua",
"Latn",
}
m["ady"] = {
"West Circassian",
27776,
"cau-cir",
"Cyrl, Latn, Arab",
translit = {
Cyrl = "cau-cir-translit",
Arab = "ar-translit",
},
override_translit = true,
display_text = {
Cyrl = s["cau-Cyrl-displaytext"]
},
strip_diacritics = {
Cyrl = s["cau-Cyrl-stripdiacritics"],
Latn = s["cau-Latn-stripdiacritics"],
},
sort_key = {
Cyrl = {
from = {
"кхъу", "къӏу", -- 4 chars
"гъу", "джу", "дзу", "жъу", "къу", "кхъ", "къӏ", "кӏу", "кӏь", "лъу", "лӏу", "пӏу", "сӏу", "тӏу", "фӏу", "хъу", "цӏу", "чъу", "чӏу", "шъу", "шӏу", "щӏу", -- 3 chars
"гу", "гъ", "гь", "дж", "дз", "ё", "жъ", "жь", "ку", "къ", "кь", "кӏ", "лъ", "ль", "лӏ", "пӏ", "сӏ", "тӏ", "фӏ", "ху", "хъ", "хь", "цу", "цӏ", "чу", "чъ", "чӏ", "шъ", "шӏ", "щӏ", "ӏу", "ӏь" -- 2 chars
},
to = {
"к" .. p[5], "к" .. p[7],
"г" .. p[3], "д" .. p[2], "д" .. p[4], "ж" .. p[2], "к" .. p[3], "к" .. p[4], "к" .. p[6], "к" .. p[10], "к" .. p[11], "л" .. p[2], "л" .. p[5], "п" .. p[2], "с" .. p[2], "т" .. p[2], "ф" .. p[2], "х" .. p[3], "ц" .. p[3], "ч" .. p[3], "ч" .. p[5], "ш" .. p[2], "ш" .. p[4], "щ" .. p[2],
"г" .. p[1], "г" .. p[2], "г" .. p[4], "д" .. p[1], "д" .. p[3], "е" .. p[1], "ж" .. p[1], "ж" .. p[3], "к" .. p[1], "к" .. p[2], "к" .. p[8], "к" .. p[9], "л" .. p[1], "л" .. p[3], "л" .. p[4], "п" .. p[1], "с" .. p[1], "т" .. p[1], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "ц" .. p[1], "ц" .. p[2], "ч" .. p[1], "ч" .. p[2], "ч" .. p[4], "ш" .. p[1], "ш" .. p[3], "щ" .. p[1], "ӏ" .. p[1], "ӏ" .. p[2]
}
},
},
}
m["adz"] = {
"Adzera",
3327445,
"poz-ocw",
"Latn",
}
m["aea"] = {
"Areba",
3509129,
"aus-pam",
"Latn",
}
m["aeb"] = {
"Tunisian Arabic",
56240,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["aed"] = {
"Argentine Sign Language",
3322073,
"sgn",
"Latn", -- when documented
}
m["aee"] = {
"Northeast Pashayi",
12642198,
"inc-pas",
"Arab, Latn",
}
m["aek"] = {
"Haeke",
5638166,
"poz-cln",
"Latn",
}
m["ael"] = {
"Ambele",
34818,
"nic-grf",
"Latn",
}
m["aem"] = {
"Arem",
3507920,
"mkh-vie",
"Latn",
}
m["aen"] = {
"Armenian Sign Language",
3446604,
"sgn",
}
m["aeq"] = {
"Aer",
3246741,
"inc-wes",
"Arab",
}
m["aer"] = {
"Eastern Arrernte",
10728232,
"aus-rnd",
"Latn",
}
m["aes"] = {
"Alsea",
2395641,
nil,
"Latn",
}
m["aeu"] = {
"Akeu",
4700657,
"tbq-sil",
"Latn",
}
m["aew"] = {
"Ambakich",
56642,
"paa-eke",
"Latn",
}
m["aey"] = {
"Amele",
3508025,
"ngf-gum",
"Latn",
}
m["aez"] = {
"Aeka",
16110528,
"ngf-oro",
"Latn",
}
m["afb"] = {
"Gulf Arabic",
56385,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["afd"] = {
"Andai",
4753480,
"paa-arf",
"Latn",
}
m["afe"] = {
"Putukwam",
3914930,
"nic-ben",
"Latn",
}
m["afg"] = {
"Afghan Sign Language",
4689093,
"sgn",
}
m["afh"] = {
"Afrihili",
384707,
"art",
"Latn",
type = "appendix-constructed",
}
m["afi"] = {
"Akrukay",
57003,
"paa-tam",
"Latn",
}
m["afk"] = {
"Nanubae",
6964416,
"paa-arf",
"Latn",
}
m["afn"] = {
"Defaka",
35174,
"nic",
"Latn",
}
m["afo"] = {
"Eloyi",
3914066,
"nic-plt",
"Latn",
}
m["afp"] = {
"Tapei",
16887371,
"paa-arf",
"Latn",
}
m["afs"] = {
"Afro-Seminole Creole",
27867,
"crp",
"Latn",
ancestors = "en",
}
m["aft"] = {
"Afitti",
3400829,
"sdv-nyi",
"Latn",
}
m["afu"] = {
"Awutu",
34847,
"alv-gng",
"Latn",
}
m["afz"] = {
"Obokuitai",
7075258,
"paa-clp",
"Latn",
}
m["agb"] = {
"Legbo",
35584,
"nic-uce",
"Latn",
}
m["agc"] = {
"Agatu",
34732,
"alv-ido",
"Latn",
}
m["agd"] = {
"Agarabi",
3399642,
"ngf-gau",
"Latn",
}
m["age"] = {
"Angal",
10951553,
"ngf-ank",
"Latn",
}
m["agf"] = {
"Arguni",
12473346,
"poz-cet",
"Latn",
}
m["agg"] = {
"Angor",
3508100,
"paa-sng",
"Latn",
}
m["agh"] = {
"Ngelima",
7022266,
"bnt-bta",
"Latn",
}
m["agj"] = {
"Argobba",
29292,
"sem-eth",
"Ethi",
}
m["agk"] = {
"Isarog Agta",
6078982,
"phi",
"Latn",
}
m["agl"] = {
"Fembe",
372927,
"ngf-est",
"Latn",
}
m["agm"] = {
"Angaataha",
3508001,
"ngf-ang",
"Latn",
}
m["agn"] = {
"Agutaynen",
3399717,
"phi-kal",
"Latn",
}
m["ago"] = {
"Tainae",
7676186,
"ngf-taa",
"Latn",
}
m["agq"] = {
"Aghem",
34737,
"nic-rnw",
"Latn",
}
m["agr"] = {
"Aguaruna",
1526530,
"sai-jiv",
"Latn",
}
m["ags"] = {
"Esimbi",
35260,
"nic-bds",
"Latn",
}
m["agt"] = {
"Central Cagayan Agta",
5017296,
"phi",
"Latn",
}
m["agu"] = {
"Aguacateca",
35091,
"myn",
"Latn",
}
m["agv"] = {
"Remontado Agta",
3508085,
"phi",
"Latn",
}
m["agw"] = {
"Kahua",
3191906,
"poz-sls",
"Latn",
}
m["agx"] = {
"Aghul",
36498,
"cau-esm",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
sort_key = {
from = {"аь", "гъ", "гь", "гӏ", "дж", "ё", "къ", "кь", "кӏ", "оь", "пӏ", "тӏ", "уь", "хъ", "хь", "хӏ", "цӏ", "чӏ"},
to = {"а" .. p[1], "г" .. p[1], "г" .. p[2], "г" .. p[3], "д" .. p[1], "е" .. p[1], "к" .. p[1], "к" .. p[2], "к" .. p[3], "о" .. p[1], "п" .. p[1], "т" .. p[1], "у" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[3], "ц" .. p[1], "ч" .. p[1]}
},
}
m["agy"] = {
"Southern Alta",
7569611,
"phi",
"Latn",
}
m["agz"] = {
"Mount Iriga Agta",
6921432,
"phi",
"Latn",
}
m["aha"] = {
"Ahanta",
34729,
"alv-ctn",
"Latn",
}
m["ahb"] = {
"Axamb",
2874710,
"poz-vnc",
"Latn",
}
m["ahg"] = {
"Qimant",
35663,
"cus-cen",
"Latn",
}
m["ahh"] = {
"Aghu",
3436645,
"ngf-awy",
"Latn",
}
m["ahi"] = {
"Tiagba",
3400073,
"kro-aiz",
"Latn",
}
m["ahk"] = {
"Akha",
56643,
"tbq-han",
"Latn, Mymr, Thai",
sort_key = {
Thai = {
from = {"[%pๆ]", "[็-๎]", "([เแโใไ])([ก-ฮ])"},
to = {"", "", "%2%1"}
},
},
}
m["ahl"] = {
"Igo",
35412,
"alv-ktg",
"Latn",
}
m["ahm"] = {
"Mobu",
35967,
"kro-aiz",
"Latn",
}
m["ahn"] = {
"Àhàn",
34723,
"alv-aah",
"Latn",
}
m["aho"] = {
"Ahom",
34778,
"tai-swe",
"Ahom",
translit = "Ahom-translit",
}
m["ahp"] = {
"Apro",
34810,
"alv-kwa",
"Latn",
}
m["ahr"] = {
"Ahirani",
15549890,
"raj",
"Deva",
translit = "mr-translit",
}
m["ahs"] = {
"Ashe",
34823,
"nic-plc",
"Latn",
}
m["aht"] = {
"Ahtna",
21058,
"ath-nor",
"Latn",
}
m["aia"] = {
"Arosi",
2863483,
"poz-sls",
"Latn",
}
m["aib"] = {
"Äynu",
27927,
"qfa-mix",
"Arab, Latn",
ancestors = "ug, fa"
}
m["aic"] = {
"Ainbai",
3332149,
"paa-bew",
"Latn",
}
m["aid"] = {
"Alngith",
3279409,
"aus-pmn",
"Latn",
}
m["aie"] = {
"Amara",
2841180,
"poz-ocw",
"Latn",
}
m["aif"] = {
"Agi",
3331491,
"paa-wpa",
"Latn",
}
m["aig"] = {
"Antigua and Barbuda Creole English",
3244184,
"crp",
"Latn",
ancestors = "en",
}
m["aih"] = {
"Ai-Cham",
2827749,
"qfa-kms",
"Latn, Hani",
sort_key = {
Hani = "Hani-sortkey"
},
}
m["aii"] = {
"Assyrian Neo-Aramaic",
29440,
"sem-nna",
"Syrc",
translit = "aii-translit",
strip_diacritics = "Syrc-stripdiacritics",
}
m["aij"] = {
"Lishanid Noshan",
3436467,
"sem-nna",
"Hebr",
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["aik"] = {
"Ake",
34808,
"nic-pls",
"Latn",
}
m["ail"] = {
"Aimele",
3327418,
"ngf-bos",
"Latn",
}
m["aim"] = {
"Aimol",
4697175,
"tbq-kuk",
"Latn, Beng",
}
m["ain"] = {
"Ainu",
27969,
"qfa-ain",
"Kana, Latn, Cyrl",
sort_key = {
Kana = "Kana-sortkey"
},
}
m["aio"] = {
"Aiton",
3399725,
"tai-swe",
"Mymr",
translit = "aio-phk-translit",
display_text = s["aio-displaytext"],
strip_diacritics = s["aio-stripdiacritics"],
}
m["aip"] = {
"Burumakok",
5000984,
"ngf-wok",
"Latn",
}
m["air"] = {
"Airoran",
3321131,
"paa-saa",
"Latn",
}
m["ait"] = {
"Arikem",
3446679,
"tup",
"Latn",
}
m["aiw"] = {
"Aari",
7495,
"omv-aro",
"Latn",
}
m["aix"] = {
"Aighon",
3504287,
"poz-ocw",
"Latn",
}
m["aiy"] = {
"Ali",
34814,
"gba-eas",
"Latn",
}
m["aja"] = {
"Aja (East Africa)",
3237491,
"csu-bkr",
"Latn",
}
m["ajg"] = {
"Aja (West Africa)",
35035,
"alv-gbe",
"Latn",
}
m["aji"] = {
"Ajië",
2828867,
"poz-cln",
"Latn",
}
m["ajn"] = {
"Andajin",
16111302,
"aus-wor",
"Latn",
}
m["ajp"] = {
"South Levantine Arabic",
55633582,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ajs"] = {
"Algerian Jewish Sign Language",
5555709,
"sgn",
}
-- m["ajt"] Judeo-Tunisian Arabic now included in Tunisian Arabic
-- m["aju"] Judeo-Moroccan Arabic now included in Moroccan Arabic
m["ajw"] = {
"Ajawa",
56645,
"cdc-wst",
"Latn",
}
m["ajz"] = {
"Amri Karbi",
3508092,
"tbq-kuk",
"Latn",
ancestors = "mjw",
}
m["akb"] = {
"Angkola Batak",
2640686,
"btk",
"Latn, Batk",
}
m["akc"] = {
"Mpur",
3327139,
"qfa-iso", -- Papuan; based on Palmer (2018), Ethnologue and Glottolog
"Latn",
}
m["akd"] = {
"Ukpet-Ehom",
36618,
"nic-ucr",
"Latn",
}
m["ake"] = {
"Akawaio",
28059,
"sai-pem",
"Latn",
}
m["akf"] = {
"Akpa",
34801,
"alv-ido",
"Latn",
}
m["akg"] = {
"Anakalangu",
4750964,
"poz-cet",
"Latn",
}
m["akh"] = {
"Angal Heneng",
10950354,
"ngf-ank",
"Latn",
}
m["aki"] = {
"Aiome",
56735,
"paa-aia",
"Latn",
}
m["akj"] = {
"Jeru",
2919121,
"qfa-adn",
"Latn, Deva",
}
m["akk"] = {
"Akkadian",
35518,
"sem-eas",
"Xsux, Latn",
}
m["akl"] = {
"Aklanon",
8773,
"phi",
"Latn",
}
m["akm"] = {
"Aka-Bo",
35361,
"qfa-adn",
"Latn",
}
m["ako"] = {
"Akurio",
56650,
"sai-tar",
"Latn",
}
m["akp"] = {
"Siwu",
36470,
"alv-ntg",
"Latn",
}
m["akq"] = {
"Ak",
56654,
"paa-sep",
"Latn",
}
m["akr"] = {
"Araki",
2699882,
"poz-vnn",
"Latn",
}
m["aks"] = {
"Akaselem",
34817,
"nic-grm",
"Latn",
}
m["akt"] = {
"Akolet",
3330162,
"poz-ocw",
"Latn",
}
m["aku"] = {
"Akum",
34799,
"nic-ykb",
"Latn",
}
m["akv"] = {
"Akhvakh",
56423,
"cau-and",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
}
m["akw"] = {
"Akwa",
34802,
"bnt-mbo",
"Latn",
}
m["akx"] = {
"Aka-Kede",
3436816,
"qfa-adc",
"Latn",
}
m["aky"] = {
"Aka-Kol",
3436784,
"qfa-adc",
"Latn",
}
m["akz"] = {
"Alabama",
1815020,
"nai-mus",
"Latn",
}
m["ala"] = {
"Alago",
34813,
"alv-ido",
"Latn",
}
m["alc"] = {
"Kawésqar",
56544,
"aqa",
"Latn",
}
m["ald"] = {
"Alladian",
34837,
"alv-lag",
"Latn",
}
m["ale"] = {
"Aleut",
27210,
"esx",
"Latn, Cyrl",
}
m["alf"] = {
"Alege",
34815,
"nic-ben",
"Latn",
}
m["alh"] = {
"Alawa",
2147917,
"aus-gun",
"Latn",
}
m["ali"] = {
"Amaimon",
3327427,
"ngf-mad",
"Latn",
}
m["alj"] = {
"Alangan",
3327423,
"phi",
"Latn",
}
m["alk"] = {
"Alak",
2714690,
"mkh",
"Latn",
}
m["all"] = {
"Allar",
3393634,
"dra-mal",
"Mlym",
-- Mlym translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
-- "aln" is treated as "sq", see [[WT:LT]]
m["alm"] = {
"Amblong",
11022615,
"poz-vnn",
"Latn",
}
m["alo"] = {
"Larike-Wakasihu",
3217929,
"poz-cma",
"Latn",
}
m["alp"] = {
"Alune",
3327367,
"poz-cet",
"Latn",
}
m["alq"] = {
"Algonquin",
28092,
"alg",
"Latn, Cans",
ancestors = "oj",
}
m["alr"] = {
"Alutor",
28213,
"qfa-ckn",
"Cyrl",
strip_diacritics = {
from = {"['’]"},
to = {"ʼ"}
},
sort_key = {
from = {"вʼ", "гʼ", "ғ", "ә", "ё", "ӄ", "ӈ"},
to = {"в" .. p[1], "г" .. p[1], "г" .. p[2], "е" .. p[1], "е" .. p[2], "к" .. p[1], "н" .. p[1]}
},
}
m["alt"] = {
"Southern Altai",
1991779,
"trk-kkp",
"Cyrl",
translit = "Altai-translit",
sort_key = {
from = {"ј", "ё", "ҥ", "ӧ", "ӱ"},
to = {"д" .. p[1], "е" .. p[1], "н" .. p[1], "о" .. p[1], "у" .. p[1]}
},
}
m["alu"] = {
"'Are'are",
5160,
"poz-sls",
"Latn",
}
m["alw"] = {
"Alaba",
56652,
"cus-hec",
"Latn",
}
m["alx"] = {
"Amol",
3504260,
"paa-pal",
"Latn",
}
m["aly"] = {
"Alyawarr",
3327389,
"aus-rnd",
"Latn",
}
m["alz"] = {
"Alur",
56507,
"sdv-los",
"Latn",
}
m["ama"] = {
"Amanayé",
3508053,
"tup-gua",
"Latn",
}
m["amb"] = {
"Ambo",
3450142,
"nic-tvn",
"Latn",
}
m["amc"] = {
"Amahuaca",
2669150,
"sai-pan",
"Latn",
}
m["ame"] = {
"Yanesha'",
3088540,
"awd",
"Latn",
}
m["amf"] = {
"Hamer-Banna",
35764,
"omv-aro",
"Latn, Ethi",
sort_key = "amf-utilities"
}
m["amg"] = {
"Amurdag",
3360016,
"aus-wdj",
"Latn",
}
m["ami"] = {
"Amis",
35132,
"map",
"Latn",
}
m["amj"] = {
"Amdang",
28335,
"ssa-fur",
"Latn",
}
m["amk"] = {
"Ambai",
1875885,
"poz-hce",
"Latn",
}
m["aml"] = {
"War-Jaintia",
56321,
"aav-khs",
"Latn",
}
m["amm"] = {
"Ama",
3446626,
"paa-lma",
"Latn",
}
m["amn"] = {
"Amanab",
3327399,
"paa-war",
"Latn",
}
m["amo"] = {
"Amo",
34826,
"nic-kne",
"Latn",
}
m["amp"] = {
"Alamblak",
56688,
"paa-sep",
"Latn",
}
m["amq"] = {
"Amahai",
3327384,
"poz-cma",
"Latn",
}
m["amr"] = {
"Amarakaeri",
35128,
"sai-har",
"Latn",
}
m["ams"] = {
"Southern Amami Ōshima",
2840986,
"jpx-nry",
"Jpan",
translit = s["jpx-translit"],
display_text = s["jpx-displaytext"],
strip_diacritics = s["jpx-stripdiacritics"],
sort_key = s["jpx-sortkey"],
}
m["amt"] = {
"Amto",
56517,
"paa-amu",
"Latn",
}
m["amu"] = {
"Guerrero Amuzgo",
3501942,
"omq",
"Latn",
}
m["amv"] = {
"Ambelau",
2669214,
"poz-cma",
"Latn",
}
m["amw"] = {
"Western Neo-Aramaic",
34226,
"sem-arw",
"Armi, Syrc, Latn",
strip_diacritics = {
Syrc = "Syrc-stripdiacritics"
},
}
m["amx"] = {
"Anmatyerre",
10412317,
"aus-rnd",
"Latn",
}
m["amy"] = {
"Ami",
10408315,
"aus-dal",
"Latn",
}
m["amz"] = {
"Atampaya",
3446651,
"aus-pam",
"Latn",
}
m["ana"] = {
"Andaqui",
2846078,
nil,
"Latn",
}
m["anb"] = {
"Andoa",
2846171,
"sai-zap",
"Latn",
}
m["anc"] = {
"Ngas",
35999,
"cdc-wst",
"Latn",
}
m["and"] = {
"Ansus",
3513300,
"poz-hce",
"Latn",
}
m["ane"] = {
"Xârâcùù",
3571097,
"poz-cln",
"Latn",
}
m["anf"] = {
"Animere",
34783,
"alv-ktg",
"Latn",
}
m["ang"] = {
"Old English",
42365,
"gmw-ang",
"Latn, Runr",
translit = {
Runr = "Runr-translit"
},
strip_diacritics = {
Latn = {
remove_diacritics = c.acute .. c.circ .. c.macron .. c.breve .. c.dotabove .. c.diaer .. c.dotbelow,
from = {"[Ƿƿ]"},
to = {{
["Ƿ"] = "W", ["ƿ"] = "w",
}},
},
},
sort_key = {
Latn = {
remove_diacritics = c.acute .. c.circ .. c.macron .. c.breve .. c.dotabove .. c.diaer .. c.dotbelow,
from = {"[æƀꝺðꝼᵹȝłœꞃꞅꞇþꝥꝧƿ]"},
to = {{
["æ"] = "ae", ["ƀ"] = "b", ["ꝺ"] = "d", ["ð"] = "d" .. p[1], ["ꝼ"] = "f",
["ᵹ"] = "g", ["ȝ"] = "g" .. p[1], ["ł"] = "l", ["œ"] = "oe", ["ꞃ"] = "r",
["ꞅ"] = "s", ["ꞇ"] = "t", ["þ"] = "t" .. p[1], ["ꝥ"] = "t" .. p[1],
["ꝧ"] = "t" .. p[1], ["ƿ"] = "w",
}},
},
},
standard_chars = {
Latn = "AaÆæBbCcDdÐðEeFfGgHhIiLlMmNnOoŒœPpRrSsTtÞþUuWwXxYy◌̄ĒēǢǣĪī",
c.punc,
},
}
m["anh"] = {
"Nend",
6991554,
"ngf-wso",
"Latn",
}
m["ani"] = {
"Andi",
34849,
"cau-and",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
}
m["anj"] = {
"Anor",
56458,
"paa-aia",
"Latn",
}
m["ank"] = {
"Goemai",
35272,
"cdc-wst",
"Latn",
}
m["anl"] = {
"Anu",
4777679,
"sit-mru",
"Latn",
}
m["anm"] = {
"Anāl",
56235,
"tbq-kuk",
"Latn",
}
m["ann"] = {
"Obolo",
36614,
"nic-lcr",
"Latn",
}
m["ano"] = {
"Andoque",
2669225,
"qfa-iso",
"Latn",
}
m["anp"] = {
"Angika",
28378,
"inc-bih",
"Deva, Kthi",
translit = {
Deva = "hi-translit",
Kthi = "bho-Kthi-translit",
},
}
m["anq"] = {
"Jarawa",
2475526,
"qfa-ong",
"Latn",
}
m["anr"] = {
"Andh",
4754314,
"inc-sou",
"Deva",
}
m["ans"] = {
"Anserma",
3446613,
"sai-chc",
"Latn",
}
m["ant"] = {
"Antakarinya",
921304,
"aus-psw",
"Latn",
}
m["anu"] = {
"Anuak",
56677,
"sdv-lon",
"Latn",
}
m["anv"] = {
"Denya",
35187,
"nic-mam",
"Latn",
}
m["anw"] = {
"Anaang",
2845320,
"nic-ief",
"Latn",
}
m["anx"] = {
"Andra-Hus",
2846195,
"poz-aay",
"Latn",
}
m["any"] = {
"Anyi",
28395,
"alv-ctn",
"Latn",
}
m["anz"] = {
"Anem",
56512,
"qfa-dis", -- Papuan; might be an isolate or in a putative West New Britain family
"Latn",
}
m["aoa"] = {
"Angolar",
34994,
"crp",
"Latn",
ancestors = "pt",
}
m["aob"] = {
"Abom",
3446647,
"qfa-dis", -- Papuan; possibly a divergent Tirio language (Anim family), or a top-level TNG node
"Latn",
}
m["aoc"] = {
"Pemon",
10729616,
"sai-pem",
"Latn",
}
m["aod"] = {
"Andarum",
3507888,
"paa-ata",
"Latn",
}
m["aoe"] = {
"Angal Enen",
10951638,
"ngf-ank",
"Latn",
}
m["aof"] = {
"Bragat",
3507977,
"paa-pal",
"Latn",
}
m["aog"] = {
"Angoram",
56366, -- cf 6754745 for merged dialect
"paa-lse",
"Latn",
}
m["aoi"] = {
"Anindilyakwa",
2714654,
"aus-arn",
"Latn",
}
m["aoj"] = {
"Mufian",
3507881,
"paa-ara",
"Latn",
}
m["aok"] = {
"Arhö",
4790086,
"poz-cln",
"Latn",
}
m["aol"] = {
"Alorese",
3332062,
"poz",
"Latn",
}
m["aom"] = {
"Ömie",
8078975,
"ngf-koi",
"Latn",
}
m["aon"] = {
"Bumbita Arapesh",
3508044,
"paa-ara",
"Latn",
}
m["aor"] = {
"Aore",
12627129,
"poz-vnn",
"Latn",
}
m["aos"] = {
"Taikat",
7676018,
"paa-taa",
"Latn",
}
m["aot"] = {
"Atong (India)",
5646,
"tbq-bdg",
"Latn, Beng",
}
m["aou"] = {
"A'ou",
16109994,
"gio",
"Latn", -- also Hani?
}
m["aox"] = {
"Atorada",
3507932,
"awd",
"Latn",
}
m["aoz"] = {
"Uab Meto",
3441962,
"poz-tim",
"Latn",
}
m["apb"] = {
"Sa'a",
36294,
"poz-sls",
"Latn",
}
m["apc"] = {
"North Levantine Arabic",
22809485,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["apd"] = {
"Sudanese Arabic",
56573,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ape"] = {
"Bukiyip",
3507895,
"paa-ara",
"Latn",
}
m["apf"] = {
"Pahanan Agta",
7135432,
"phi",
"Latn",
}
m["apg"] = {
"Ampanang",
4748035,
"poz",
"Latn",
}
m["aph"] = {
"Athpare",
3449126,
"sit-kie",
"Deva, Latn",
}
m["api"] = {
"Apiaká",
3507941,
"tup-gua",
"Latn",
}
m["apj"] = {
"Jicarilla",
28277,
"apa",
"Latn",
}
m["apk"] = {
"Plains Apache",
27861,
"apa",
"Latn",
}
m["apl"] = {
"Lipan",
28269,
"apa",
"Latn",
}
m["apm"] = {
"Chiricahua",
13368,
"apa",
"Latn",
}
m["apn"] = {
"Apinayé",
2858311,
"sai-nje",
"Latn",
}
m["apo"] = {
"Ambul",
12627135,
"poz-ocw",
"Latn",
}
m["app"] = {
"Apma",
2669188,
"poz-vnn",
"Latn",
}
m["apq"] = {
"A-Pucikwar",
28466,
"qfa-adc",
"Latn",
}
m["apr"] = {
"Arop-Lokep",
2863482,
"poz-ocw",
"Latn",
}
m["aps"] = {
"Arop-Sissano",
12627242,
"poz-ocw",
"Latn",
}
m["apt"] = {
"Apatani",
56306,
"sit-tan",
"Latn",
}
m["apu"] = {
"Apurinã",
2859081,
"awd",
"Latn",
}
m["apv"] = {
"Alapmunte",
16110782,
"sai-nmk",
"Latn",
}
m["apw"] = {
"Western Apache",
28060,
"apa",
"Latn",
}
m["apx"] = {
"Aputai",
12473343,
"poz-tim",
"Latn",
}
m["apy"] = {
"Apalaí",
2736980,
"sai-gui",
"Latn",
}
m["apz"] = {
"Safeyoka",
7398693,
"ngf-woj",
"Latn",
}
m["aqc"] = {
"Archi",
34915,
"cau-lzg",
"Cyrl",
translit = "cau-nec-translit",
override_translit = true,
display_text = s["cau-Cyrl-displaytext"],
strip_diacritics = s["cau-Cyrl-stripdiacritics"],
sort_key = {
from = {
"ккъӏв", "ххьӏв", -- 5 chars
"гъӏв", "ёоӏ", "ккъӏ", "ккъв", "къӏв", "ллъв", "ххьӏ", "хъӏв", "хьӏв", "ццӏв", "ччӏв", -- 4 chars
"ааӏ", "гӏв", "гъӏ", "гъв", "гьв", "ееӏ", "ёӏ", "ёо", "ииӏ", "кӏв", "ккв", "ккъ", "къӏ", "къв", "кьв", "лӏв", "ллъ", "лъв", "льв", "ооӏ", "пӏв", "ппв", "ссв", "тӏв", "ттв", "ууӏ", "хӏв", "ххв", "хъӏ", "хъв", "хьӏ", "цӏв", "ццӏ", "ццв", "чӏв", "ччӏ", "ээӏ", "юуӏ", "яаӏ", -- 3 chars
"аӏ", "аа", "гӏ", "гв", "гъ", "гь", "дв", "еӏ", "ее", "ё", "жв", "зв", "иӏ", "ии", "кӏ", "кв", "кк", "къ", "кь", "лӏ", "лв", "лъ", "ль", "оӏ", "оо", "пӏ", "пв", "пп", "св", "сс", "тӏ", "тв", "тт", "уӏ", "уу", "фв", "хӏ", "хв", "хх", "хъ", "цӏ", "цв", "цц", "чӏ", "чв", "шв", "щв", "эӏ", "ээ", "юӏ", "юу", "яӏ", "яа" -- 2 chars
},
to = {
"к" .. p[8], "х" .. p[7],
"г" .. p[6], "е" .. p[7], "к" .. p[7], "к" .. p[9], "к" .. p[12], "л" .. p[5], "х" .. p[6], "х" .. p[10], "х" .. p[13], "ц" .. p[6], "ч" .. p[5],
"а" .. p[3], "г" .. p[2], "г" .. p[5], "г" .. p[7], "г" .. p[9], "е" .. p[3], "е" .. p[5], "е" .. p[6], "и" .. p[3], "к" .. p[2], "к" .. p[5], "к" .. p[6], "к" .. p[11], "к" .. p[13], "к" .. p[15], "л" .. p[2], "л" .. p[4], "л" .. p[7], "л" .. p[9], "о" .. p[3], "п" .. p[2], "п" .. p[5], "с" .. p[3], "т" .. p[2], "т" .. p[5], "у" .. p[3], "х" .. p[2], "х" .. p[5], "х" .. p[9], "х" .. p[11], "х" .. p[12], "ц" .. p[2], "ц" .. p[5], "ц" .. p[7], "ч" .. p[2], "ч" .. p[4], "э" .. p[3], "ю" .. p[3], "я" .. p[3],
"а" .. p[1], "а" .. p[2], "г" .. p[1], "г" .. p[3], "г" .. p[4], "г" .. p[8], "д" .. p[1], "е" .. p[1], "е" .. p[2], "е" .. p[4], "ж" .. p[1], "з" .. p[1], "и" .. p[1], "и" .. p[2], "к" .. p[1], "к" .. p[3], "к" .. p[4], "к" .. p[10], "к" .. p[14], "л" .. p[1], "л" .. p[3], "л" .. p[6], "л" .. p[8], "о" .. p[1], "о" .. p[2], "п" .. p[1], "п" .. p[3], "п" .. p[4], "с" .. p[1], "с" .. p[2], "т" .. p[1], "т" .. p[3], "т" .. p[4], "у" .. p[1], "у" .. p[2], "ф" .. p[1], "х" .. p[1], "х" .. p[3], "х" .. p[4], "х" .. p[8], "ц" .. p[1], "ц" .. p[3], "ц" .. p[4], "ч" .. p[1], "ч" .. p[3], "ш" .. p[1], "щ" .. p[1], "э" .. p[1], "э" .. p[2], "ю" .. p[1], "ю" .. p[2], "я" .. p[1], "я" .. p[2]
}
},
}
m["aqd"] = {
"Ampari Dogon",
4748057,
"nic-dgw",
"Latn",
}
m["aqg"] = {
"Arigidi",
34829,
"alv-von",
"Latn",
}
m["aqm"] = {
"Atohwaim",
11732297,
"paa-kay",
"Latn",
}
m["aqn"] = {
"Northern Alta",
7058116,
"phi",
"Latn",
}
m["aqp"] = {
"Atakapa",
10975683,
"qfa-iso",
"Latn",
}
m["aqr"] = {
"Arhâ",
4790085,
"poz-cln",
"Latn",
}
m["aqt"] = {
"Angaité",
15736037,
"sai-mas",
"Latn",
}
m["aqz"] = {
"Akuntsu",
4701960,
"tup",
"Latn",
}
m["arc"] = {
"Aramaic",
28602,
"sem-ara",
"Hebr, Armi, Syrc, Palm, Nbat, Phnx, Mand, Samr, Hatr, Elym",
translit = {
Armi = "Armi-translit",
Palm = "Palm-translit",
},
strip_diacritics = {
-- The first three were added by [[User:Wikitiki89]] in 2015 for use with Syriac, which has diacritics that look
-- like a diaeresis (syāmē) and macrons above and below (mṭalqānā); see Wikipedia [[w:Syriac alphabet]]. But
-- I don't know if they are actually represented using these diacritics.
Syrc = {remove_diacritics = c.macron .. c.diaer .. c.macronbelow .. u(0x0730) .. "-" .. u(0x0748)},
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
-- Samr strip_diacritics, sort_key in [[Module:scripts/data]]; previously no sort_key for Samr, presumably a mistake
-- Phnx translit in [[Module:scripts/data]] (NOTE: not present before, presumably an accidental omission)
}
m["ard"] = {
"Arabana",
3507959,
"aus-kar",
"Latn",
}
m["are"] = {
"Western Arrernte",
12645549,
"aus-rnd",
"Latn",
}
m["arh"] = {
"Arhuaco",
2640621,
"cba",
"Latn",
}
m["ari"] = {
"Arikara",
56539,
"cdd",
"Latn",
strip_diacritics = {remove_diacritics = c.acute},
}
m["arj"] = {
"Arapaso",
9627356,
"sai-tuc",
"Latn",
}
m["ark"] = {
"Arikapú",
3446640,
"sai-mje",
"Latn",
}
m["arl"] = {
"Arabela",
2591221,
"sai-zap",
"Latn",
}
m["arn"] = {
"Mapudungun",
33730,
"sai-ara",
"Latn",
}
m["aro"] = {
"Araona",
958414,
"sai-tac",
"Latn",
}
m["arp"] = {
"Arapaho",
56417,
"alg-ara",
"Latn",
}
m["arq"] = {
"Algerian Arabic",
56499,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["arr"] = {
"Arara-Karo",
35539,
"tup",
"Latn",
}
m["ars"] = {
"Najdi Arabic",
56574,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["aru"] = {
"Arua",
2746221,
"auf",
"Latn",
}
m["arv"] = {
"Arbore",
56883,
"cus-eas",
"Latn",
}
m["arw"] = {
"Lokono",
2655664,
"awd-taa",
"Latn",
}
m["arx"] = {
"Aruá",
3507907,
"tup",
"Latn",
}
m["ary"] = {
"Moroccan Arabic",
56426,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["arz"] = {
"Egyptian Arabic",
29919,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["asa"] = {
"Pare",
36403,
"bnt-par",
"Latn",
}
m["asb"] = {
"Assiniboine",
2591288,
"sio-dkt",
"Latn",
}
m["asc"] = {
"Casuarina Coast Asmat",
11732046,
"ngf-asm",
"Latn",
}
m["ase"] = {
"American Sign Language",
14759,
"sgn-asl",
"Sgnw",
}
m["asf"] = {
"Auslan",
29525,
"sgn",
"Latn", -- when documented
}
m["asg"] = {
"Cishingini",
35199,
"nic-kam",
"Latn",
}
m["ash"] = {
"Abishira",
2871740,
"qfa-dis", -- extinct, poorly documented; isolate or in a proposed Tequiraca-Canichana family by Kaufman (1994)
"Latn",
}
m["asi"] = {
"Buruwai",
5001031,
"ngf-sab",
"Latn",
}
m["asj"] = {
"Nsari",
36418,
"nic-bbe",
"Latn",
}
m["ask"] = {
"Ashkun",
29379,
"nur-sou",
"Arab, Latn",
}
m["asl"] = {
"Asilulu",
12473347,
"poz-cma",
"Latn",
}
m["asn"] = {
"Xingú Asuriní",
8044571,
"tup-gua",
"Latn",
}
m["aso"] = {
"Dano",
5220979,
"ngf-gah",
"Latn",
}
m["asp"] = {
"Algerian Sign Language",
3135421,
"sgn",
}
m["asq"] = {
"Austrian Sign Language",
36668,
"sgn",
"Latn", -- when documented
}
m["asr"] = {
"Asuri",
3504321,
"mun",
"Latn", -- when documented
}
m["ass"] = {
"Ipulo",
35408,
"nic-tvc",
"Latn",
}
m["ast"] = {
"Asturian",
29507,
"roa-asl",
"Latn",
}
m["asu"] = {
"Tocantins Asurini",
32041490,
"tup-gua",
"Latn",
}
m["asv"] = {
"Asoa",
56296,
"csu-maa",
"Latn",
}
m["asw"] = {
"Australian Aboriginal Sign Language",
955216,
"sgn",
"Latn", -- when documented
}
m["asx"] = {
"Muratayak",
11732766,
"ngf-war",
"Latn",
}
m["asy"] = {
"Yaosakor Asmat",
16113158,
"ngf-asm",
"Latn",
}
m["asz"] = {
"As",
2866218,
"poz-hce",
"Latn",
}
m["ata"] = {
"Pele-Ata",
56511,
"qfa-dis", -- Papuan; possibly in a putative West New Britain family, or an isolate
"Latn",
}
m["atb"] = {
"Zaiwa",
56594,
"tbq-brm",
"Latn, Lisu", -- also Hani?
-- Lisu translit, sort_key in [[Module:scripts/data]]
}
m["atc"] = {
"Atsahuaca",
4817730,
"sai-pan",
"Latn",
}
m["atd"] = {
"Ata Manobo",
12627315,
"mno",
"Latn",
}
m["ate"] = {
"Atemble",
4813055,
"ngf-wso",
"Latn",
}
m["atg"] = {
"Okpela",
7082551,
"alv-yek",
"Latn",
}
m["ati"] = {
"Attié",
34844,
"alv-lag",
"Latn",
}
m["atj"] = {
"Atikamekw",
56590,
"alg",
"Latn",
ancestors = "cr",
}
m["atk"] = {
"Ati",
3217458,
"phi",
"Latn",
}
m["atl"] = {
"Mount Iraya Agta",
6921430,
"phi",
"Latn",
}
m["atm"] = {
"Ata",
4812603,
"phi",
"Latn",
}
m["ato"] = {
"Atong (Cameroon)",
34824,
"nic-grs",
"Latn",
}
m["atp"] = {
"Pudtol Atta",
12640726,
"phi",
"Latn",
}
m["atq"] = {
"Aralle-Tabulahan",
4783889,
"poz-ssw",
"Latn",
}
m["atr"] = {
"Waimiri-Atroari",
56865,
"sai-car",
"Latn",
}
m["ats"] = {
"Gros Ventre",
56628,
"alg-ara",
"Latn",
}
m["att"] = {
"Pamplona Atta",
12639245,
"phi",
"Latn",
}
m["atu"] = {
"Reel",
7306882,
"sdv-dnu",
"Latn",
}
m["atv"] = {
"Northern Altai",
2640863,
"trk-ssb",
"Cyrl",
translit = "Altai-translit",
}
m["atw"] = {
"Atsugewi",
56718,
"nai-pal",
"Latn",
}
m["atx"] = {
"Arutani",
56609,
nil,
"Latn",
}
m["aty"] = {
"Aneityum",
2379113,
"poz-vns",
"Latn",
}
m["atz"] = {
"Arta",
3508067,
"phi",
"Latn",
}
m["aua"] = {
"Asumboa",
4811870,
"poz-tem",
"Latn",
}
m["aub"] = {
"Alugu",
12626798,
"tbq-urp",
"Latn", -- also Hani?
}
m["auc"] = {
"Huaorani",
758570,
"qfa-iso",
"Latn",
}
m["aud"] = {
"Anuta",
35326,
"poz-pnp",
"Latn",
}
m["aug"] = {
"Aguna",
34733,
"alv-gbe",
"Latn",
}
m["auh"] = {
"Aushi",
2872082,
"bnt-sbi",
"Latn",
}
m["aui"] = {
"Anuki",
3508132,
"poz-ocw",
"Latn",
}
m["auj"] = {
"Awjila",
56398,
"ber",
"Latn, Arab, Tfng",
}
m["auk"] = {
"Heyo",
3504295,
"paa-hya",
"Latn",
}
m["aul"] = {
"Aulua",
427300,
"poz-vnc",
"Latn",
}
m["aum"] = {
"Asu",
34798,
"alv-ngb",
"Latn",
}
m["aun"] = {
"Molmo One",
12637224,
"paa-trr",
"Latn",
}
m["auo"] = {
"Auyokawa",
56247,
"cdc-wst",
"Latn",
}
m["aup"] = {
"Makayam",
6738863,
"paa-tir",
"Latn",
}
m["auq"] = {
"Anus",
23855,
"poz-ocw",
"Latn",
}
m["aur"] = {
"Aruek",
3504279,
"paa-kom",
"Latn",
}
m["aut"] = {
"Austral",
2669261,
"poz-pep",
"Latn",
}
m["auu"] = {
"Auye",
4827334,
"ngf-pan",
"Latn",
}
m["auw"] = {
"Awyi",
3513326,
"paa-taa",
"Latn",
}
m["aux"] = {
"Aurá",
3507995,
"tup-gua",
"Latn",
}
m["auy"] = {
"Auyana",
2873211,
"ngf-gau",
"Latn",
}
m["auz"] = {
"Uzbeki Arabic",
3399507,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["avb"] = {
"Avau",
12627412,
"poz-ocw",
"Latn",
}
m["avd"] = {
"Alviri-Vidari",
3327357,
"xme",
"Arab",
ancestors = "xme-mid",
}
m["avi"] = {
"Avikam",
34840,
"alv-lag",
"Latn",
}
m["avk"] = {
"Kotava",
1377116,
"art",
"Latn",
type = "appendix-constructed",
}
m["avm"] = {
"Angkamuthi",
62603022,
"aus-pmn",
"Latn",
}
m["avn"] = {
"Avatime",
34796,
"alv-ktg",
"Latn",
}
-- avo Agavotaguerra retired
m["avs"] = {
"Aushiri",
3409318,
"sai-zap",
"Latn",
}
m["avt"] = {
"Au",
3446608,
"paa-wap",
"Latn",
}
m["avu"] = {
"Avokaya",
56685,
"csu-mma",
"Latn",
}
m["avv"] = {
"Avá-Canoeiro",
4829584,
"tup-gua",
"Latn",
}
m["awa"] = {
"Awadhi",
29579,
"inc-hie",
"Deva, Kthi, Aran",
translit = {
Deva = "hi-translit"
},
}
m["awb"] = {
"Awa (New Guinea)",
2874650,
"ngf-gau",
"Latn",
}
m["awc"] = {
"Cicipu",
35193,
"nic-kam",
"Latn",
}
m["awe"] = {
"Awetí",
4830038,
"tup",
"Latn",
}
m["awg"] = {
"Anguthimri",
4764288,
"aus-pam",
"Latn",
}
m["awh"] = {
"Awbono",
3446684,
"paa-baa",
"Latn",
}
m["awi"] = {
"Aekyom",
3399691,
"paa-kae",
"Latn",
}
m["awk"] = {
"Awabakal",
3449138,
"aus-pam",
"Latn",
}
m["awm"] = {
"Arawum",
4784537,
"ngf-rai",
"Latn",
}
m["awn"] = {
"Awngi",
34934,
"cus-cen",
"Ethi",
}
m["awo"] = {
"Awak",
3446643,
"alv-wjk",
"Latn",
}
m["awr"] = {
"Awera",
56379,
"paa-flp",
"Latn",
}
m["aws"] = {
"South Awyu",
12633986,
"ngf-awy",
"Latn",
}
m["awt"] = {
"Araweté",
4784535,
"tup-gua",
"Latn",
}
m["awu"] = {
"Central Awyu",
12628801,
"ngf-awy",
"Latn",
}
m["awv"] = {
"Jair Awyu",
16110177,
"ngf-awy",
"Latn",
}
m["aww"] = {
"Awun",
56369,
"paa-sep",
"Latn",
}
m["awx"] = {
"Awara",
2874670,
"ngf-waa",
"Latn",
}
m["awy"] = {
"Edera Awyu",
12630425,
"ngf-awy",
"Latn",
}
m["axb"] = {
"Abipón",
11252539,
"sai-guc",
"Latn",
}
m["axe"] = {
"Ayerrerenge",
16112737,
"aus-pam",
"Latn",
}
m["axg"] = {
"Arára (Mato Grosso)",
3446660,
nil,
"Latn",
}
m["axk"] = {
"Aka (Central Africa)",
11010149,
"bnt-ngn",
"Latn",
}
m["axl"] = {
"Lower Southern Aranda",
6693295,
"aus-rnd",
"Latn",
}
m["axm"] = {
"Middle Armenian",
4438498,
"hyx",
"Armn",
ancestors = "xcl",
-- Armn translit in [[Module:scripts/data]]
override_translit = true,
strip_diacritics = {
remove_diacritics = "՞՜՛՟",
from = {"եւ", "ՙ", "՚"},
to = {"և", "ʻ", "’"}
}
}
m["axx"] = {
"Xârâgurè",
8045635,
"poz-cln",
"Latn",
}
m["aya"] = {
"Awar",
56876,
"paa-baw",
"Latn",
}
m["ayb"] = {
"Ayizo",
34841,
"alv-pph",
"Latn",
}
m["ayd"] = {
"Ayabadhu",
3509164,
"aus-pmn",
"Latn",
}
m["aye"] = {
"Ayere",
34788,
"alv-aah",
"Latn",
}
m["ayg"] = {
"Nyanga (Togo)",
35446,
"alv-gng",
"Latn",
}
m["ayi"] = {
"Leyigha",
3914492,
"nic-uce",
"Latn",
}
m["ayk"] = {
"Akuku",
3450179,
"alv-nwd",
"Latn",
}
m["ayl"] = {
"Libyan Arabic",
56503,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ayn"] = {
"Yemeni Arabic",
1686766,
"sem-arb",
"Arab, Hebr",
strip_diacritics = {
Arab = "ar-stripdiacritics",
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["ayo"] = {
"Ayoreo",
56634,
"sai-zam",
"Latn",
}
m["ayp"] = {
"North Mesopotamian Arabic",
56577,
"sem-arb",
"Arab",
ancestors = "acm",
strip_diacritics = "ar-stripdiacritics",
}
m["ayq"] = {
"Ayi",
56449,
"paa-sep",
"Latn",
}
m["ays"] = {
"Sorsogon Ayta",
7563752,
"phi",
"Latn",
}
m["ayt"] = {
"Bataan Ayta",
4921648,
"phi",
"Latn",
}
m["ayu"] = {
"Ayu",
34786,
"alv",
"Latn",
}
-- ayy deleted and removed from ISO; per the removal request, "no linguistic data exists for any [Ayta] language that the
-- ancestors of this group might have once spoken. And thus, there is no evidence that this group ever had a language
-- distinct from any other Philippine language." [Lobel]
m["ayz"] = {
"Maybrat",
4830892,
"paa-may",
-- either an isolate; grouped with Abun and the West Bird's Head family; or in the putative West Papuan family
"Latn",
}
m["aza"] = {
"Azha",
4832486,
"tbq-axi",
"Latn",
}
m["azd"] = {
"Eastern Durango Nahuatl",
16115449,
"azc-dur",
"Latn",
}
m["azg"] = {
"San Pedro Amuzgos Amuzgo",
35092,
"omq",
"Latn",
}
m["azm"] = {
"Ipalapa Amuzgo",
12633013,
"omq",
"Latn",
}
m["azn"] = {
"Western Durango Nahuatl",
12645553,
"azc-dur",
"Latn",
}
m["azo"] = {
"Awing",
34856,
"nic-nge",
"Latn",
}
m["azt"] = {
"Faire Atta",
12630884,
"phi",
"Latn",
}
m["azz"] = {
"Highland Puebla Nahuatl",
12953754,
"azc-nah",
"Latn",
}
return require("Module:languages").finalizeData(m, "language")
p3yg07yuzrfvwcizddo8acr3zq97yjd
Module:utilities/templates
828
7967
54945
54700
2026-09-30T03:10:32Z
Deadend0914
7211
54945
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local parameters_module = "Module:parameters"
local utilities_module = "Module:utilities"
local utilities_format_categories_with_sort_keys_module = "Module:utilities/format_categories_with_sort_keys"
local concat = table.concat
local insert = table.insert
local require = require
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_categories_with_sort_keys(...)
format_categories_with_sort_keys = require(utilities_format_categories_with_sort_keys_module)
return format_categories_with_sort_keys(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function track(...)
track = require(debug_track_module)
return track(...)
end
-- Old English localization: the category wordings that templates pass to {{cln}} /
-- {{catlangname}} (and the declension-class categories built from them, e.g. "Englisc masculine
-- a-stem nouns") come from [[Module:floccnaman]] (see that module); the English wording is kept
-- when a translation is missing. Loaded lazily and optionally, so a missing module can never
-- break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
-- Used by {{catfix}}.
function export.catfix(frame)
local args = process_params(frame:getParent().args, {
[1] = {type = "language", required = true},
[2] = {alias_of = "sc"},
["sc"] = {type = "script"},
})
return require("Module:utilities").catfix(args[1], args.sc)
end
-- Used by {{categorize}}, {{catlangname}} and {{topics}}.
function export.categorize(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, type = "language", default = "und", sublist = true},
[2] = {required = true, list = true, allow_holes = true},
sort = {list = true, separate_no_index = true, allow_holes = true},
force = {type = "boolean"},
})
local langs = args[1]
if not langs[1] then
return ""
end
local parts = {}
for _, lang in ipairs(langs) do
local full_langcode = lang:getFullCode()
if lang:getCode() ~= full_langcode then
track("Module:utilities/templates/categorize called with variant langcode")
end
local raw_cats, sort_keys, format = args[2], args.sort, frame.args["format"]
local default_sort = sort_keys.default
local prefix = format == "pos" and lang:getFullName() .. " " or format == "topic" and full_langcode .. ":" or ""
-- Put the categories in an array. If any have an individual sortkey, they
-- will need to be tables with the category and sort key for
-- [[Module:utilities/format_categories_with_sort_keys]]; otherwise, add
-- them as strings.
local cats, n, with_sort_keys = {}, 0, false
for i = 1, raw_cats.maxindex do
local cat = raw_cats[i]
if cat ~= nil then
-- Old English localization: with format="pos" the wording is a reader-visible
-- "<sprǣc> <word>" category, so translate the word before the language name is
-- prepended. Wording that is not in the table yet stays English, as elsewhere.
if format == "pos" then
cat = cat_word(lang, cat)
end
cat = prefix .. cat
local sort_key = sort_keys[i]
if with_sort_keys then
cat = {category = cat, sort_key = sort_key}
-- If a sort key exists, reformat all previously-processed
-- categories into the table format.
elseif sort_key ~= nil then
with_sort_keys = true
for j = 1, n do
cats[j] = {category = cats[j]}
end
cat = {category = cat, sort_key = sort_key}
end
n = n + 1
cats[n] = cat
end
end
if with_sort_keys then
insert(parts, format_categories_with_sort_keys(cats, lang, default_sort, nil, args.force))
else
insert(parts, format_categories(cats, lang, default_sort, nil, args.force))
end
end
return concat(parts)
end
return export
35dl0mpl27ov7ax83ku7krkgx93l82y
Module:headword/page
828
7978
54926
54925
2026-09-29T17:57:05Z
Deadend0914
7211
54926
Scribunto
text/plain
local export = {}
local languages_module = "Module:languages"
local maintenance_category_module = "Module:maintenance category"
local pages_module = "Module:pages"
local string_compare_module = "Module:string/compare"
local string_decode_entities_module = "Module:string/decodeEntities"
local string_remove_comments_module = "Module:string/removeComments"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local template_parser_module = "Module:template parser"
local mw = mw
local string = string
local table = table
local ustring = mw.ustring
local concat = table.concat
local find = string.find
local format = string.format
local gsub = string.gsub
local insert = table.insert
local load_data = mw.loadData
local match = string.match
local new_title = mw.title.new
local pairs = pairs
local require = require
local sub = string.sub
local toNFC = ustring.toNFC
local toNFD = ustring.toNFD
local ugsub = ustring.gsub
local function class_else_type(...)
class_else_type = require(template_parser_module).class_else_type
return class_else_type(...)
end
local function decode_entities(...)
decode_entities = require(string_decode_entities_module)
return decode_entities(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
local function get_category(...)
get_category = require(maintenance_category_module).get_category
return get_category(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function list_to_set(...)
list_to_set = require(table_module).listToSet
return list_to_set(...)
end
local function parse(...)
parse = require(template_parser_module).parse
return parse(...)
end
local function remove_comments(...)
remove_comments = require(string_remove_comments_module)
return remove_comments(...)
end
local function physical_to_logical_pagename_if_mammoth(...)
physical_to_logical_pagename_if_mammoth = require(pages_module).physical_to_logical_pagename_if_mammoth
return physical_to_logical_pagename_if_mammoth(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function string_compare(...)
string_compare = require(string_compare_module)
return string_compare(...)
end
local function uupper(...)
uupper = require(string_utilities_module).upper
return uupper(...)
end
--[==[
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
-- Old English localization: the ==L2== headings are rendered by [[Bysen:sprǣc]] from
-- [[Module:sprǣcnaman]], so those names have to be recognized as language names below as well. The
-- module is optional: if it is missing, the English names are used exactly as before.
local ang_names_module = "Module:sprǣcnaman"
local ang_names
local function get_ang_names()
if ang_names == nil then
local ok, mod = pcall(require, ang_names_module)
ang_names = ok and mod or false
end
return ang_names or nil
end
local langnames
local function get_langnames()
local data = load_data("Module:languages/canonical names")
-- Old English localization: an ==L2== heading written with {{Bysen:sprǣc}} contains an Old
-- English name (e.g. "Nīwenglisc"), so those names have to count as language names here as
-- well. The table returned by mw.loadData() is read-only, so the Old English names are put
-- in a new table that falls back to the English one; both are only used as a membership
-- test, so the values do not matter.
local m_ang_names = get_ang_names()
if m_ang_names then
local ang_langnames = {}
for _, ang_name in pairs(m_ang_names.names) do
ang_langnames[ang_name] = true
end
langnames = setmetatable(ang_langnames, {__index = data})
else
langnames = data
end
get_langnames = nil
return langnames
end
-- Combining character data used when categorising unusual characters. These resolve into two patterns, used to find
-- single combining characters (i.e. character + diacritic(s)) or double combining characters (i.e. character +
-- diacritic(s) + character).
-- Charsets are in the format used by Unicode's UnicodeSet tool: https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp.
-- Single combining characters.
-- Charset: [[:M:]&[:^Canonical_Combining_Class=/^Double_/:]&[:^subhead=Grapheme joiner:]&[:^Variation_Selector=Yes:]]
-- Note: concatenating hundreds of lines at once gives an error, so () are used every 150 lines to break it up into chunks.
local comb_chars_single =
("\204\128-\205\142" .. -- U+0300-U+034E
"\205\144-\205\155" .. -- U+0350-U+035B
"\205\163-\205\175" .. -- U+0363-U+036F
"\210\131-\210\137" .. -- U+0483-U+0489
"\214\145-\214\189" .. -- U+0591-U+05BD
"\214\191" .. -- U+05BF
"\215\129" .. -- U+05C1
"\215\130" .. -- U+05C2
"\215\132" .. -- U+05C4
"\215\133" .. -- U+05C5
"\215\135" .. -- U+05C7
"\216\144-\216\154" .. -- U+0610-U+061A
"\217\139-\217\159" .. -- U+064B-U+065F
"\217\176" .. -- U+0670
"\219\150-\219\156" .. -- U+06D6-U+06DC
"\219\159-\219\164" .. -- U+06DF-U+06E4
"\219\167" .. -- U+06E7
"\219\168" .. -- U+06E8
"\219\170-\219\173" .. -- U+06EA-U+06ED
"\220\145" .. -- U+0711
"\220\176-\221\138" .. -- U+0730-U+074A
"\222\166-\222\176" .. -- U+07A6-U+07B0
"\223\171-\223\179" .. -- U+07EB-U+07F3
"\223\189" .. -- U+07FD
"\224\160\150-\224\160\153" .. -- U+0816-U+0819
"\224\160\155-\224\160\163" .. -- U+081B-U+0823
"\224\160\165-\224\160\167" .. -- U+0825-U+0827
"\224\160\169-\224\160\173" .. -- U+0829-U+082D
"\224\161\153-\224\161\155" .. -- U+0859-U+085B
"\224\162\151-\224\162\159" .. -- U+0897-U+089F
"\224\163\138-\224\163\161" .. -- U+08CA-U+08E1
"\224\163\163-\224\164\131" .. -- U+08E3-U+0903
"\224\164\186-\224\164\188" .. -- U+093A-U+093C
"\224\164\190-\224\165\143" .. -- U+093E-U+094F
"\224\165\145-\224\165\151" .. -- U+0951-U+0957
"\224\165\162" .. -- U+0962
"\224\165\163" .. -- U+0963
"\224\166\129-\224\166\131" .. -- U+0981-U+0983
"\224\166\188" .. -- U+09BC
"\224\166\190-\224\167\132" .. -- U+09BE-U+09C4
"\224\167\135" .. -- U+09C7
"\224\167\136" .. -- U+09C8
"\224\167\139-\224\167\141" .. -- U+09CB-U+09CD
"\224\167\151" .. -- U+09D7
"\224\167\162" .. -- U+09E2
"\224\167\163" .. -- U+09E3
"\224\167\190" .. -- U+09FE
"\224\168\129-\224\168\131" .. -- U+0A01-U+0A03
"\224\168\188" .. -- U+0A3C
"\224\168\190-\224\169\130" .. -- U+0A3E-U+0A42
"\224\169\135" .. -- U+0A47
"\224\169\136" .. -- U+0A48
"\224\169\139-\224\169\141" .. -- U+0A4B-U+0A4D
"\224\169\145" .. -- U+0A51
"\224\169\176" .. -- U+0A70
"\224\169\177" .. -- U+0A71
"\224\169\181" .. -- U+0A75
"\224\170\129-\224\170\131" .. -- U+0A81-U+0A83
"\224\170\188" .. -- U+0ABC
"\224\170\190-\224\171\133" .. -- U+0ABE-U+0AC5
"\224\171\135-\224\171\137" .. -- U+0AC7-U+0AC9
"\224\171\139-\224\171\141" .. -- U+0ACB-U+0ACD
"\224\171\162" .. -- U+0AE2
"\224\171\163" .. -- U+0AE3
"\224\171\186-\224\171\191" .. -- U+0AFA-U+0AFF
"\224\172\129-\224\172\131" .. -- U+0B01-U+0B03
"\224\172\188" .. -- U+0B3C
"\224\172\190-\224\173\132" .. -- U+0B3E-U+0B44
"\224\173\135" .. -- U+0B47
"\224\173\136" .. -- U+0B48
"\224\173\139-\224\173\141" .. -- U+0B4B-U+0B4D
"\224\173\149-\224\173\151" .. -- U+0B55-U+0B57
"\224\173\162" .. -- U+0B62
"\224\173\163" .. -- U+0B63
"\224\174\130" .. -- U+0B82
"\224\174\190-\224\175\130" .. -- U+0BBE-U+0BC2
"\224\175\134-\224\175\136" .. -- U+0BC6-U+0BC8
"\224\175\138-\224\175\141" .. -- U+0BCA-U+0BCD
"\224\175\151" .. -- U+0BD7
"\224\176\128-\224\176\132" .. -- U+0C00-U+0C04
"\224\176\188" .. -- U+0C3C
"\224\176\190-\224\177\132" .. -- U+0C3E-U+0C44
"\224\177\134-\224\177\136" .. -- U+0C46-U+0C48
"\224\177\138-\224\177\141" .. -- U+0C4A-U+0C4D
"\224\177\149" .. -- U+0C55
"\224\177\150" .. -- U+0C56
"\224\177\162" .. -- U+0C62
"\224\177\163" .. -- U+0C63
"\224\178\129-\224\178\131" .. -- U+0C81-U+0C83
"\224\178\188" .. -- U+0CBC
"\224\178\190-\224\179\132" .. -- U+0CBE-U+0CC4
"\224\179\134-\224\179\136" .. -- U+0CC6-U+0CC8
"\224\179\138-\224\179\141" .. -- U+0CCA-U+0CCD
"\224\179\149" .. -- U+0CD5
"\224\179\150" .. -- U+0CD6
"\224\179\162" .. -- U+0CE2
"\224\179\163" .. -- U+0CE3
"\224\179\179" .. -- U+0CF3
"\224\180\128-\224\180\131" .. -- U+0D00-U+0D03
"\224\180\187" .. -- U+0D3B
"\224\180\188" .. -- U+0D3C
"\224\180\190-\224\181\132" .. -- U+0D3E-U+0D44
"\224\181\134-\224\181\136" .. -- U+0D46-U+0D48
"\224\181\138-\224\181\141" .. -- U+0D4A-U+0D4D
"\224\181\151" .. -- U+0D57
"\224\181\162" .. -- U+0D62
"\224\181\163" .. -- U+0D63
"\224\182\129-\224\182\131" .. -- U+0D81-U+0D83
"\224\183\138" .. -- U+0DCA
"\224\183\143-\224\183\148" .. -- U+0DCF-U+0DD4
"\224\183\150" .. -- U+0DD6
"\224\183\152-\224\183\159" .. -- U+0DD8-U+0DDF
"\224\183\178" .. -- U+0DF2
"\224\183\179" .. -- U+0DF3
"\224\184\177" .. -- U+0E31
"\224\184\180-\224\184\186" .. -- U+0E34-U+0E3A
"\224\185\135-\224\185\142" .. -- U+0E47-U+0E4E
"\224\186\177" .. -- U+0EB1
"\224\186\180-\224\186\188" .. -- U+0EB4-U+0EBC
"\224\187\136-\224\187\142" .. -- U+0EC8-U+0ECE
"\224\188\152" .. -- U+0F18
"\224\188\153" .. -- U+0F19
"\224\188\181" .. -- U+0F35
"\224\188\183" .. -- U+0F37
"\224\188\185" .. -- U+0F39
"\224\188\190" .. -- U+0F3E
"\224\188\191" .. -- U+0F3F
"\224\189\177-\224\190\132" .. -- U+0F71-U+0F84
"\224\190\134" .. -- U+0F86
"\224\190\135" .. -- U+0F87
"\224\190\141-\224\190\151" .. -- U+0F8D-U+0F97
"\224\190\153-\224\190\188" .. -- U+0F99-U+0FBC
"\224\191\134" .. -- U+0FC6
"\225\128\171-\225\128\190" .. -- U+102B-U+103E
"\225\129\150-\225\129\153" .. -- U+1056-U+1059
"\225\129\158-\225\129\160" .. -- U+105E-U+1060
"\225\129\162-\225\129\164" .. -- U+1062-U+1064
"\225\129\167-\225\129\173" .. -- U+1067-U+106D
"\225\129\177-\225\129\180" .. -- U+1071-U+1074
"\225\130\130-\225\130\141" .. -- U+1082-U+108D
"\225\130\143" .. -- U+108F
"\225\130\154-\225\130\157" .. -- U+109A-U+109D
"\225\141\157-\225\141\159" .. -- U+135D-U+135F
"\225\156\146-\225\156\149" .. -- U+1712-U+1715
"\225\156\178-\225\156\180" .. -- U+1732-U+1734
"\225\157\146" .. -- U+1752
"\225\157\147" .. -- U+1753
"\225\157\178" .. -- U+1772
"\225\157\179" .. -- U+1773
"\225\158\180-\225\159\147") .. -- U+17B4-U+17D3
("\225\159\157" .. -- U+17DD
"\225\162\133" .. -- U+1885
"\225\162\134" .. -- U+1886
"\225\162\169" .. -- U+18A9
"\225\164\160-\225\164\171" .. -- U+1920-U+192B
"\225\164\176-\225\164\187" .. -- U+1930-U+193B
"\225\168\151-\225\168\155" .. -- U+1A17-U+1A1B
"\225\169\149-\225\169\158" .. -- U+1A55-U+1A5E
"\225\169\160-\225\169\188" .. -- U+1A60-U+1A7C
"\225\169\191" .. -- U+1A7F
"\225\170\176-\225\171\142" .. -- U+1AB0-U+1ACE
"\225\172\128-\225\172\132" .. -- U+1B00-U+1B04
"\225\172\180-\225\173\132" .. -- U+1B34-U+1B44
"\225\173\171-\225\173\179" .. -- U+1B6B-U+1B73
"\225\174\128-\225\174\130" .. -- U+1B80-U+1B82
"\225\174\161-\225\174\173" .. -- U+1BA1-U+1BAD
"\225\175\166-\225\175\179" .. -- U+1BE6-U+1BF3
"\225\176\164-\225\176\183" .. -- U+1C24-U+1C37
"\225\179\144-\225\179\146" .. -- U+1CD0-U+1CD2
"\225\179\148-\225\179\168" .. -- U+1CD4-U+1CE8
"\225\179\173" .. -- U+1CED
"\225\179\180" .. -- U+1CF4
"\225\179\183-\225\179\185" .. -- U+1CF7-U+1CF9
"\225\183\128-\225\183\140" .. -- U+1DC0-U+1DCC
"\225\183\142-\225\183\187" .. -- U+1DCE-U+1DFB
"\225\183\189-\225\183\191" .. -- U+1DFD-U+1DFF
"\226\131\144-\226\131\176" .. -- U+20D0-U+20F0
"\226\179\175-\226\179\177" .. -- U+2CEF-U+2CF1
"\226\181\191" .. -- U+2D7F
"\226\183\160-\226\183\191" .. -- U+2DE0-U+2DFF
"\227\128\170-\227\128\175" .. -- U+302A-U+302F
"\227\130\153" .. -- U+3099
"\227\130\154" .. -- U+309A
"\234\153\175-\234\153\178" .. -- U+A66F-U+A672
"\234\153\180-\234\153\189" .. -- U+A674-U+A67D
"\234\154\158" .. -- U+A69E
"\234\154\159" .. -- U+A69F
"\234\155\176" .. -- U+A6F0
"\234\155\177" .. -- U+A6F1
"\234\160\130" .. -- U+A802
"\234\160\134" .. -- U+A806
"\234\160\139" .. -- U+A80B
"\234\160\163-\234\160\167" .. -- U+A823-U+A827
"\234\160\172" .. -- U+A82C
"\234\162\128" .. -- U+A880
"\234\162\129" .. -- U+A881
"\234\162\180-\234\163\133" .. -- U+A8B4-U+A8C5
"\234\163\160-\234\163\177" .. -- U+A8E0-U+A8F1
"\234\163\191" .. -- U+A8FF
"\234\164\166-\234\164\173" .. -- U+A926-U+A92D
"\234\165\135-\234\165\147" .. -- U+A947-U+A953
"\234\166\128-\234\166\131" .. -- U+A980-U+A983
"\234\166\179-\234\167\128" .. -- U+A9B3-U+A9C0
"\234\167\165" .. -- U+A9E5
"\234\168\169-\234\168\182" .. -- U+AA29-U+AA36
"\234\169\131" .. -- U+AA43
"\234\169\140" .. -- U+AA4C
"\234\169\141" .. -- U+AA4D
"\234\169\187-\234\169\189" .. -- U+AA7B-U+AA7D
"\234\170\176" .. -- U+AAB0
"\234\170\178-\234\170\180" .. -- U+AAB2-U+AAB4
"\234\170\183" .. -- U+AAB7
"\234\170\184" .. -- U+AAB8
"\234\170\190" .. -- U+AABE
"\234\170\191" .. -- U+AABF
"\234\171\129" .. -- U+AAC1
"\234\171\171-\234\171\175" .. -- U+AAEB-U+AAEF
"\234\171\181" .. -- U+AAF5
"\234\171\182" .. -- U+AAF6
"\234\175\163-\234\175\170" .. -- U+ABE3-U+ABEA
"\234\175\172" .. -- U+ABEC
"\234\175\173" .. -- U+ABED
"\239\172\158" .. -- U+FB1E
"\239\184\160-\239\184\175" .. -- U+FE20-U+FE2F
"\240\144\135\189" .. -- U+101FD
"\240\144\139\160" .. -- U+102E0
"\240\144\141\182-\240\144\141\186" .. -- U+10376-U+1037A
"\240\144\168\129-\240\144\168\131" .. -- U+10A01-U+10A03
"\240\144\168\133" .. -- U+10A05
"\240\144\168\134" .. -- U+10A06
"\240\144\168\140-\240\144\168\143" .. -- U+10A0C-U+10A0F
"\240\144\168\184-\240\144\168\186" .. -- U+10A38-U+10A3A
"\240\144\168\191" .. -- U+10A3F
"\240\144\171\165" .. -- U+10AE5
"\240\144\171\166" .. -- U+10AE6
"\240\144\180\164-\240\144\180\167" .. -- U+10D24-U+10D27
"\240\144\181\169-\240\144\181\173" .. -- U+10D69-U+10D6D
"\240\144\186\171" .. -- U+10EAB
"\240\144\186\172" .. -- U+10EAC
"\240\144\187\188-\240\144\187\191" .. -- U+10EFC-U+10EFF
"\240\144\189\134-\240\144\189\144" .. -- U+10F46-U+10F50
"\240\144\190\130-\240\144\190\133" .. -- U+10F82-U+10F85
"\240\145\128\128-\240\145\128\130" .. -- U+11000-U+11002
"\240\145\128\184-\240\145\129\134" .. -- U+11038-U+11046
"\240\145\129\176" .. -- U+11070
"\240\145\129\179" .. -- U+11073
"\240\145\129\180" .. -- U+11074
"\240\145\129\191-\240\145\130\130" .. -- U+1107F-U+11082
"\240\145\130\176-\240\145\130\186" .. -- U+110B0-U+110BA
"\240\145\131\130" .. -- U+110C2
"\240\145\132\128-\240\145\132\130" .. -- U+11100-U+11102
"\240\145\132\167-\240\145\132\180" .. -- U+11127-U+11134
"\240\145\133\133" .. -- U+11145
"\240\145\133\134" .. -- U+11146
"\240\145\133\179" .. -- U+11173
"\240\145\134\128-\240\145\134\130" .. -- U+11180-U+11182
"\240\145\134\179-\240\145\135\128" .. -- U+111B3-U+111C0
"\240\145\135\137-\240\145\135\140" .. -- U+111C9-U+111CC
"\240\145\135\142" .. -- U+111CE
"\240\145\135\143" .. -- U+111CF
"\240\145\136\172-\240\145\136\183" .. -- U+1122C-U+11237
"\240\145\136\190" .. -- U+1123E
"\240\145\137\129" .. -- U+11241
"\240\145\139\159-\240\145\139\170" .. -- U+112DF-U+112EA
"\240\145\140\128-\240\145\140\131" .. -- U+11300-U+11303
"\240\145\140\187" .. -- U+1133B
"\240\145\140\188" .. -- U+1133C
"\240\145\140\190-\240\145\141\132" .. -- U+1133E-U+11344
"\240\145\141\135" .. -- U+11347
"\240\145\141\136" .. -- U+11348
"\240\145\141\139-\240\145\141\141" .. -- U+1134B-U+1134D
"\240\145\141\151" .. -- U+11357
"\240\145\141\162" .. -- U+11362
"\240\145\141\163" .. -- U+11363
"\240\145\141\166-\240\145\141\172" .. -- U+11366-U+1136C
"\240\145\141\176-\240\145\141\180" .. -- U+11370-U+11374
"\240\145\142\184-\240\145\143\128" .. -- U+113B8-U+113C0
"\240\145\143\130" .. -- U+113C2
"\240\145\143\133" .. -- U+113C5
"\240\145\143\135-\240\145\143\138" .. -- U+113C7-U+113CA
"\240\145\143\140-\240\145\143\144" .. -- U+113CC-U+113D0
"\240\145\143\146" .. -- U+113D2
"\240\145\143\161" .. -- U+113E1
"\240\145\143\162" .. -- U+113E2
"\240\145\144\181-\240\145\145\134" .. -- U+11435-U+11446
"\240\145\145\158" .. -- U+1145E
"\240\145\146\176-\240\145\147\131" .. -- U+114B0-U+114C3
"\240\145\150\175-\240\145\150\181" .. -- U+115AF-U+115B5
"\240\145\150\184-\240\145\151\128" .. -- U+115B8-U+115C0
"\240\145\151\156" .. -- U+115DC
"\240\145\151\157" .. -- U+115DD
"\240\145\152\176-\240\145\153\128" .. -- U+11630-U+11640
"\240\145\154\171-\240\145\154\183" .. -- U+116AB-U+116B7
"\240\145\156\157-\240\145\156\171" .. -- U+1171D-U+1172B
"\240\145\160\172-\240\145\160\186" .. -- U+1182C-U+1183A
"\240\145\164\176-\240\145\164\181" .. -- U+11930-U+11935
"\240\145\164\183" .. -- U+11937
"\240\145\164\184" .. -- U+11938
"\240\145\164\187-\240\145\164\190" .. -- U+1193B-U+1193E
"\240\145\165\128") .. -- U+11940
("\240\145\165\130" .. -- U+11942
"\240\145\165\131" .. -- U+11943
"\240\145\167\145-\240\145\167\151" .. -- U+119D1-U+119D7
"\240\145\167\154-\240\145\167\160" .. -- U+119DA-U+119E0
"\240\145\167\164" .. -- U+119E4
"\240\145\168\129-\240\145\168\138" .. -- U+11A01-U+11A0A
"\240\145\168\179-\240\145\168\185" .. -- U+11A33-U+11A39
"\240\145\168\187-\240\145\168\190" .. -- U+11A3B-U+11A3E
"\240\145\169\135" .. -- U+11A47
"\240\145\169\145-\240\145\169\155" .. -- U+11A51-U+11A5B
"\240\145\170\138-\240\145\170\153" .. -- U+11A8A-U+11A99
"\240\145\176\175-\240\145\176\182" .. -- U+11C2F-U+11C36
"\240\145\176\184-\240\145\176\191" .. -- U+11C38-U+11C3F
"\240\145\178\146-\240\145\178\167" .. -- U+11C92-U+11CA7
"\240\145\178\169-\240\145\178\182" .. -- U+11CA9-U+11CB6
"\240\145\180\177-\240\145\180\182" .. -- U+11D31-U+11D36
"\240\145\180\186" .. -- U+11D3A
"\240\145\180\188" .. -- U+11D3C
"\240\145\180\189" .. -- U+11D3D
"\240\145\180\191-\240\145\181\133" .. -- U+11D3F-U+11D45
"\240\145\181\135" .. -- U+11D47
"\240\145\182\138-\240\145\182\142" .. -- U+11D8A-U+11D8E
"\240\145\182\144" .. -- U+11D90
"\240\145\182\145" .. -- U+11D91
"\240\145\182\147-\240\145\182\151" .. -- U+11D93-U+11D97
"\240\145\187\179-\240\145\187\182" .. -- U+11EF3-U+11EF6
"\240\145\188\128" .. -- U+11F00
"\240\145\188\129" .. -- U+11F01
"\240\145\188\131" .. -- U+11F03
"\240\145\188\180-\240\145\188\186" .. -- U+11F34-U+11F3A
"\240\145\188\190-\240\145\189\130" .. -- U+11F3E-U+11F42
"\240\145\189\154" .. -- U+11F5A
"\240\147\145\128" .. -- U+13440
"\240\147\145\135-\240\147\145\149" .. -- U+13447-U+13455
"\240\150\132\158-\240\150\132\175" .. -- U+1611E-U+1612F
"\240\150\171\176-\240\150\171\180" .. -- U+16AF0-U+16AF4
"\240\150\172\176-\240\150\172\182" .. -- U+16B30-U+16B36
"\240\150\189\143" .. -- U+16F4F
"\240\150\189\145-\240\150\190\135" .. -- U+16F51-U+16F87
"\240\150\190\143-\240\150\190\146" .. -- U+16F8F-U+16F92
"\240\150\191\164" .. -- U+16FE4
"\240\150\191\176" .. -- U+16FF0
"\240\150\191\177" .. -- U+16FF1
"\240\155\178\157" .. -- U+1BC9D
"\240\155\178\158" .. -- U+1BC9E
"\240\156\188\128-\240\156\188\173" .. -- U+1CF00-U+1CF2D
"\240\156\188\176-\240\156\189\134" .. -- U+1CF30-U+1CF46
"\240\157\133\165-\240\157\133\169" .. -- U+1D165-U+1D169
"\240\157\133\173-\240\157\133\178" .. -- U+1D16D-U+1D172
"\240\157\133\187-\240\157\134\130" .. -- U+1D17B-U+1D182
"\240\157\134\133-\240\157\134\139" .. -- U+1D185-U+1D18B
"\240\157\134\170-\240\157\134\173" .. -- U+1D1AA-U+1D1AD
"\240\157\137\130-\240\157\137\132" .. -- U+1D242-U+1D244
"\240\157\168\128-\240\157\168\182" .. -- U+1DA00-U+1DA36
"\240\157\168\187-\240\157\169\172" .. -- U+1DA3B-U+1DA6C
"\240\157\169\181" .. -- U+1DA75
"\240\157\170\132" .. -- U+1DA84
"\240\157\170\155-\240\157\170\159" .. -- U+1DA9B-U+1DA9F
"\240\157\170\161-\240\157\170\175" .. -- U+1DAA1-U+1DAAF
"\240\158\128\128-\240\158\128\134" .. -- U+1E000-U+1E006
"\240\158\128\136-\240\158\128\152" .. -- U+1E008-U+1E018
"\240\158\128\155-\240\158\128\161" .. -- U+1E01B-U+1E021
"\240\158\128\163" .. -- U+1E023
"\240\158\128\164" .. -- U+1E024
"\240\158\128\166-\240\158\128\170" .. -- U+1E026-U+1E02A
"\240\158\130\143" .. -- U+1E08F
"\240\158\132\176-\240\158\132\182" .. -- U+1E130-U+1E136
"\240\158\138\174" .. -- U+1E2AE
"\240\158\139\172-\240\158\139\175" .. -- U+1E2EC-U+1E2EF
"\240\158\147\172-\240\158\147\175" .. -- U+1E4EC-U+1E4EF
"\240\158\151\174" .. -- U+1E5EE
"\240\158\151\175" .. -- U+1E5EF
"\240\158\163\144-\240\158\163\150" .. -- U+1E8D0-U+1E8D6
"\240\158\165\132-\240\158\165\138") -- U+1E944-U+1E94A
-- Double combining characters.
-- Charset: [[:M:]&[:Canonical_Combining_Class=/^Double_/:]&[:^subhead=Grapheme joiner:]&[:^Variation_Selector=Yes:]]
local comb_chars_double =
"\205\156-\205\162" .. -- U+035C-U+0362
"\225\183\141" .. -- U+1DCD
"\225\183\188" -- U+1DFC
-- Variation selectors etc.; separated out so that we don't get categories for them.
-- Charset: [[:M:]&[[:subhead=Grapheme joiner:][:Variation_Selector=Yes:]]].
local comb_chars_other =
"\205\143" .. -- U+034F
"\225\160\139-\225\160\141" .. -- U+180B-U+180D
"\225\160\143" .. -- U+180F
"\239\184\128-\239\184\143" .. -- U+FE00-U+FE0F
"\243\160\132\128-\243\160\135\175" -- U+E0100-U+E01EF
local comb_chars_all = comb_chars_single .. comb_chars_double .. comb_chars_other
local comb_chars = {
combined_single = "[^" .. comb_chars_all .. "][" .. comb_chars_single .. comb_chars_other .. "]+%f[^" .. comb_chars_all .. "]",
combined_double = "[^" .. comb_chars_all .. "][" .. comb_chars_single .. comb_chars_other .. "]*[" .. comb_chars_double .. "]+[" .. comb_chars_all .. "]*.[" .. comb_chars_single .. comb_chars_other .. "]*",
diacritics_single = "[" .. comb_chars_single .. "]",
diacritics_double = "[" .. comb_chars_double .. "]",
diacritics_all = "[" .. comb_chars_all .. "]"
}
-- Somewhat curated list from https://unicode.org/Public/emoji/16.0/emoji-sequences.txt.
-- NOTE: There are lots more emoji sequences involving non-emoji Plane 0 symbols followed by 0xFE0F, which we don't
-- (yet?) handle.
local emoji_chars =
"\226\140\154" .. -- U+231A (⌚)
"\226\140\155" .. -- U+231B (⌛)
"\226\140\168" .. -- U+2328 (⌨)
"\226\143\143" .. -- U+23CF (⏏)
"\226\143\169-\226\143\179" .. -- U+23E9-U+23F3 (⏩-⏳)
"\226\143\184-\226\143\186" .. -- U+23F8-U+23FA (⏸-⏺)
"\226\150\170" .. -- U+25AA (▪)
"\226\150\171" .. -- U+25AB (▫)
"\226\150\182" .. -- U+25B6 (▶)
"\226\151\128" .. -- U+25C0 (◀)
"\226\151\187-\226\151\190" .. -- U+25FB-U+25FE (◻-◾)
"\226\152\128-\226\152\132" .. -- U+2600-U+2604 (☀-☄)
"\226\152\142" .. -- U+260E (☎)
"\226\152\145" .. -- U+2611 (☑)
"\226\152\148" .. -- U+2614 (☔)
"\226\152\149" .. -- U+2615 (☕)
"\226\152\152" .. -- U+2618 (☘)
"\226\152\157" .. -- U+261D (☝)
"\226\152\160" .. -- U+2620 (☠)
"\226\152\162" .. -- U+2622 (☢)
"\226\152\163" .. -- U+2623 (☣)
"\226\152\166" .. -- U+2626 (☦)
"\226\152\170" .. -- U+262A (☪)
"\226\152\174" .. -- U+262E (☮)
"\226\152\175" .. -- U+262F (☯)
"\226\152\184-\226\152\186" .. -- U+2638-U+263A (☸-☺)
"\226\153\136-\226\153\147" .. -- U+2648-U+2653 (♈-♓)
"\226\153\159" .. -- U+265F (♟)
"\226\153\160" .. -- U+2660 (♠)
"\226\153\163" .. -- U+2663 (♣)
"\226\153\165" .. -- U+2665 (♥)
"\226\153\166" .. -- U+2666 (♦)
"\226\153\168" .. -- U+2668 (♨)
"\226\153\187" .. -- U+267B (♻)
"\226\153\190" .. -- U+267E (♾)
"\226\153\191" .. -- U+267F (♿)
"\226\154\146-\226\154\151" .. -- U+2692-U+2697 (⚒-⚗)
"\226\154\153" .. -- U+2699 (⚙)
"\226\154\155" .. -- U+269B (⚛)
"\226\154\156" .. -- U+269C (⚜)
"\226\154\160" .. -- U+26A0 (⚠)
"\226\154\161" .. -- U+26A1 (⚡)
"\226\154\170" .. -- U+26AA (⚪)
"\226\154\171" .. -- U+26AB (⚫)
"\226\154\176" .. -- U+26B0 (⚰)
"\226\154\177" .. -- U+26B1 (⚱)
"\226\154\189" .. -- U+26BD (⚽)
"\226\154\190" .. -- U+26BE (⚾)
"\226\155\132" .. -- U+26C4 (⛄)
"\226\155\133" .. -- U+26C5 (⛅)
"\226\155\136" .. -- U+26C8 (⛈)
"\226\155\142" .. -- U+26CE (⛎)
"\226\155\143" .. -- U+26CF (⛏)
"\226\155\145" .. -- U+26D1 (⛑)
"\226\155\147" .. -- U+26D3 (⛓)
"\226\155\148" .. -- U+26D4 (⛔)
"\226\155\169" .. -- U+26E9 (⛩)
"\226\155\170" .. -- U+26EA (⛪)
"\226\155\176-\226\155\181" .. -- U+26F0-U+26F5 (⛰-⛵)
"\226\155\183-\226\155\186" .. -- U+26F7-U+26FA (⛷-⛺)
"\226\155\189" .. -- U+26FD (⛽)
"\226\156\130" .. -- U+2702 (✂)
"\226\156\133" .. -- U+2705 (✅)
"\226\156\136-\226\156\141" .. -- U+2708-U+270D (✈-✍)
"\226\156\143" .. -- U+270F (✏)
"\226\156\146" .. -- U+2712 (✒)
"\226\156\148" .. -- U+2714 (✔)
"\226\156\150" .. -- U+2716 (✖)
"\226\156\157" .. -- U+271D (✝)
"\226\156\161" .. -- U+2721 (✡)
"\226\156\168" .. -- U+2728 (✨)
"\226\156\179" .. -- U+2733 (✳)
"\226\156\180" .. -- U+2734 (✴)
"\226\157\132" .. -- U+2744 (❄)
"\226\157\135" .. -- U+2747 (❇)
"\226\157\140" .. -- U+274C (❌)
"\226\157\142" .. -- U+274E (❎)
"\226\157\147-\226\157\149" .. -- U+2753-U+2755 (❓-❕)
"\226\157\151" .. -- U+2757 (❗)
"\226\157\163" .. -- U+2763 (❣)
"\226\157\164" .. -- U+2764 (❤)
"\226\158\149-\226\158\151" .. -- U+2795-U+2797 (➕-➗)
"\226\158\161" .. -- U+27A1 (➡)
"\226\158\176" .. -- U+27B0 (➰)
"\226\158\191" .. -- U+27BF (➿)
"\226\164\180" .. -- U+2934 (⤴)
"\226\164\181" .. -- U+2935 (⤵)
"\226\172\133-\226\172\135" .. -- U+2B05-U+2B07 (⬅-⬇)
"\226\172\155" .. -- U+2B1B (⬛)
"\226\172\156" .. -- U+2B1C (⬜)
"\226\173\144" .. -- U+2B50 (⭐)
"\226\173\149" .. -- U+2B55 (⭕)
"\227\128\176" .. -- U+3030 (〰)
"\227\128\189" .. -- U+303D (〽)
"\227\138\151" .. -- U+3297 (㊗)
"\227\138\153" .. -- U+3299 (㊙)
"\240\159\128\132" .. -- U+1F004 (🀄)
"\240\159\131\143" .. -- U+1F0CF (🃏)
"\240\159\133\176" .. -- U+1F170 (🅰)
"\240\159\133\177" .. -- U+1F171 (🅱)
"\240\159\133\190" .. -- U+1F17E (🅾)
"\240\159\133\191" .. -- U+1F17F (🅿)
"\240\159\134\142" .. -- U+1F18E (🆎)
"\240\159\134\145-\240\159\134\154" .. -- U+1F191-U+1F19A (🆑-🆚)
"\240\159\136\129" .. -- U+1F201 (🈁)
"\240\159\136\130" .. -- U+1F202 (🈂)
"\240\159\136\154" .. -- U+1F21A (🈚)
"\240\159\136\175" .. -- U+1F22F (🈯)
"\240\159\136\178-\240\159\136\186" .. -- U+1F232-U+1F23A (🈲-🈺)
"\240\159\137\144" .. -- U+1F250 (🉐)
"\240\159\137\145" .. -- U+1F251 (🉑)
"\240\159\140\128-\240\159\153\143" .. -- U+1F300-U+1F64F (🌀-🙏)
"\240\159\154\128-\240\159\155\151" .. -- U+1F680-U+1F6D7 (🚀-🛗)
"\240\159\155\156-\240\159\155\172" .. -- U+1F6DC-U+1F6EC (🛜-🛬)
"\240\159\155\176-\240\159\155\188" .. -- U+1F6F0-U+1F6FC (🛰-🛼)
"\240\159\159\160-\240\159\159\171" .. -- U+1F7E0-U+1F7EB (🟠-🟫)
"\240\159\159\176" .. -- U+1F7F0 (🟰)
"\240\159\164\140-\240\159\169\147" .. -- U+1F90C-U+1FA53 (🤌-🩓)
"\240\159\169\160-\240\159\169\173" .. -- U+1FA60-U+1FA6D (🩠-🩭)
"\240\159\169\176-\240\159\169\188" .. -- U+1FA70-U+1FA7C (🩰-🩼)
"\240\159\170\128-\240\159\170\137" .. -- U+1FA80-U+1FA89 (🪀-)
"\240\159\170\143-\240\159\171\134" .. -- U+1FA8F-U+1FAC6 (-)
"\240\159\171\142-\240\159\171\156" .. -- U+1FACE-U+1FADC (🫎-)
"\240\159\171\159-\240\159\171\169" .. -- U+1FADF-U+1FAE9 (-)
"\240\159\171\176-\240\159\171\184" -- U+1FAF0-U+1FAF8 (🫰-🫸)
local unsupported_characters
local function get_unsupported_characters()
unsupported_characters, get_unsupported_characters = {}, nil
for k, v in pairs(load_data("Module:links/data").unsupported_characters) do
unsupported_characters[v] = k
end
return unsupported_characters
end
-- The list of unsupported titles and invert it (so the keys are pagenames and values are canonical titles).
local unsupported_titles
local function get_unsupported_titles()
unsupported_titles, get_unsupported_titles = {}, nil
for k, v in pairs(load_data("Module:links/data").unsupported_titles) do
unsupported_titles[v] = k
end
return unsupported_titles
end
-- To save on memory, we only cache names with either non-ASCII characters in them or ASCII characters to be removed or
-- transformed (apostrophe, double quote, hyphen).
local L2_sort_key_cache = {}
function export.get_L2_sort_key(L2)
if L2 == "Translingual" then
return "\1"
elseif L2 == "English" then
return "\2"
elseif match(L2, "^[%z\1-\b\14-!#-&(-,.-\127]+$") then
return L2
end
local sort_key = L2_sort_key_cache[L2]
if sort_key then
return sort_key
end
sort_key = toNFC(ugsub(ugsub(toNFD(L2), "[" .. comb_chars_all .. "'\"ʻʼ]+", ""), "[%s%-]+", " "))
L2_sort_key_cache[L2] = sort_key
return sort_key
end
--[==[
Given a pagename (or {nil} for the current page), create and return a data structure describing the page. The returned
object includes the following fields:
* `comb_chars`: A table containing various Lua character class patterns for different types of combined characters
(those that decompose into multiple characters in the NFD decomposition). The patterns are meant to be used with
{mw.ustring.find()}. The keys are:
** `single`: Single combining characters (character + diacritic), without surrounding brackets;
** `double`: Double combining characters (character + diacritic + character), without surrounding brackets;
** `vs`: Variation selectors, without surrounding brackets;
** `all`: Concatenation of `single` + `double` + `vs`, without surrounding brackets;
** `diacritics_single`: Like `single` but with surrounding brackets;
** `diacritics_double`: Like `double` but with surrounding brackets;
** `diacritics_all`: Like `all` but with surrounding brackets;
** `combined_single`: Lua pattern for matching a spacing character followed by one or more single combining characters;
** `combined_double`: Lua pattern for matching a combination of two spacing characters separated by one or more double
combining characters, possibly also with single combining characters;
* `emoji_pattern`: A Lua character class pattern (including surrounding brackets) that matches emojis. Meant to be used
with {mw.ustring.find()}.
* `L2_list`: Ordered list of L2 headings on the page, with the extra key `n` that gives the length of the list.
* `L2_sections`: Lookup table of L2 headings on the page, where the key is the section number assigned by the preprocessor, and the value is the L2 heading name. Once an invocation has got its actual section number from get_current_L2 in [[Module:pages]], it can use this table to determine its parent L2. TODO: We could expand this to include subsections, to check POS headings are correct etc.
* `unsupported_titles`: Map from pagenames to canonical titles for unsupported-title pages.
* `namespace`: Namespace of the pagename.
* `ns`: Namespace table for the page from mw.site.namespaces (TODO: merge with `namespace` above).
* `full_raw_pagename`: Full version of the '''RAW''' pagename (i.e. unsupported-title pages aren't canonicalized);
including the namespace and the base (portion before the slash).
* `pagename`: Canonicalized subpage portion of the pagename (unsupported-title pages are canonicalized).
* `pagename_with_base`: Same as `pagename` in the main namespace; otherwise, the whole pagename without the namespace.
* `decompose_pagename`: Equivalent of `pagename` in NFD decomposition.
* `pagename_len`: Length of `pagename` in Unicode chars, where combinations of spacing character + decomposed diacritic
are treated as single characters.
* `explode_pagename`: Set of characters found in `pagename`. The keys are characters (where combinations of spacing
character + decomposed diacritic are treated as single characters).
* `encoded_pagename`: FIXME: Document me.
* `pagename_defaultsort`: FIXME: Document me.
* `raw_defaultsort`: FIXME: Document me.
* `wikitext_topic_cat`: FIXME: Document me.
* `wikitext_langname_cat`: FIXME: Document me.
`no_fetch_content` says to not fetch and parse the content or set a DEFAULTSORT sort key, in order to save time on
test and documentation pages that have lots of template invocations that set `|pagename=`. It turns out nearly all the
time of this function is contained in the line `frame:callParserFunction("DEFAULTSORT", data.pagename_defaultsort)`,
so we skip it on test and documentation pages where it accomplishes nothing in any case.
]==]
function export.process_page(pagename, no_fetch_content)
local data = {
comb_chars = comb_chars,
emoji_pattern = "[" .. emoji_chars .. "]",
unsupported_titles = unsupported_titles or get_unsupported_titles()
}
local cats = {}
data.cats = cats
-- We cannot store `raw_title` in `data` because it contains a metatable.
local raw_title
local function bad_pagename()
if not pagename then
error("Internal error: Something wrong, `data.pagename` not specified but current title contains illegal characters")
else
error(format("Bad value for `data.pagename`: '%s', which must not contain illegal characters", pagename))
end
end
if pagename then -- for testing, doc pages, etc.
raw_title = new_title(pagename)
if not raw_title then
bad_pagename()
end
else
raw_title = mw.title.getCurrentTitle()
end
local nsText = raw_title.nsText
local namespace_is_reconstruction = nsText == "Reconstruction"
data.namespace = nsText
data.ns = mw.site.namespaces[raw_title.namespace]
local full_raw_pagename = raw_title.fullText
data.full_raw_pagename = full_raw_pagename
local frame = mw.getCurrentFrame()
-- WARNING: `content` may be nil, e.g. if we're substing a template like {{ja-new}} on a not-yet-created page
-- or if the module specifies the subpage as `data.pagename` (which many modules do) and we're in an Appendix
-- or other non-mainspace page. We used to make the latter an error but there are too many modules that do it,
-- and substing on a nonexistent page is totally legit, and we don't actually need to be able to access the
-- content of the page.
local content = not no_fetch_content and raw_title:getContent() or nil
-- Get the pagename.
pagename = physical_to_logical_pagename_if_mammoth(raw_title)
pagename = gsub(pagename, "^Unsupported titles/(.+)", function(m)
insert(cats, "Unsupported titles")
local title = (unsupported_titles or get_unsupported_titles())[m]
if title then
return title
end
-- Substitute pairs of "`". Those not used for escaping should be escaped as "`grave`", but might not be,
-- so if a pair don't form a match, the closing "`" should become the opening "`" of the next match attempt.
-- This has to be done manually, instead of using gsub.
local open_pos = find(m, "`")
if not open_pos then
return m
end
title = {sub(m, 1, open_pos - 1)}
while true do
local close_pos = find(m, "`", open_pos + 1)
if not close_pos then
-- Add "`" plus any remaining characters.
insert(title, sub(m, open_pos))
break
end
local escape = sub(m, open_pos, close_pos)
local ch = (unsupported_characters or get_unsupported_characters())[escape]
-- Match found, so substitute the character and move to the first "`" after the match if found, or
-- otherwise return.
if ch then
insert(title, ch)
local nxt_pos = close_pos + 1
open_pos = find(m, "`", nxt_pos)
-- Add any characters between the match and the next "`" or end.
if open_pos then
insert(title, sub(m, nxt_pos, open_pos - 1))
else
insert(title, sub(m, nxt_pos))
break
end
-- Match not found, so make the closing "`" the opening "`" of the next attempt.
else
-- Add the failed match, except for the closing "`".
insert(title, sub(m, open_pos, close_pos - 1))
open_pos = close_pos
end
end
return concat(title)
end)
-- Save pagename, as the local variable will be destructively modified.
data.pagename = pagename
if nsText == "" then
data.pagename_with_base = pagename
else
data.pagename_with_base = raw_title.text
end
-- Decompose the pagename in Unicode normalization form D.
data.decompose_pagename = toNFD(pagename)
-- Explode the current page name into a character table, taking decomposed combining characters into account.
local explode_pagename = {}
local pagename_len = 0
local function explode(char)
explode_pagename[char] = true
pagename_len = pagename_len + 1
return ""
end
pagename = ugsub(pagename, comb_chars.combined_double, explode)
pagename = gsub(ugsub(pagename, comb_chars.combined_single, explode), ".[\128-\191]*", explode)
data.explode_pagename = explode_pagename
data.pagename_len = pagename_len
-- Generate DEFAULTSORT.
data.encoded_pagename = encode_entities(data.pagename)
data.pagename_defaultsort = get_lang("mul"):makeSortKey(data.encoded_pagename)
if not no_fetch_content then
frame:callParserFunction("DEFAULTSORT", data.pagename_defaultsort)
end
data.raw_defaultsort = uupper(raw_title.text)
-- Make `L2_list` and `L2_sections`, note raw wikitext use of {{DEFAULTSORT:}} and {{DISPLAYTITLE:}}, then add categories if any unwanted L1 headings are found, the L2 headings are in the wrong order, or they don't match a canonical language name.
-- Note: HTML comments shouldn't be removed from `content` until after this step, as they can affect the result.
do
local L2_list, L2_list_len, L2_sections = {}, 0, {}
local prev, rc
local new_cats, L2_wrong_order = {}
local function handle_heading(heading)
local level = heading.level
if level > 2 then
return
end
local name = heading:get_name()
-- heading:get_name() will return nil if there are any newline characters in the preprocessed heading name (e.g. from an expanded template). In such cases, the preprocessor section count still increments (since it's calculated pre-expansion), but the heading will fail, so the L2 count shouldn't be incremented.
if name == nil then
return
end
L2_list_len = L2_list_len + 1
L2_list[L2_list_len] = name
L2_sections[heading.section] = name
-- Also add any L1s, since they terminate the preceding L2, but add a maintenance category since it's probably a mistake.
if level == 1 then
new_cats["Pages with unwanted L1 headings"] = true
end
-- Check the heading is in the right order.
-- FIXME: we need a more sophisticated sorting method which handles non-diacritic special characters (e.g. Magɨ).
if prev and not (
L2_wrong_order or
string_compare(export.get_L2_sort_key(prev), export.get_L2_sort_key(name))
) then
new_cats["Pages with language headings in the wrong order"] = true
L2_wrong_order = true
end
-- Check it's a canonical language name.
if not (langnames or get_langnames())[name] then
new_cats["Pages with nonstandard language headings"] = true
end
prev = name
end
local function handle_template(template)
-- Turn off redirect checking except in the Reconstruction namespace because the rc flag is only
-- used in the Reconstruction namespace and the other names are parser functions, which AFAIK can't
-- be redirected to.
local name = template:get_name(nil, not namespace_is_reconstruction and "no_redirect" or nil)
if name == "DEFAULTSORT:" then
new_cats["Pages with DEFAULTSORT conflicts"] = true
elseif name == "DISPLAYTITLE:" then
new_cats["Pages with DISPLAYTITLE conflicts"] = true
elseif name == "reconstructed" then
rc = true
end
end
if content then
for node in parse(content):iterate_nodes() do
local node_class = class_else_type(node)
if node_class == "heading" then
handle_heading(node)
elseif node_class == "template" then
handle_template(node)
elseif node_class == "parameter" then
new_cats["Pages with raw triple-brace template parameters"] = true
end
end
end
L2_list.n = L2_list_len
data.L2_list = L2_list
data.L2_sections = L2_sections
insert(cats, get_category("Pages with entries"))
insert(cats, get_category(format("Pages with %s entr%s", L2_list_len, L2_list_len == 1 and "y" or "ies")))
for cat in pairs(new_cats) do
insert(cats, get_category(cat))
end
if namespace_is_reconstruction and not rc then
local langname = match(full_raw_pagename, "^Reconstruction:([^/]+)/.")
if langname then
insert(cats, get_category(langname .. " entries missing Template:reconstructed"))
end
end
end
------ 4. Parse page for maintenance categories. ------
-- Use of tab characters.
if content and find(content, "\t", 1, true) then
insert(cats, get_category("Pages with tab characters"))
end
-- Unencoded character(s) in title.
local IDS = list_to_set{"⿰", "⿱", "⿲", "⿳", "⿴", "⿵", "⿶", "⿷", "⿸", "⿹", "⿺", "⿻", "", "", "", "", ""}
for char in pairs(explode_pagename) do
if IDS[char] and char ~= data.pagename then
insert(cats, "Terms containing unencoded characters")
break
end
end
-- Raw wikitext use of a topic or langname category. Also check if any raw sortkeys have been used.
do
local wikitext_topic_cat = {}
local wikitext_langname_cat = {}
local raw_sortkey
-- If a raw sortkey has been found, add it to the relevant table.
-- If there's no table (or the index is just `true`), create one first.
local function add_cat_table(t, lang, sortkey)
local t_lang = t[lang]
if not sortkey then
if not t_lang then
t[lang] = true
end
return
elseif t_lang == true or not t_lang then
t_lang = {}
t[lang] = t_lang
end
t_lang[uupper(decode_entities(sortkey))] = true
end
local function process_category(content, cat, colon, nxt)
local pipe = find(cat, "|", colon + 1, true)
-- Categories cannot end "|]]".
if pipe == #cat then
return
end
local title = new_title(pipe and sub(cat, 1, pipe - 1) or cat)
if not (title and title.namespace == 14) then
return
end
-- Get the sortkey (if any), then canonicalize category title.
local sortkey = pipe and sub(cat, pipe + 1) or nil
cat = title.text
if sortkey then
raw_sortkey = true
-- If the sortkey contains "[", the first "]" of a final "]]]" is treated as part of the sortkey.
if find(sortkey, "[", 1, true) and sub(content, nxt, nxt) == "]" then
sortkey = sortkey .. "]"
end
end
local code = match(cat, "^([%w%-.]+):")
if code then
add_cat_table(wikitext_topic_cat, code, sortkey)
return
end
-- Split by word.
cat = split(cat, " ", true, true)
-- Formerly we looked for the language name anywhere in the category. This is simply wrong
-- because there are no categories like 'Alsatian French lemmas' (only L2 languages
-- have langname categories), but doing it this way wrongly catches things like [[Category:Shapsug Adyghe]]
-- in [[Category:Adyghe entries with language name categories using raw markup]].
local n = #cat - 1
if n <= 0 then
return
end
-- Go from longest to shortest and stop once we've found a language name. Going from shortest
-- to longest or not stopping after a match risks falsely matching (e.g.) German Low German
-- categories as German.
repeat
local name = concat(cat, " ", 1, n)
if (langnames or get_langnames())[name] then
add_cat_table(wikitext_langname_cat, name, sortkey)
return
end
n = n - 1
until n == 0
end
if content then
-- Remove comments, then iterate over category links.
content = remove_comments(content, "BOTH")
local head = find(content, "[[", 1, true)
while head do
local close = find(content, "]]", head + 2, true)
if not close then
break
end
-- Make sure there are no intervening "[[" between head and close.
local open = find(content, "[[", head + 2, true)
while open and open < close do
head = open
open = find(content, "[[", head + 2, true)
end
local cat = sub(content, head + 2, close - 1)
-- Locate the colon, and weed out most unwanted links. "[ _\128-\244]*" catches valid whitespace, and ensures any category links using the colon trick are ignored. We match all non-ASCII characters, as there could be multibyte spaces, and mw.title.new will filter out any remaining false-positives; this is a lot faster than running mw.title.new on every link.
local colon = match(cat, "^[ _\128-\244]*[Cc][Aa][Tt][EeGgOoRrYy _\128-\244]*():")
if colon then
process_category(content, cat, colon, close + 2)
end
head = open
end
end
data.wikitext_topic_cat = wikitext_topic_cat
data.wikitext_langname_cat = wikitext_langname_cat
if raw_sortkey then
insert(cats, get_category("Pages with raw sortkeys"))
end
end
return data
end
return export
4bu8vdvni16bm0r3r27l04sls0geljk
Module:gender and number
828
7988
54935
54920
2026-09-29T19:37:33Z
Deadend0914
7211
54935
Scribunto
text/plain
local export = {}
local decorations_module = "Module:decorations"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local concat = table.concat
local insert = table.insert
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_decorations(...)
format_decorations = require(decorations_module).format_decorations
return format_decorations(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local gender_and_number_data
local function get_gender_and_number_data()
gender_and_number_data, get_gender_and_number_data = load_data("Module:gender and number/data"), nil
return gender_and_number_data
end
--[==[ intro:
This module creates standardised displays for gender and number. It converts a gender specification into Wiki/HTML format.
A gender/number specification consists of one or more gender/number elements, separated by hyphens. Examples are:
{"n"} (neuter gender), {"f-p"} (feminine plural), {"m-an-p"} (masculine animate plural),
{"pf"} (perfective aspect). Each gender/number element has the following properties:
# A code, as used in the spec, e.g. {"f"} for feminine, {"p"} for plural.
# A type, e.g. `gender`, `number` or `animacy`. Each element in a given spec must be of a different type.
# A display form, which in turn consists of a display code and a tooltip gloss. The display code
may not be the same as the spec code, e.g. the spec code {"an"} has display code {"anim"} and tooltip
gloss ''animate''.
# A category into which lemmas of the right part of speech are placed if they have a gender/number
spec containing the given element. For example, a noun with gender/number spec {"m-an-p"} is placed
into the categories `<var>lang</var> masculine nouns`, `<var>lang</var> animate nouns` and `<var>lang</var> pluralia tantum`.
]==]
--[==[
Version of format_genders() that can be invoked from a template.
]==]
function export.show_list(frame)
local params = {
[1] = {list = true},
["lang"] = {type = "language"},
}
local iargs = process_params(frame.args, params)
local text, cats = export.format_genders(iargs[1], iargs.lang)
if not cats then
return text
end
return text .. format_categories(cats, iargs.lang)
end
function export.format_list(...)
-- FIXME: Added 2026-09-17. Remove after 2026-10-17.
error("Use format_genders instead of format_list")
end
local function autoadd_abbr(display)
if not display then
error("Internal error: '.display' for gender/number code is missing")
end
if display:find("<abbr", nil, true) then
return display
end
return ('%s'):format(display, display)
end
--[=[
Add decorations (qualifiers, labels and references) to a formatted gender/number spec. `spec` is the object
describing the gender/number spec, which should optionally contain:
* left qualifiers in `q`, an array of strings;
* right qualifiers in `qq`, an array of strings;
* left labels in `l`, an array of strings;
* right labels in `ll`, an array of strings;
* references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
(formatted reference text) and optionally `name` and/or `group`;
`formatted` is the formatted version of the term itself, and `lang` is the optional language object passed into
format_genders().
]=]
local function add_decorations(formatted, spec, lang)
local function field_non_empty(field)
local list = spec[field]
if not list then
return nil
end
if type(list) ~= "table" then
error(("Internal error: Wrong type for `spec.%s`=%s, should be \"table\""):format(
field, mw.dumpObject(list)))
end
return list[1]
end
if field_non_empty("q") or field_non_empty("qq") or field_non_empty("l") or field_non_empty("ll") or
field_non_empty("refs") then
formatted = format_decorations {
lang = lang,
text = formatted,
q = spec.q,
qq = spec.qq,
l = spec.l,
ll = spec.ll,
refs = spec.refs,
}
end
return formatted
end
--[==[
Format one or more gender/number specifications. Each spec is either a string, e.g. {"f-p"}, or a table of the form
{ {spec = "SPEC",
q = {"LEFT_QUALIFIER", "LEFT_QUALIFIER", ...},
qq = {"RIGHT_QUALIFIER", "RIGHT_QUALIFIER", ...},
l = {"LEFT_LABEL", "LEFT_LABEL", ...},
ll = {"RIGHT_LABEL", "RIGHT_LABEL", ...},
refs = {"FORMATTED_REFERENCE_TEXT", {text = "FORMATTED_REFERENCE_TEXT", name = "REFNAME", group = "REFGROUP"}, ...},
}} In the table format, only `spec` is required, and in the `refs` object format, only `text` is required.
If `lang` is not given, the funtion returns only one value, the formatted text.
If `lang` is given, the function returns two values:
# the formatted text;
# a list of the categories to add, which will be {nil} if there are no categories to add.
If `lang` (which should be a language object) and `pos_for_cat` (which should be a plural part of speech) are given,
gender categories such as `German masculine nouns` or `Russian imperfective verbs` are added to the categories, and
request categories such as `Requests for gender in <var>lang</var> entries` or
`Requests for animacy in <var>lang</var> entries` may also be added. Otherwise, if only `lang` is given, only request
categories may be returned. If both are omitted, only one return value is returned, as mentioned above.
]==]
-- Old English localization: category wordings come from [[Module:floccnaman]] (see that module);
-- the English wording is kept when a translation is missing. Loaded lazily and optionally, so a
-- missing module can never break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
function export.format_genders(specs, lang, pos_for_cat)
local formatted_specs, categories, seen_types = {}
local all_is_nounclass = nil
local full_langname = lang and lang:getFullName() or nil
local function do_gender_spec(spec, parts)
local types = {}
local codes = (gender_and_number_data or get_gender_and_number_data()).codes
for key, code in ipairs(parts) do
-- Is this code valid?
if not codes[code] then
error('The tag "' .. code .. '" in the gender specification "' .. spec.spec ..
'" is not valid. See [[Module:gender and number]] for a list of valid tags.')
end
-- Check for multiple genders/numbers/animacies in a single spec.
local typ = codes[code].type
if typ ~= "other" and types[typ] then
error('The gender specification "' .. spec.spec .. '" contains multiple tags of type "' .. typ .. '".')
end
types[typ] = true
parts[key] = autoadd_abbr(codes[code].display)
if categories and lang and pos_for_cat then
for i, cat in ipairs(categories) do
categories[i] = cat:gsub("POS", pos_for_cat)
end
end
-- Generate categories if called for.
if lang and pos_for_cat then
local cat = codes[code].cat
if cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_word(lang, cat))
end
if not seen_types then
seen_types = {}
elseif seen_types[typ] and seen_types[typ] ~= code then
cat = (gender_and_number_data or get_gender_and_number_data()).multicode_cats[typ]
if cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_word(lang, cat))
end
end
seen_types[typ] = code
end
if lang and codes[code].req then
local type_for_req = typ
if code == "?" then
-- Keep in mind `pos_for_cat` may be nil here.
type_for_req = pos_for_cat == "verbs" and "aspect" or "gender"
end
if not categories then
categories = {}
end
insert(categories, "Requests for " .. type_for_req .. " in " .. full_langname .. " entries")
end
end
-- Add the processed codes together with non-breaking spaces
if not parts[2] and parts[1] then
return parts[1]
else
return concat(parts, " ")
end
end
for _, spec in ipairs(specs) do
if type(spec) ~= "table" then
spec = {spec = spec}
end
local spec_spec, is_nounclass = spec.spec
-- If the specification starts with cX, then it is a noun class specification.
if spec_spec:match("^%d") or spec_spec:match("^c[^-]") then
is_nounclass = true
local code = spec_spec:gsub("^c", "")
local text
if code == "?" then
text = '<abbr class="noun-class" title="noun class missing">?</abbr>'
if lang then
if not categories then
categories = {}
end
insert(categories, "Requests for noun class in " .. full_langname .. " entries")
end
else
text = '<abbr class="noun-class" title="noun class ' .. code .. '">' .. code .. "</abbr>"
if lang and pos_for_cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_word(lang, "class " .. code .. " POS"))
end
end
local text_with_decorations = add_decorations(text, spec, lang)
insert(formatted_specs, text_with_decorations)
else
-- Split the parts and iterate over each part, converting it into its display form
local parts = split(spec.spec, "-", true, true)
local combined_codes = (gender_and_number_data or get_gender_and_number_data()).combinations
if lang then
-- Check if the specification is valid
--elseif langinfo.genders then
-- local valid_genders = {}
-- for _, g in ipairs(langinfo.genders) do valid_genders[g] = true end
--
-- if not valid_genders[spec.spec] then
-- local valid_string = {}
-- for i, g in ipairs(langinfo.genders) do valid_string[i] = g end
-- error('The gender specification "' .. spec.spec .. '" is not valid for ' .. langinfo.names[1] .. ". Valid are: " .. concat(valid_string, ", "))
-- end
--end
end
local has_combined = false
for _, code in ipairs(parts) do
if combined_codes[code] then
has_combined = true
break
end
end
if not has_combined then
if formatted_specs[1] then
insert(formatted_specs, "or")
end
insert(formatted_specs, add_decorations(do_gender_spec(spec, parts), spec, lang))
else
-- This logic is to handle combined gender specs like 'mf' and 'mfbysense'.
local all_parts = {{}}
local extra_displays
local this_formatted_specs = {}
for _, code in ipairs(parts) do
if combined_codes[code] then
local new_all_parts = {}
for _, one_parts in ipairs(all_parts) do
for _, one_code in ipairs(combined_codes[code].codes) do
local new_combined_parts = deep_copy(one_parts)
insert(new_combined_parts, one_code)
insert(new_all_parts, new_combined_parts)
end
end
all_parts = new_all_parts
if lang and pos_for_cat then
local extra_cat = combined_codes[code].cat
if extra_cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_word(lang, extra_cat))
end
end
local extra_display = combined_codes[code].display
if extra_display then
if not extra_displays then
extra_displays = {}
end
insert(extra_displays, autoadd_abbr(extra_display))
end
else
for _, one_parts in ipairs(all_parts) do
insert(one_parts, code)
end
end
end
for _, this_parts in ipairs(all_parts) do
if this_formatted_specs[1] then
insert(this_formatted_specs, "or")
end
insert(this_formatted_specs, do_gender_spec(spec, this_parts))
end
if extra_displays then
for _, display in ipairs(extra_displays) do
insert(this_formatted_specs, display)
end
end
insert(formatted_specs, add_decorations(
concat(this_formatted_specs, " "), spec, lang))
end
is_nounclass = false
end
-- Ensure that the specifications are either all noun classes, or none are.
if all_is_nounclass == nil then
all_is_nounclass = is_nounclass
elseif all_is_nounclass ~= is_nounclass then
error("Noun classes and genders cannot be mixed. Please use either one or the other.")
end
end
local formatted_retval
if all_is_nounclass then
-- Add the processed codes together with slashes
formatted_retval = '<span class="gender">class ' .. concat(formatted_specs, "/") .. "</span>"
else
-- Add the processed codes together with spaces
formatted_retval = '<span class="gender">' .. concat(formatted_specs, " ") .. "</span>"
end
if lang then
return formatted_retval, categories
else
return formatted_retval
end
end
return export
m6p1huyrc6voup3hqbgc46tgkq3d7i8
54936
54935
2026-09-30T02:24:26Z
Deadend0914
7211
54936
Scribunto
text/plain
local export = {}
local decorations_module = "Module:decorations"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local concat = table.concat
local insert = table.insert
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_decorations(...)
format_decorations = require(decorations_module).format_decorations
return format_decorations(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local gender_and_number_data
local function get_gender_and_number_data()
gender_and_number_data, get_gender_and_number_data = load_data("Module:gender and number/data"), nil
return gender_and_number_data
end
--[==[ intro:
This module creates standardised displays for gender and number. It converts a gender specification into Wiki/HTML format.
A gender/number specification consists of one or more gender/number elements, separated by hyphens. Examples are:
{"n"} (neuter gender), {"f-p"} (feminine plural), {"m-an-p"} (masculine animate plural),
{"pf"} (perfective aspect). Each gender/number element has the following properties:
# A code, as used in the spec, e.g. {"f"} for feminine, {"p"} for plural.
# A type, e.g. `gender`, `number` or `animacy`. Each element in a given spec must be of a different type.
# A display form, which in turn consists of a display code and a tooltip gloss. The display code
may not be the same as the spec code, e.g. the spec code {"an"} has display code {"anim"} and tooltip
gloss ''animate''.
# A category into which lemmas of the right part of speech are placed if they have a gender/number
spec containing the given element. For example, a noun with gender/number spec {"m-an-p"} is placed
into the categories `<var>lang</var> masculine nouns`, `<var>lang</var> animate nouns` and `<var>lang</var> pluralia tantum`.
]==]
--[==[
Version of format_genders() that can be invoked from a template.
]==]
function export.show_list(frame)
local params = {
[1] = {list = true},
["lang"] = {type = "language"},
}
local iargs = process_params(frame.args, params)
local text, cats = export.format_genders(iargs[1], iargs.lang)
if not cats then
return text
end
return text .. format_categories(cats, iargs.lang)
end
function export.format_list(...)
-- FIXME: Added 2026-09-17. Remove after 2026-10-17.
error("Use format_genders instead of format_list")
end
local function autoadd_abbr(display)
if not display then
error("Internal error: '.display' for gender/number code is missing")
end
if display:find("<abbr", nil, true) then
return display
end
return ('%s'):format(display, display)
end
--[=[
Add decorations (qualifiers, labels and references) to a formatted gender/number spec. `spec` is the object
describing the gender/number spec, which should optionally contain:
* left qualifiers in `q`, an array of strings;
* right qualifiers in `qq`, an array of strings;
* left labels in `l`, an array of strings;
* right labels in `ll`, an array of strings;
* references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
(formatted reference text) and optionally `name` and/or `group`;
`formatted` is the formatted version of the term itself, and `lang` is the optional language object passed into
format_genders().
]=]
local function add_decorations(formatted, spec, lang)
local function field_non_empty(field)
local list = spec[field]
if not list then
return nil
end
if type(list) ~= "table" then
error(("Internal error: Wrong type for `spec.%s`=%s, should be \"table\""):format(
field, mw.dumpObject(list)))
end
return list[1]
end
if field_non_empty("q") or field_non_empty("qq") or field_non_empty("l") or field_non_empty("ll") or
field_non_empty("refs") then
formatted = format_decorations {
lang = lang,
text = formatted,
q = spec.q,
qq = spec.qq,
l = spec.l,
ll = spec.ll,
refs = spec.refs,
}
end
return formatted
end
--[==[
Format one or more gender/number specifications. Each spec is either a string, e.g. {"f-p"}, or a table of the form
{ {spec = "SPEC",
q = {"LEFT_QUALIFIER", "LEFT_QUALIFIER", ...},
qq = {"RIGHT_QUALIFIER", "RIGHT_QUALIFIER", ...},
l = {"LEFT_LABEL", "LEFT_LABEL", ...},
ll = {"RIGHT_LABEL", "RIGHT_LABEL", ...},
refs = {"FORMATTED_REFERENCE_TEXT", {text = "FORMATTED_REFERENCE_TEXT", name = "REFNAME", group = "REFGROUP"}, ...},
}} In the table format, only `spec` is required, and in the `refs` object format, only `text` is required.
If `lang` is not given, the funtion returns only one value, the formatted text.
If `lang` is given, the function returns two values:
# the formatted text;
# a list of the categories to add, which will be {nil} if there are no categories to add.
If `lang` (which should be a language object) and `pos_for_cat` (which should be a plural part of speech) are given,
gender categories such as `German masculine nouns` or `Russian imperfective verbs` are added to the categories, and
request categories such as `Requests for gender in <var>lang</var> entries` or
`Requests for animacy in <var>lang</var> entries` may also be added. Otherwise, if only `lang` is given, only request
categories may be returned. If both are omitted, only one return value is returned, as mentioned above.
]==]
-- Old English localization: category wordings come from [[Module:floccnaman]] (see that module);
-- the English wording is kept when a translation is missing. Loaded lazily and optionally, so a
-- missing module can never break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
-- Old English wording for a gender/number category template containing a "POS"
-- placeholder (e.g. "masculine POS"). The resolved wording is looked up as a whole
-- first, so that e.g. "masculine nouns" can be given its own entry; otherwise the
-- placeholder is replaced with the translated part of speech, but only when the
-- wording around it is known too. Anything not translated yet is kept in English in
-- full, so that no half-translated category is ever produced.
local function cat_with_pos(lang, template, pos_for_cat)
local mod = get_floccnaman()
local english = (template:gsub("POS", pos_for_cat))
if not mod then
return english
end
local resolved = mod.translate(lang, english)
if resolved then
return resolved
end
local templ_oe = mod.translate(lang, template)
local pos_oe = mod.translate(lang, pos_for_cat)
if templ_oe and templ_oe:find("POS", 1, true) and pos_oe then
return (templ_oe:gsub("POS", pos_oe))
end
return english
end
function export.format_genders(specs, lang, pos_for_cat)
local formatted_specs, categories, seen_types = {}
local all_is_nounclass = nil
local full_langname = lang and lang:getFullName() or nil
local function do_gender_spec(spec, parts)
local types = {}
local codes = (gender_and_number_data or get_gender_and_number_data()).codes
for key, code in ipairs(parts) do
-- Is this code valid?
if not codes[code] then
error('The tag "' .. code .. '" in the gender specification "' .. spec.spec ..
'" is not valid. See [[Module:gender and number]] for a list of valid tags.')
end
-- Check for multiple genders/numbers/animacies in a single spec.
local typ = codes[code].type
if typ ~= "other" and types[typ] then
error('The gender specification "' .. spec.spec .. '" contains multiple tags of type "' .. typ .. '".')
end
types[typ] = true
parts[key] = autoadd_abbr(codes[code].display)
-- Generate categories if called for.
if lang and pos_for_cat then
local cat = codes[code].cat
if cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_with_pos(lang, cat, pos_for_cat))
end
if not seen_types then
seen_types = {}
elseif seen_types[typ] and seen_types[typ] ~= code then
cat = (gender_and_number_data or get_gender_and_number_data()).multicode_cats[typ]
if cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_with_pos(lang, cat, pos_for_cat))
end
end
seen_types[typ] = code
end
if lang and codes[code].req then
local type_for_req = typ
if code == "?" then
-- Keep in mind `pos_for_cat` may be nil here.
type_for_req = pos_for_cat == "verbs" and "aspect" or "gender"
end
if not categories then
categories = {}
end
insert(categories, "Requests for " .. type_for_req .. " in " .. full_langname .. " entries")
end
end
-- Add the processed codes together with non-breaking spaces
if not parts[2] and parts[1] then
return parts[1]
else
return concat(parts, " ")
end
end
for _, spec in ipairs(specs) do
if type(spec) ~= "table" then
spec = {spec = spec}
end
local spec_spec, is_nounclass = spec.spec
-- If the specification starts with cX, then it is a noun class specification.
if spec_spec:match("^%d") or spec_spec:match("^c[^-]") then
is_nounclass = true
local code = spec_spec:gsub("^c", "")
local text
if code == "?" then
text = '<abbr class="noun-class" title="noun class missing">?</abbr>'
if lang then
if not categories then
categories = {}
end
insert(categories, "Requests for noun class in " .. full_langname .. " entries")
end
else
text = '<abbr class="noun-class" title="noun class ' .. code .. '">' .. code .. "</abbr>"
if lang and pos_for_cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_with_pos(lang, "class " .. code .. " POS", pos_for_cat))
end
end
local text_with_decorations = add_decorations(text, spec, lang)
insert(formatted_specs, text_with_decorations)
else
-- Split the parts and iterate over each part, converting it into its display form
local parts = split(spec.spec, "-", true, true)
local combined_codes = (gender_and_number_data or get_gender_and_number_data()).combinations
if lang then
-- Check if the specification is valid
--elseif langinfo.genders then
-- local valid_genders = {}
-- for _, g in ipairs(langinfo.genders) do valid_genders[g] = true end
--
-- if not valid_genders[spec.spec] then
-- local valid_string = {}
-- for i, g in ipairs(langinfo.genders) do valid_string[i] = g end
-- error('The gender specification "' .. spec.spec .. '" is not valid for ' .. langinfo.names[1] .. ". Valid are: " .. concat(valid_string, ", "))
-- end
--end
end
local has_combined = false
for _, code in ipairs(parts) do
if combined_codes[code] then
has_combined = true
break
end
end
if not has_combined then
if formatted_specs[1] then
insert(formatted_specs, "or")
end
insert(formatted_specs, add_decorations(do_gender_spec(spec, parts), spec, lang))
else
-- This logic is to handle combined gender specs like 'mf' and 'mfbysense'.
local all_parts = {{}}
local extra_displays
local this_formatted_specs = {}
for _, code in ipairs(parts) do
if combined_codes[code] then
local new_all_parts = {}
for _, one_parts in ipairs(all_parts) do
for _, one_code in ipairs(combined_codes[code].codes) do
local new_combined_parts = deep_copy(one_parts)
insert(new_combined_parts, one_code)
insert(new_all_parts, new_combined_parts)
end
end
all_parts = new_all_parts
if lang and pos_for_cat then
local extra_cat = combined_codes[code].cat
if extra_cat then
if not categories then
categories = {}
end
insert(categories, full_langname .. " " .. cat_with_pos(lang, extra_cat, pos_for_cat))
end
end
local extra_display = combined_codes[code].display
if extra_display then
if not extra_displays then
extra_displays = {}
end
insert(extra_displays, autoadd_abbr(extra_display))
end
else
for _, one_parts in ipairs(all_parts) do
insert(one_parts, code)
end
end
end
for _, this_parts in ipairs(all_parts) do
if this_formatted_specs[1] then
insert(this_formatted_specs, "or")
end
insert(this_formatted_specs, do_gender_spec(spec, this_parts))
end
if extra_displays then
for _, display in ipairs(extra_displays) do
insert(this_formatted_specs, display)
end
end
insert(formatted_specs, add_decorations(
concat(this_formatted_specs, " "), spec, lang))
end
is_nounclass = false
end
-- Ensure that the specifications are either all noun classes, or none are.
if all_is_nounclass == nil then
all_is_nounclass = is_nounclass
elseif all_is_nounclass ~= is_nounclass then
error("Noun classes and genders cannot be mixed. Please use either one or the other.")
end
end
local formatted_retval
if all_is_nounclass then
-- Add the processed codes together with slashes
formatted_retval = '<span class="gender">class ' .. concat(formatted_specs, "/") .. "</span>"
else
-- Add the processed codes together with spaces
formatted_retval = '<span class="gender">' .. concat(formatted_specs, " ") .. "</span>"
end
if lang then
return formatted_retval, categories
else
return formatted_retval
end
end
return export
pfx46ai0u06bu8vpqe3xgogaacvl5kl
Module:ang-headword
828
8016
54938
54924
2026-09-30T02:26:14Z
Deadend0914
7211
54938
Scribunto
text/plain
local export = {}
local pos_functions = {}
local lang = require("Module:languages").getByCode("ang")
local insert = table.insert
local remove = table.remove
local function get_plaintext(...)
get_plaintext = require("Module:utilities").get_plaintext
return get_plaintext(...)
end
local function track(page)
require("Module:debug").track("ang-headword/" .. page)
return true
end
local function glossary_link(anchor, text)
text = text or anchor
return "[[Appendix:Glossary#" .. anchor .. "|" .. text .. "]]"
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
-- Old English localization: category wordings come from [[Module:floccnaman]] (see that module);
-- the English wording is kept when a translation is missing. Loaded lazily and optionally, so a
-- missing module can never break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
function export.show(frame)
local NAMESPACE = mw.title.getCurrentTitle().nsText
-- unused
-- local PAGENAME = mw.loadData("Module:headword/data").pagename
local iparams = {
[1] = {required = true},
["def"] = true,
["suff_type"] = true,
}
local iargs = require("Module:parameters").process(frame.args, iparams)
local args = frame:getParent().args
local poscat = iargs[1]
local def = iargs.def
local suff_type = iargs.suff_type
local postype = nil
if suff_type then
postype = poscat .. "-" .. suff_type
else
postype = poscat
end
local data = {
lang = lang,
heads = {},
genders = {},
inflections = {},
categories = {},
no_redundant_head_cat = true, -- we want the headword specified to specify whether it has long vowels
}
if poscat == "suffixes" and suff_type then
insert(data.categories, "Englisc " .. cat_word(lang, suff_type .. "-forming suffixes"))
end
if pos_functions[postype] then
local new_poscat = pos_functions[postype](def, args, data)
if new_poscat then
poscat = new_poscat
end
end
data.pos_category = poscat
return require("Module:headword").full_headword(data)
end
local function validate_genders(genders)
for _, gspec in ipairs(genders) do
local g = gspec.spec
if g ~= "wer" and g ~= "wif" and g ~= "n" and g ~= "m-p" and g ~= "f-p" and g ~= "n-p" and g~="m" and g~="f" and g ~= "?" then
error("Invalid gender: " .. g)
end
end
end
pos_functions["nouns"] = function(def, args, data)
local params = {
["head"] = {list = true},
["id"] = true,
[1] = {type = "genders", list = "g", flatten = true, disallow_holes = true},
["g"] = {alias_of = 1, list = false},
[2] = {list = "pl", disallow_holes = true},
}
local args = require("Module:parameters").process(args, params)
data.heads = args.head
data.id = args.id
validate_genders(args[1])
data.genders = args[1]
local pl = args[2]
if pl[1] then
pl.label = "nominative plural"
insert(data.inflections, pl)
end
end
pos_functions["proper nouns"] = pos_functions["nouns"]
pos_functions["verbs"] = function(def, args, data)
local params = {
[1] = {alias_of = "head", list = false},
["head"] = {list = true},
["id"] = true,
}
local args = require("Module:parameters").process(args, params)
data.heads = args.head
data.id = args.id
end
local function adjectives(pos, def, args, data)
local list = {list = true}
local params = {
[1] = {alias_of = "head", list = false},
["head"] = list,
["comp"] = list,
[2] = {alias_of = "comp", list = false},
["sup"] = list,
[3] = {alias_of = "sup", list = false},
["adv"] = list,
["indecl"] = {type = "boolean"},
["id"] = true,
}
local args = require("Module:parameters").process(args, params)
data.heads = args.head
data.id = args.id
if args.indecl then
insert(data.inflections, {label = glossary_link("indeclinable")})
end
local comp = args.comp
if #comp > 0 then
comp.label = "comparative"
insert(data.inflections, comp)
end
local sup = args.sup
if #sup > 0 then
sup.label = "superlative"
insert(data.inflections, sup)
end
if #args.adv > 0 then
args.adv.label = "adverb"
insert(data.inflections, args.adv)
end
end
pos_functions["adjectives"] = function(def, args, data)
return adjectives("adjectives", def, args, data)
end
pos_functions["participles"] = function(def, args, data)
return adjectives("participles", def, args, data)
end
pos_functions["determiners"] = function(def, args, data)
return adjectives("determiners", def, args, data)
end
pos_functions["pronouns"] = function(def, args, data)
return adjectives("pronouns", def, args, data)
end
pos_functions["suffixes-adjective"] = function(def, args, data)
return adjectives("suffixes", def, args, data)
end
pos_functions["numerals-adjective"] = function(def, args, data)
return adjectives("numerals", def, args, data)
end
pos_functions["adverbs"] = function(def, args, data)
local list = {list = true}
local params = {
[1] = {alias_of = "head", list = false},
[2] = {alias_of = "comp", list = false},
[3] = {alias_of = "sup", list = false},
["head"] = list,
["comp"] = list,
["sup"] = list,
["id"] = true,
}
local args = require("Module:parameters").process(args, params)
data.heads = args.head
data.id = args.id
local comp, sup
if args.comp[1] == "-" then
comp = "-"
elseif #args.comp > 0 then
args.comp.label = glossary_link("comparative")
comp = args.comp
end
if args.comp[1] == "-" or args.sup[1] == "-" then
sup = "-"
elseif #args.sup > 0 then
args.sup.label = glossary_link("superlative")
sup = args.sup
end
if comp == "-" then
insert(data.inflections, {label = "not " .. glossary_link("comparable")})
insert(data.categories, "Englisc " .. cat_word(lang, "uncomparable adverbs"))
else
insert(data.inflections, comp)
end
if sup == "-" then
if comp ~= "-" then
insert(data.inflections, {label = "no " .. glossary_link("superlative")})
end
else
insert(data.inflections, sup)
end
end
pos_functions["suffixes-adverb"] = pos_functions["adverbs"]
local function get_forms(forms)
if #forms == 0 then
return nil
end
local i, attested = 1, false
while true do
local form = forms[i]
if form == nil then
return forms, attested
elseif form == "-" then
remove(forms, i)
else
if not (attested or get_plaintext(form):sub(1, 1) == "*") then
attested = true
end
i = i + 1
end
end
end
local function degree(pos, deg, other_arg, other_label, args, data)
local boolean = {type = "boolean"}
local list = {list = true}
local params = {
[1] = {alias_of = "head", list = false},
["head"] = list,
["positive"] = list,
[other_arg] = list,
["indecl"] = boolean,
["id"] = true,
}
local args = require("Module:parameters").process(args, params)
data.heads = args.head
data.id = args.id
if args.indecl then
insert(data.inflections, {label = glossary_link("indeclinable")})
end
local positive, positive_attested = get_forms(args.positive)
if positive then
if not positive_attested then
insert(data.categories, "Englisc " .. cat_word(lang, deg .. "-only " .. pos))
end
if #positive > 0 then
args.positive.label = "positive"
insert(data.inflections, args.positive)
else
insert(data.inflections, {label = "no positive form"})
end
end
local other = get_forms(args[other_arg])
if other then
if #other > 0 then
args[other_arg].label = other_label
insert(data.inflections, args[other_arg])
else
insert(data.inflections, {label = "no " .. other_label .. " form"})
end
end
-- If a lemma, return the primary part of speech ("adjectives" or
-- "adverbs"), so that the term is categorized in "Old English adjectives"
-- or "Old English adverbs". Otherwise, return nothing, so that the term
-- goes in the relevant non-lemma category (e.g. "Old English comparative
-- adjectives"), and into "Old English non-lemma forms".
if positive and not positive_attested then
return pos
end
end
pos_functions["comparative adjectives"] = function(def, args, data)
return degree("adjectives", "comparative", "sup", "superlative", args, data)
end
pos_functions["superlative adjectives"] = function(def, args, data)
return degree("adjectives", "superlative", "comp", "comparative", args, data)
end
pos_functions["comparative adverbs"] = function(def, args, data)
return degree("adverbs", "comparative", "sup", "superlative", args, data)
end
pos_functions["superlative adverbs"] = function(def, args, data)
return degree("adverbs", "superlative", "comp", "comparative", args, data)
end
local function non_lemma_forms(def, args, data)
local params = {
[1] = {required = true, default = def}, -- headword or cases
["head"] = {list = true, require_index = true},
["g"] = {list = true},
["id"] = true,
}
local args = require("Module:parameters").process(args, params)
local heads = {args[1]}
for _, head in ipairs(args.head) do
insert(heads, head)
end
data.heads = heads
data.genders = args.g
data.id = args.id
end
pos_functions["noun forms"] = non_lemma_forms
pos_functions["proper noun forms"] = non_lemma_forms
pos_functions["pronoun forms"] = non_lemma_forms
pos_functions["verb forms"] = non_lemma_forms
pos_functions["adjective forms"] = non_lemma_forms
pos_functions["participle forms"] = non_lemma_forms
pos_functions["determiner forms"] = non_lemma_forms
pos_functions["numeral forms"] = non_lemma_forms
pos_functions["suffix forms"] = non_lemma_forms
return export
1ammk5ygb53a01n58205mr5si66nnfw
Module:headword
828
8019
54929
54770
2026-09-29T18:48:06Z
Deadend0914
7211
54929
Scribunto
text/plain
local export = {}
-- Named constants for all modules used, to make it easier to swap out sandbox versions.
local debug_track_module = "Module:debug/track"
local decorations_module = "Module:decorations"
local en_utilities_module = "Module:en-utilities"
local gender_and_number_module = "Module:gender and number"
local headword_data_module = "Module:headword/data"
local headword_page_module = "Module:headword/page"
local links_module = "Module:links"
local load_module = "Module:load"
local pages_module = "Module:pages"
local palindromes_module = "Module:palindromes"
local scripts_module = "Module:scripts"
local scripts_data_module = "Module:scripts/data"
local script_utilities_module = "Module:script utilities"
local script_utilities_data_module = "Module:script utilities/data"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
-- Old English localization: category wordings come from [[Module:floccnaman]] (see that module for
-- the rules); the English wording is kept when a translation is missing. Loaded lazily and
-- optionally, so a missing module can never break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
local concat = table.concat
local dump = mw.dumpObject
local insert = table.insert
local ipairs = ipairs
local max = math.max
local new_title = mw.title.new
local pairs = pairs
local require = require
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local type = type
local ufind = mw.ustring.find
local ugmatch = mw.ustring.gmatch
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
--[==[
Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==]
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function contains(...)
contains = require(table_module).contains
return contains(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_genders(...)
format_genders = require(gender_and_number_module).format_genders
return format_genders(...)
end
local function format_decorations(...)
format_decorations = require(decorations_module).format_decorations
return format_decorations(...)
end
local function full_link(...)
full_link = require(links_module).full_link
return full_link(...)
end
local function get_current_L2(...)
get_current_L2 = require(pages_module).get_current_L2
return get_current_L2(...)
end
local function get_link_page(...)
get_link_page = require(links_module).get_link_page
return get_link_page(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function is_palindrome(...)
is_palindrome = require(palindromes_module).is_palindrome
return is_palindrome(...)
end
local function language_link(...)
language_link = require(links_module).language_link
return language_link(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function pluralize(...)
pluralize = require(en_utilities_module).pluralize
return pluralize(...)
end
local function process_page(...)
process_page = require(headword_page_module).process_page
return process_page(...)
end
local function remove_links(...)
remove_links = require(links_module).remove_links
return remove_links(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_transcription(...)
tag_transcription = require(script_utilities_module).tag_transcription
return tag_transcription(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
--[==[
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
local m_data
local function get_data()
m_data = load_data(headword_data_module)
return m_data
end
local script_data
local function get_script_data()
script_data = load_data(scripts_data_module)
return script_data
end
local script_utilities_data
local function get_script_utilities_data()
script_utilities_data = load_data(script_utilities_data_module)
return script_utilities_data
end
-- If set to true, categories always appear, even in non-mainspace pages
local test_force_categories = false
-- Add a tracking category to track entries with certain (unusually undesirable) properties. `track_id` is an identifier
-- for the particular property being tracked and goes into the tracking page. Specifically, this adds a link in the
-- page text to [[Wiktionary:Tracking/headword/TRACK_ID]], meaning you can find all entries with the `track_id` property
-- by visiting [[Special:WhatLinksHere/Wiktionary:Tracking/headword/TRACK_ID]].
--
-- If `lang` (a language object) is given, an additional tracking page [[Wiktionary:Tracking/headword/TRACK_ID/CODE]] is
-- linked to where CODE is the language code of `lang`, and you can find all entries in the combination of `track_id`
-- and `lang` by visiting [[Special:WhatLinksHere/Wiktionary:Tracking/headword/TRACK_ID/CODE]]. This makes it possible to
-- isolate only the entries with a specific tracking property that are in a given language. Note that if `lang`
-- references at etymology-only language, both that language's code and its full parent's code are tracked.
local function track(track_id, lang)
local tracking_page = "headword/" .. track_id
if lang and lang:hasType("etymology-only") then
debug_track{tracking_page, tracking_page .. "/" .. lang:getCode(),
tracking_page .. "/" .. lang:getFullCode()}
elseif lang then
debug_track{tracking_page, tracking_page .. "/" .. lang:getCode()}
else
debug_track(tracking_page)
end
return true
end
local function text_in_script(text, script_code)
local sc = get_script(script_code)
if not sc then
error("Internal error: Bad script code " .. script_code)
end
local characters = sc.characters
local out
if characters then
text = ugsub(text, "%W", "")
out = ufind(text, "[" .. characters .. "]")
end
if out then
return true
else
return false
end
end
local spacingPunctuation = "[%s%p]+"
--[[ List of punctuation or spacing characters that are found inside of words.
Used to exclude characters from the regex above. ]]
local wordPunc = "-#%%&@־׳״'.·*’་•:᠊"
local notWordPunc = "[^" .. wordPunc .. "]+"
--[=[
Format a term (either a head term or an inflection term) along with any decorations (left or right qualifiers, labels,
references or customized separator). `part` is the object specifying the term (and `lang` the language of the term),
which should optionally contain:
* left qualifiers in `q`, an array of strings;
* right qualifiers in `qq`, an array of strings;
* left labels in `l`, an array of strings;
* right labels in `ll`, an array of strings;
* references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
(formatted reference text) and optionally `name` and/or `group`;
* a separator in `separator`, defaulting to " <i>or</i> " if this is not the first term (j > 1), otherwise "".
`formatted` is the formatted version of the term itself, and `j` is the index of the term.
]=]
local function format_term_with_decorations(lang, part, formatted, j)
local function part_non_empty(field)
local list = part[field]
if not list then
return nil
end
if type(list) ~= "table" then
error(("Internal error: Wrong type for `part.%s`=%s, should be \"table\""):format(field, dump(list)))
end
return list[1]
end
if part_non_empty("q") or part_non_empty("qq") or part_non_empty("l") or
part_non_empty("ll") or part_non_empty("refs") then
formatted = format_decorations {
lang = lang,
text = formatted,
q = part.q,
qq = part.qq,
l = part.l,
ll = part.ll,
refs = part.refs,
}
end
local separator = part.separator or j > 1 and " <i>or</i> " -- use "" to request no separator
if separator then
formatted = separator .. formatted
end
return formatted
end
--[==[Return true if the given head is multiword according to the algorithm used in full_headword().]==]
function export.head_is_multiword(head)
for possibleWordBreak in ugmatch(head, spacingPunctuation) do
if umatch(possibleWordBreak, notWordPunc) then
return true
end
end
return false
end
do
local function workaround_to_exclude_chars(s)
return (ugsub(s, notWordPunc, "\2%1\1"))
end
--[==[
Add appropriate links to `head`, correctly handling multiword terms. This is intended for multiword terms but can
be used for any term if you want links added to single-word terms as well. If you want to only add
links to multiword terms, first check that the term is multiword using `head_is_multiword`.
If `default` is specified, this will escape colons so that they don't get interpreted as interwiki links. This
should generally only be used when `head` is an actual pagename or is taken from a {{para|pagename}} parameter, not
when taken from a {{para|head}} parameter.
]==]
function export.add_multiword_links(head, default)
head = "\1" .. ugsub(head, spacingPunctuation, workaround_to_exclude_chars) .. "\2"
if default then
head = head
:gsub("(\1[^\2]*)\\([:#][^\2]*\2)", "%1\\\\%2")
:gsub("(\1[^\2]*)([:#][^\2]*\2)", "%1\\%2")
end
--Escape any remaining square brackets to stop them breaking links (e.g. "[citation needed]").
head = encode_entities(head, "[]", true, true)
--[=[
use this when workaround is no longer needed:
head = "[[" .. ugsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]"
Remove any empty links, which could have been created above
at the beginning or end of the string.
]=]
return (head
:gsub("\1\2", "")
:gsub("[\1\2]", {["\1"] = "[[", ["\2"] = "]]"}))
end
end
local function non_categorizable(full_raw_pagename)
return full_raw_pagename:find("^Appendix:Gestures/") or
-- Unsupported titles with descriptive names.
(full_raw_pagename:find("^Unsupported titles/") and not full_raw_pagename:find("`"))
end
local function tag_text_and_add_decorations(data, head, formatted, j)
-- Add language and script wrapper.
formatted = tag_text(formatted, data.lang, head.sc, "head", nil, j == 1 and data.id or nil)
-- Add decorations (qualifiers, labels, references and separator).
return format_term_with_decorations(data.lang, head, formatted, j)
end
-- Format a headword with transliterations.
local function format_headword(data)
-- Are there non-empty transliterations?
local has_translits = false
local has_manual_translits = false
------ Format the headwords. ------
local head_parts = {}
local unique_head_parts = {}
local has_multiple_heads = not not data.heads[2]
for j, head in ipairs(data.heads) do
if head.tr or head.ts then
has_translits = true
end
if head.tr and head.tr_manual or head.ts then
has_manual_translits = true
end
local formatted
-- Apply processing to the headword, for formatting links and such.
if head.term:find("[[", nil, true) and head.sc:getCode() ~= "Image" then
formatted = language_link{term = head.term, lang = data.lang}
else
formatted = data.lang:makeDisplayText(head.term, head.sc, true)
end
local head_part = tag_text_and_add_decorations(data, head, formatted, j)
insert(head_parts, head_part)
-- If multiple heads, try to determine whether all heads display the same. To do this we need to effectively
-- rerun the text tagging and addition of decorations, using 1 for all indices.
if has_multiple_heads then
local unique_head_part
if j == 1 then
unique_head_part = head_part
else
unique_head_part = tag_text_and_add_decorations(data, head, formatted, 1)
end
unique_head_parts[unique_head_part] = true
end
end
local set_size = 0
if has_multiple_heads then
for _ in pairs(unique_head_parts) do
set_size = set_size + 1
end
end
if set_size == 1 then
head_parts = head_parts[1]
else
head_parts = concat(head_parts)
end
if has_manual_translits then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/manual-tr]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/manual-tr/LANGCODE]]
track("manual-tr", data.lang)
end
------ Format the transliterations and transcriptions. ------
local translits_formatted
if has_translits then
local translit_parts = {}
for _, head in ipairs(data.heads) do
if head.tr or head.ts then
local this_parts = {}
if head.tr then
insert(this_parts, tag_translit(head.tr, data.lang:getCode(), "head", nil, head.tr_manual))
if head.ts then
insert(this_parts, " ")
end
end
if head.ts then
insert(this_parts, "/" .. tag_transcription(head.ts, data.lang:getCode(), "head") .. "/")
end
insert(translit_parts, concat(this_parts))
end
end
translits_formatted = " (" .. concat(translit_parts, " <i>or</i> ") .. ")"
local function format_transliteration_page_link(langname)
local transliteration_pagename = langname .. " transliteration"
local transliteration_page = new_title(transliteration_pagename, "Wiktionary")
if transliteration_page and transliteration_page:getContent() then
return ("[[Wiktionary:%s|•]]"):format(transliteration_pagename)
end
return nil
end
local translit_page_link = format_transliteration_page_link(data.lang:getCanonicalName())
-- If data.lang is an etymology-only language and we didn't find a translation page for it, fall back to the
-- full parent.
if not translit_page_link and data.lang:hasType("etymology-only") then
translit_page_link = format_transliteration_page_link(data.lang:getFullName())
end
if translit_page_link then
translits_formatted = " " .. translit_page_link .. translits_formatted
end
else
translits_formatted = ""
end
------ Paste heads and transliterations/transcriptions. ------
local lemma_gloss
if data.gloss then
lemma_gloss = ' <span class="ib-content qualifier-content">' .. data.gloss .. '</span>'
else
lemma_gloss = ""
end
return head_parts .. translits_formatted .. lemma_gloss
end
local function format_headword_genders(data, is_varform_only)
local retval = ""
if data.genders and data.genders[1] then
if data.gloss then
retval = ","
end
local pos_for_cat
if not data.nogendercat and not is_varform_only then
local no_gender_cat = (m_data or get_data()).no_gender_cat
if not (no_gender_cat[data.lang:getCode()] or no_gender_cat[data.lang:getFullCode()]) then
pos_for_cat = (m_data or get_data()).pos_for_gender_number_cat[data.pos_category:gsub("^reconstructed ", "")]
end
end
local text, cats = format_genders(data.genders, data.lang, pos_for_cat)
if cats then
extend(data.categories, cats)
end
retval = retval .. " " .. text
end
return retval
end
-- Forward reference
local format_inflections
local function format_inflection_parts(data, parts)
for j, part in ipairs(parts) do
if type(part) ~= "table" then
part = {term = part}
end
local partaccel = part.accel
local face = part.face or "bold"
if face ~= "bold" and face ~= "plain" and face ~= "hypothetical" then
error("The face `" .. face .. "` " .. (
(script_utilities_data or get_script_utilities_data()).faces[face] and
"should not be used for non-headword terms on the headword line." or
"is invalid."
))
end
-- Here the final part 'or data.nolinkinfl' allows to have 'nolinkinfl=true'
-- right into the 'data' table to disable inflection links of the entire headword
-- when inflected forms aren't entry-worthy, e.g.: in Vulgar Latin
local nolinkinfl = part.face == "hypothetical" or (part.nolink and track("nolink") or part.nolinkinfl) or (
data.nolink and track("nolink") or data.nolinkinfl)
local formatted
if part.label then
-- FIXME: There should be a better way of italicizing a label. As is, this isn't customizable.
formatted = "<i>" .. part.label .. "</i>"
else
-- Convert the term into a full link. Don't show a transliteration here unless enable_auto_translit is
-- requested, either at the `parts` level (i.e. per inflection) or at the `data.inflections` level (i.e.
-- specified for all inflections). This is controllable in {{head}} using autotrinfl=1 for all inflections,
-- or fNautotr=1 for an individual inflection (remember that a single inflection may be associated with
-- multiple terms). The reason for doing this is to avoid clutter in headword lines by default in languages
-- where the script is relatively straightforward to read by learners (e.g. Greek, Russian), but allow it
-- to be enabled in languages with more complex scripts (e.g. Arabic).
--
-- FIXME: With nested inflections, should we also respect `enable_auto_translit` at the top level of the
-- nested inflections structure?
local tr = part.tr or not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil
local postprocess_annotations
if part.inflections then
postprocess_annotations = function(infldata)
insert(infldata.annotations, format_inflections(data, part.inflections))
end
end
formatted = full_link(
{
term = not nolinkinfl and part.term or nil,
alt = part.alt or (nolinkinfl and part.term or nil),
lang = part.lang or data.lang,
sc = part.sc or parts.sc or nil,
gloss = part.gloss,
pos = part.pos,
lit = part.lit,
id = part.id,
genders = part.genders,
tr = tr,
ts = part.ts,
accel = partaccel or parts.accel,
postprocess_annotations = postprocess_annotations,
},
face
)
end
parts[j] = format_term_with_decorations(part.lang or data.lang, part,
formatted, j)
end
local parts_output
if parts[1] then
parts_output = (parts.label and " " or "") .. concat(parts)
elseif parts.request then
parts_output = " <small>[please provide]</small>"
insert(data.categories, "Requests for inflections in " .. data.lang:getFullName() .. " entries")
else
parts_output = ""
end
local parts_label = parts.label and ("<i>" .. parts.label .. "</i>") or ""
return format_term_with_decorations(data.lang, parts, parts_label .. parts_output, 1)
end
-- Format the inflections following the headword or nested after a given inflection. Declared local above.
function format_inflections(data, inflections)
if inflections and inflections[1] then
-- Format each inflection individually.
for key, infl in ipairs(inflections) do
inflections[key] = format_inflection_parts(data, infl)
end
return concat(inflections, ", ")
else
return ""
end
end
-- Format the top-level inflections following the headword. Currently this just adds parens around the
-- formatted comma-separated inflections in `data.inflections`.
local function format_top_level_inflections(data)
local result = format_inflections(data, data.inflections)
if result ~= "" then
return " (" .. result .. ")"
else
return result
end
end
-- Forward reference
local check_red_link_inflections
-- Check a single inflection (which consists of a label and zero or more terms, each possibly with nested inflections)
-- for red links. If so, insert a red-link category based on `plpos` (the plural part of speech to insert in the
-- category), stop further processing, and return true. If no red links found, return false.
local function check_red_link_inflection_parts(data, parts, plpos)
for _, part in ipairs(parts) do
if type(part) ~= "table" then
part = {term = part}
end
local term = part.term
if term and not term:find("%[%[") then
local stripped_physical_term = get_link_page(term, data.lang, part.sc or parts.sc or nil)
if stripped_physical_term then
local title = mw.title.new(stripped_physical_term)
if title and not title:getContent() then
insert(data.categories, data.lang:getFullName() .. " " .. plpos .. " with red links in their headword lines")
return true
end
end
end
if part.inflections then
if check_red_link_inflections(data, part.inflections, plpos) then
return true
end
end
end
return false
end
-- Check a set of inflections (each of which describes a single inflection of the term, such as feminine or plural, and
-- consists of a label and zero or more terms, each possibly with nested inflections) for red links. If so, insert a
-- red-link category based on `plpos` (the plural part of speech to insert in the category), stop further processing,
-- and return true. If no red links found, return false.
function check_red_link_inflections(data, inflections, plpos)
if inflections and inflections[1] then
-- Check each inflection individually.
for key, infl in ipairs(inflections) do
if check_red_link_inflection_parts(data, infl, plpos) then
return true
end
end
end
return false
end
-- Check the top-level inflections in `data.inflections`, along with any nested inflections, for red links. If so,
-- insert a red-link category based on `plpos` (the plural part of speech to insert in the category), stop further
-- processing, and return true. If no red links found, return false.
local function check_red_link_inflections_top_level(data, plpos)
return check_red_link_inflections(data, data.inflections, plpos)
end
--[==[
Returns the plural form of `pos`, a raw part of speech input, which could be singular or
plural. Irregular plural POS are taken into account (e.g. "kanji" pluralizes to
"kanji").
]==]
function export.pluralize_pos(pos)
-- Make the plural form of the part of speech
return (m_data or get_data()).irregular_plurals[pos] or
pos:sub(-1) == "s" and pos or
pluralize(pos)
end
--[==[
Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil
if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.).
If you have a POS in its singular form, call {export.pluralize_pos()} above to pluralize it
in a smart fashion that knows when to add "-s" and when to add "-es", and also takes
into account any irregular plurals.
If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess
based on whether it ends in " forms"; otherwise, return nil.
]==]
function export.pos_lemma_or_nonlemma(plpos, best_guess)
local m_headword_data = m_data or get_data()
local isLemma = m_headword_data.lemmas
-- Is it a lemma category?
if isLemma[plpos] then
return "lemma"
end
local plpos_no_recon = plpos:gsub("^reconstructed ", "")
if isLemma[plpos_no_recon] then
return "lemma"
end
-- Is it a nonlemma category?
local isNonLemma = m_headword_data.nonlemmas
if isNonLemma[plpos] or isNonLemma[plpos_no_recon] then
return "non-lemma form"
end
local plpos_no_mut = plpos:gsub("^mutated ", "")
if isLemma[plpos_no_mut] or isNonLemma[plpos_no_mut] then
return "non-lemma form"
elseif best_guess then
return plpos:find(" forms$") and "non-lemma form" or "lemma"
else
return nil
end
end
--[==[
Canonicalize a part of speech as specified in 2= in {{tl|head}}. This checks for POS aliases and non-lemma form
aliases ending in 'f', and then pluralizes if the POS term does not have an invariable plural.
]==]
function export.canonicalize_pos(pos)
-- FIXME: Temporary code to throw an error for alias 'pre' (= preposition) that will go away.
if pos == "pre" then
-- Don't throw error on 'pref' as it's an alias for "prefix".
error("POS 'pre' for 'preposition' no longer allowed as it's too ambiguous; use 'prep'")
end
-- Likewise for pro = pronoun.
if pos == "pro" or pos == "prof" then
error("POS 'pro' for 'pronoun' no longer allowed as it's too ambiguous; use 'pron'")
end
local m_headword_data = m_data or get_data()
if m_headword_data.pos_aliases[pos] then
pos = m_headword_data.pos_aliases[pos]
elseif pos:sub(-1) == "f" then
pos = pos:sub(1, -2)
pos = (m_headword_data.pos_aliases[pos] or pos) .. " forms"
end
return export.pluralize_pos(pos)
end
-- Find and return the maximum index in the array `data[element]` (which may have gaps in it), and initialize it to a
-- zero-length array if unspecified. Check to make sure all keys are numeric (other than "maxindex", which is set by
-- [[Module:parameters]] for list parameters), all values are strings, and unless `allow_blank_string` is given,
-- no blank (zero-length) strings are present.
local function init_and_find_maximum_index(data, element, allow_blank_string)
local maxind = 0
if not data[element] then
data[element] = {}
end
local typ = type(data[element])
if typ ~= "table" then
error(("Internal error: In full_headword(), `data.%s` must be an array but is a %s"):format(element, typ))
end
for k, v in pairs(data[element]) do
if k ~= "maxindex" then
if type(k) ~= "number" then
error(("Internal error: Unrecognized non-numeric key '%s' in `data.%s`"):format(k, element))
end
if k > maxind then
maxind = k
end
if v then
if type(v) ~= "string" then
error(("Internal error: For key '%s' in `data.%s`, value should be a string but is a %s"):format(k, element, type(v)))
end
if not allow_blank_string and v == "" then
error(("Internal error: For key '%s' in `data.%s`, blank string not allowed; use 'false' for the default"):format(k, element))
end
end
end
end
return maxind
end
--[==[
-- Add the page to various maintenance categories for the language and the
-- whole page. These are placed in the headword somewhat arbitrarily, but
-- mainly because headword templates are mandatory for entries (meaning that
-- in theory it provides full coverage).
--
-- This is provided as an external entry point so that modules which transclude
-- information from other entries (such as {{tl|ja-see}}) can take advantage
-- of this feature as well, because they are used in place of a conventional
-- headword template.]==]
do
-- Handle any manual sortkeys that have been specified in raw categories
-- by tracking if they are the same or different from the automatically-
-- generated sortkey, so that we can track them in maintenance
-- categories.
local function handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
sortkey = sortkey or lang:makeSortKey(page.pagename)
-- If there are raw categories with no sortkey, then they will be
-- sorted based on the default MediaWiki sortkey, so we check against
-- that.
if tbl == true then
if page.raw_defaultsort ~= sortkey then
insert(lang_cats, lang:getFullName() .. " terms with non-redundant non-automated sortkeys")
end
return
end
local redundant, different
for k in pairs(tbl) do
if k == sortkey then
redundant = true
else
different = true
end
end
if redundant then
insert(lang_cats, lang:getFullName() .. " terms with redundant sortkeys")
end
if different then
insert(lang_cats, lang:getFullName() .. " terms with non-redundant non-automated sortkeys")
end
return sortkey
end
function export.maintenance_cats(page, lang, lang_cats, page_cats)
extend(page_cats, page.cats)
lang = lang:getFull() -- since we are just generating categories
local canonical = lang:getCanonicalName()
local tbl = page.wikitext_topic_cat[lang:getCode()]
local sortkey = nil
if tbl then
sortkey = handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
insert(lang_cats, canonical .. " entries with topic categories using raw markup")
end
tbl = page.wikitext_langname_cat[canonical]
if tbl then
handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
insert(lang_cats, canonical .. " entries with language name categories using raw markup")
end
if get_current_L2() ~= canonical then
insert(lang_cats, canonical .. " entries with incorrect language header")
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/incorrect language header]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/incorrect language header/LANGCODE]]
track("incorrect language header", lang)
end
end
end
--[==[This is the primary external entry point.
{{lua|full_headword(data)}}
This is used by {{temp|head}} and various language-specific headword templates (e.g. {{temp|ru-adj}} for Russian adjectives, {{temp|de-noun}} for German nouns, etc.) to display an entire headword line.
See [[#Further explanations for full_headword()]]
]==]
function export.full_headword(data)
-- Prevent data from being destructively modified.
data = shallow_copy(data)
------------ 1. Basic checks for old-style (multi-arg) calling convention. ------------
if data.getCanonicalName then
error("Internal error: In full_headword(), the first argument `data` needs to be a Lua object (table) of properties, not a language object")
end
if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then
error("Internal error: In full_headword(), the first argument `data` needs to be a Lua object (table) and `data.lang` must be a language object")
end
if data.id and type(data.id) ~= "string" then
error("Internal error: The id in the data table should be a string.")
end
------------ 2. Initialize pagename etc. ------------
local langcode = data.lang:getCode()
local full_langcode = data.lang:getFullCode()
local langname = data.lang:getCanonicalName()
local full_langname = data.lang:getFullName()
local raw_pagename = data.pagename
local page
local m_headword_data = m_data or get_data()
if raw_pagename and raw_pagename ~= m_headword_data.pagename then -- for testing, doc pages, etc.
-- data.pagename is often set on documentation and test pages through the pagename= parameter of various
-- templates, to emulate running on that page. Having a large number of such test templates on a single
-- page often leads to timeouts, because we fetch and parse the contents of each page in turn. However,
-- we don't really need to do that and can function fine without fetching and parsing the contents of a
-- given page, so turn off content fetching/parsing (and also setting the DEFAULTSORT key through a parser
-- function, which is *slooooow*) in certain namespaces where test and documentation templates are likely to
-- be found and where actual content does not live (User, Template, Module).
local actual_namespace = m_headword_data.page.namespace
local no_fetch_content = actual_namespace == "User" or actual_namespace == "Template" or
actual_namespace == "Module"
page = process_page(raw_pagename, no_fetch_content)
else
page = m_headword_data.page
end
local namespace = page.namespace
if data.altform then
-- Temporary tracking for use of old altform=
track("altform", data.lang)
end
local noposcat = data.noposcat
local is_varform_only = data.var and data.var ~= "both"
local is_varform_both = data.var == "both"
------------ 3. Initialize `data.heads` table; if old-style, convert to new-style. ------------
if type(data.heads) == "table" and type(data.heads[1]) == "table" then
-- new-style
if data.translits or data.transcriptions then
error("Internal error: In full_headword(), if `data.heads` is new-style (array of head objects), `data.translits` and `data.transcriptions` cannot be given")
end
else
-- convert old-style `heads`, `translits` and `transcriptions` to new-style
local maxind = max(
init_and_find_maximum_index(data, "heads"),
init_and_find_maximum_index(data, "translits", true),
init_and_find_maximum_index(data, "transcriptions", true)
)
for i = 1, maxind do
data.heads[i] = {
term = data.heads[i],
tr = data.translits[i],
ts = data.transcriptions[i],
}
end
end
-- Make sure there's at least one head.
if not data.heads[1] then
data.heads[1] = {}
end
------------ 4. Initialize and validate `data.categories` and `data.whole_page_categories`, and determine `pos_category` if not given, and add basic categories. ------------
init_and_find_maximum_index(data, "categories")
init_and_find_maximum_index(data, "whole_page_categories")
local pos_category_already_present = false
if data.categories[1] then
local escaped_langname = pattern_escape(full_langname)
local matches_lang_pattern = "^" .. escaped_langname .. " "
for _, cat in ipairs(data.categories) do
-- Does the category begin with the language name? If not, tag it with a tracking category.
if not cat:find(matches_lang_pattern) then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/no lang category]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/no lang category/LANGCODE]]
track("no lang category", data.lang)
end
end
-- If `pos_category` not given, try to infer it from the first specified category. If this doesn't work, we
-- throw an error below.
if not data.pos_category and data.categories[1]:find(matches_lang_pattern) then
data.pos_category = data.categories[1]:gsub(matches_lang_pattern, "")
-- Optimization to avoid inserting category already present.
pos_category_already_present = true
end
end
if not data.pos_category then
error("Internal error: `data.pos_category` not specified and could not be inferred from the categories given in "
.. "`data.categories`. Either specify the plural part of speech in `data.pos_category` "
.. "(e.g. \"proper nouns\") or ensure that the first category in `data.categories` is formed from the "
.. "language's canonical name plus the plural part of speech (e.g. \"Norwegian Bokmål proper nouns\")."
)
end
-- Insert a category at the beginning for the part of speech unless it's already present or `data.noposcat` given.
if not (pos_category_already_present or noposcat or is_varform_only) then
local pos_category = full_langname .. " " .. cat_word(data.lang, data.pos_category)
-- FIXME: [[User:Theknightwho]] Why is this special case here? Please add an explanatory comment.
if pos_category ~= "Translingual Han characters" then
insert(data.categories, 1, pos_category)
end
end
-- Try to determine whether the part of speech refers to a lemma or a non-lemma form; if we can figure this out,
-- add an appropriate category.
local postype = export.pos_lemma_or_nonlemma(data.pos_category)
if not postype then
-- We don't know what this category is, so tag it with a tracking category.
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/LANGCODE]]
track("unrecognized pos", data.lang)
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/POS]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/POS/LANGCODE]]
track("unrecognized pos/pos/" .. data.pos_category, data.lang)
elseif not (noposcat or is_varform_only or data.nolemmacat) then
insert(data.categories, 1, full_langname .. " " .. cat_word(data.lang, postype .. "s"))
end
-- Categorize variant forms into 'variant lemmas' or 'variant non-lemma forms'. Originally proposed in
-- [[Wiktionary:Beer parlour/2024/June#Decluttering the altform mess]] as 'alternative forms'; renamed in
-- [[Wiktionary:Beer parlour/2026/July#Renaming the "alternative forms" categories]].
if (is_varform_only or is_varform_both) and postype then
insert(data.categories, 1, full_langname .. " " .. cat_word(data.lang, "variant " .. postype .. "s"))
end
------------ 5. Create a default headword, and add links to multiword page names. ------------
-- Determine if this is an "anti-asterisk" term, i.e. an attested term in a language that must normally be
-- reconstructed.
local is_anti_asterisk = data.heads[1].term and data.heads[1].term:find("^!!")
local lang_reconstructed = data.lang:hasType("reconstructed")
if is_anti_asterisk then
if not lang_reconstructed then
error("Anti-asterisk feature (head= beginning with !!) can only be used with reconstructed languages")
end
if namespace == "Reconstruction" then
error("Anti-asterisk feature (head= beginning with !!) should be used in mainspace, not in Reconstruction space")
end
lang_reconstructed = false
end
-- Determine if term is reconstructed
local is_reconstructed = namespace == "Reconstruction" or lang_reconstructed
-- Create a default headword based on the pagename, which is determined in
-- advance by the data module so that it only needs to be done once.
local default_head = page.pagename
-- Add links to multi-word page names when appropriate
if not (is_reconstructed or data.nolinkhead) then
local no_links = m_headword_data.no_multiword_links
if not (no_links[langcode] or no_links[full_langcode]) and export.head_is_multiword(default_head) then
default_head = export.add_multiword_links(default_head, true)
end
end
if is_reconstructed then
default_head = "*" .. default_head
end
------------ 6. Check the namespace against the language type. ------------
if namespace == "" then
if lang_reconstructed then
error("Entries in " .. langname .. " must be placed in the Reconstruction: namespace")
elseif data.lang:hasType("appendix-constructed") then
error("Entries in " .. langname .. " must be placed in the Appendix: namespace")
end
elseif namespace == "Citations" or namespace == "Thesaurus" then
error("Headword templates should not be used in the " .. namespace .. ": namespace.")
end
------------ 7. Fill in missing values in `data.heads`. ------------
-- True if any script among the headword scripts has spaces in it.
local any_script_has_spaces = false
-- True if any term has a redundant head= param.
local has_redundant_head_param = false
for _, head in ipairs(data.heads) do
------ 7a. If missing head, replace with default head.
if not head.term then
head.term = default_head
elseif head.term == default_head then
has_redundant_head_param = true
elseif is_anti_asterisk and head.term == "!!" then
-- If explicit head=!! is given, it's an anti-asterisk term and we fill in the default head.
head.term = "!!" .. default_head
elseif head.term:find("^[!?]$") then
-- If explicit head= just consists of ! or ?, add it to the end of the default head.
head.term = default_head .. head.term
end
head.term_no_initial_bang_bang = is_anti_asterisk and head.term:sub(3) or head.term
if is_reconstructed then
local head_term = head.term
if head_term:find("%[%[") then
head_term = remove_links(head_term)
end
if head_term:sub(1, 1) ~= "*" then
error("The headword '" .. head_term .. "' must begin with '*' to indicate that it is reconstructed.")
end
end
------ 7b. Try to detect the script(s) if not provided. If a per-head script is provided, that takes precedence,
------ otherwise fall back to the overall script if given. If neither given, autodetect the script.
local auto_sc = data.lang:findBestScript(head.term)
if (
auto_sc:getCode() == "None" and
find_best_script_without_lang(head.term):getCode() ~= "None"
) then
insert(data.categories, full_langname .. " terms in nonstandard scripts")
end
if not (head.sc or data.sc) then -- No script code given, so use autodetected script.
head.sc = auto_sc
else
if not head.sc then -- Overall script code given.
head.sc = data.sc
end
-- Track uses of sc parameter.
if head.sc:getCode() == auto_sc:getCode() then
track("redundant script code", data.lang)
if not data.no_script_code_cat then
insert(data.categories, full_langname .. " terms with redundant script codes")
end
else
track("non-redundant manual script code", data.lang)
if not data.no_script_code_cat then
insert(data.categories, full_langname .. " terms with non-redundant manual script codes")
end
end
end
-- If using a discouraged character sequence, add to maintenance category.
if head.sc:hasNormalizationFixes() == true then
local composed_head = toNFC(head.term)
if head.sc:fixDiscouragedSequences(composed_head) ~= composed_head then
insert(data.whole_page_categories, "Pages using discouraged character sequences")
end
end
any_script_has_spaces = any_script_has_spaces or head.sc:hasSpaces()
------ 7c. Create automatic transliterations for any non-Latin headwords without manual translit given
------ (provided automatic translit is available, e.g. not in Persian or Hebrew).
-- Make transliterations
head.tr_manual = nil
-- Try to generate a transliteration if necessary
if head.tr == "-" then
head.tr = nil
else
local notranslit = m_headword_data.notranslit
if not (notranslit[langcode] or notranslit[full_langcode]) and head.sc:isTransliterated() then
head.tr_manual = not not head.tr
local text = head.term_no_initial_bang_bang
if not data.lang:link_tr(head.sc) then
text = remove_links(text)
end
local automated_tr = data.lang:transliterate(text, head.sc)
if automated_tr then
local manual_tr = head.tr
if manual_tr then
if remove_links(manual_tr) == remove_links(automated_tr) then
insert(data.categories, full_langname .. " terms with redundant transliterations")
else
insert(data.categories, full_langname .. " terms with non-redundant manual transliterations")
end
end
if not manual_tr then
head.tr = automated_tr
end
end
-- There is still no transliteration?
-- Add the entry to a cleanup category.
if not head.tr then
head.tr = "<small>transliteration needed</small>"
-- FIXME: No current support for 'Request for transliteration of Classical Persian terms' or similar.
-- Consider adding this support in [[Module:category tree/poscatboiler/data/entry maintenance]].
insert(data.categories, "Requests for transliteration of " .. full_langname .. " terms")
else
-- Otherwise, trim it.
head.tr = trim(head.tr)
end
end
end
-- Link to the transliteration entry for languages that require this.
if head.tr and data.lang:link_tr(head.sc) then
head.tr = full_link{
term = head.tr,
lang = data.lang,
sc = get_script("Latn"),
tr = "-"
}
end
end
------------ 8. Maybe tag the title with the appropriate script code, using the `display_title` mechanism. ------------
-- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace.
-- (FIXME: Don't make assumptions like this, and if you need to do so, throw an error if the assumption is violated.)
-- Avoid tagging ASCII as Hani even when it is tagged as Hani in the headword, as in [[check]]. The check for ASCII
-- might need to be expanded to a check for any Latin characters and whitespace or punctuation.
local display_title
-- Where there are multiple headwords, use the script for the first. This assumes the first headword is similar to
-- the pagename, and that headwords that are in different scripts from the pagename aren't first. This seems to be
-- about the best we can do (alternatively we could potentially do script detection on the pagename).
local dt_script = data.heads[1].sc
local dt_script_code = dt_script:getCode()
local page_non_ascii = namespace == "" and not page.pagename:find("^[%z\1-\127]+$")
local unsupported_pagename, unsupported = page.full_raw_pagename:gsub("^Unsupported titles/", "")
if unsupported == 1 and page.unsupported_titles[unsupported_pagename] then
display_title = 'Unsupported titles/<span class="' .. dt_script_code .. '">' .. page.unsupported_titles[unsupported_pagename] .. '</span>'
elseif page_non_ascii and m_headword_data.toBeTagged[dt_script_code]
or (dt_script_code == "Jpan" and (text_in_script(page.pagename, "Hira") or text_in_script(page.pagename, "Kana")))
or (dt_script_code == "Kore" and text_in_script(page.pagename, "Hang")) then
display_title = '<span class="' .. dt_script_code .. '">' .. page.full_raw_pagename .. '</span>'
-- Keep Han entries region-neutral in the display title.
elseif page_non_ascii and (dt_script_code == "Hant" or dt_script_code == "Hans") then
display_title = '<span class="Hani">' .. page.full_raw_pagename .. '</span>'
elseif namespace == "Reconstruction" then
local matched
display_title, matched = ugsub(
page.full_raw_pagename,
"^(Reconstruction:[^/]+/)(.+)$",
function(before, term)
return before .. tag_text(term, data.lang, dt_script)
end
)
if matched == 0 then
display_title = nil
end
end
-- FIXME: Generalize this.
-- If the current language uses Aran (Nastaliq), e.g. Urdu, and there's more than one language on the page, don't
-- set the display title because we don't want Nastaliq for terms that also exist in other languages that don't
-- display in Nastaliq (e.g. Arabic or Persian). Because the word "Urdu" occurs near the end of the alphabet, Urdu
-- fonts tend to override the fonts of other languages. FIXME: This is checking for more than one language on the
-- page but instead needs to check if there are any languages using scripts other than Aran.
if dt_script_code == "Aran" and page.L2_list.n > 1 then
display_title = nil
end
if display_title then
mw.getCurrentFrame():callParserFunction(
"DISPLAYTITLE",
display_title
)
end
------------ 9. Insert additional categories. ------------
if data.force_cat_output then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/force cat output]]
track("force cat output")
end
if has_redundant_head_param then
if not data.no_redundant_head_cat then
-- This is not the right way to go about this; too many exceptions and problems due to language-specific headword
-- handling customization. If we want this, it should be opt-in by a given language passing in the default headword.
-- insert(data.categories, full_langname .. " terms with redundant head parameter")
end
end
if namespace == "Reconstruction" and not lang_reconstructed then
insert(data.categories, full_langname .. " reconstructed terms")
end
-- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms".
if not data.nomultiwordcat and not is_varform_only and any_script_has_spaces and postype == "lemma" then
local no_multiword_cat = m_headword_data.no_multiword_cat
if not (no_multiword_cat[langcode] or no_multiword_cat[full_langcode]) then
-- Check for spaces or hyphens, but exclude prefixes and suffixes.
-- Use the pagename, not the head= value, because the latter may have extra
-- junk in it, e.g. superscripted text that throws off the algorithm.
local no_hyphen = m_headword_data.hyphen_not_multiword_sep
-- Exclude hyphens if the data module states that they should for this language.
local checkpattern = (no_hyphen[langcode] or no_hyphen[full_langcode]) and ".[%s፡]." or ".[%s%-፡]."
local is_multiword = umatch(page.pagename, checkpattern)
if is_multiword and not non_categorizable(page.full_raw_pagename) then
insert(data.categories, full_langname .. " multiword terms")
elseif not is_multiword then
local long_word_threshold = m_headword_data.long_word_thresholds[langcode] or
m_headword_data.long_word_thresholds[full_langcode]
if long_word_threshold and ulen(page.pagename) >= long_word_threshold then
insert(data.categories, "Long " .. full_langname .. " words")
end
end
end
end
-- Determine whether to insert a category 'LANGNAME POS in SCRIPT'. If there are multiple heads, we may need to check
-- each head, as the heads may (theoretically) have different scripts.
local default_sccat = m_headword_data.default_sccat
if data.sccat or not is_varform_only and (default_sccat[langcode] or langcode ~= full_langcode and default_sccat[full_langcode]) then
local function needs_sccat(sccat_entry, sc)
if sccat_entry == true or not sccat_entry then
return sccat_entry
end
if type(sccat_entry) == "table" then
local in_list = contains(sccat_entry, sc:getCode())
if sccat_entry[1] == "not" then
in_list = not in_list
end
return in_list
end
return nil
end
for _, head in ipairs(data.heads) do
-- First check the `sccat` specified at the {{head}} level.
local this_needs_sccat = needs_sccat(data.sccat, head.sc)
-- If that wasn't given, check the default sccat at the language level for the lang code.
if this_needs_sccat == nil and not is_varform_only then
this_needs_sccat = needs_sccat(default_sccat[langcode], head.sc)
end
-- If that wasn't found and the lang code is an etym code, check the default sccat at the parent language level.
if this_needs_sccat == nil and not is_varform_only and langcode ~= full_langcode then
this_needs_sccat = needs_sccat(default_sccat[full_langcode], head.sc)
end
if this_needs_sccat then
insert(data.categories, full_langname .. " " .. data.pos_category .. " in " ..
head.sc:getDisplayForm(data.lang))
end
end
end
-- Reconstructed terms often use weird combinations of scripts and realistically aren't spelled so much as notated.
if namespace ~= "Reconstruction" and not is_varform_only then
-- Map from languages to a string containing the characters to ignore when considering whether a term has
-- multiple written scripts in it. Typically these are Greek or Cyrillic letters used for their phonetic
-- values.
local characters_to_ignore = {
["aaq"] = "αάὰ", -- Penobscot (Algonquian)
["acy"] = "δθ", -- Cypriot Arabic
["aez"] = "β", -- Aeka (Trans-New Guinea)
["anc"] = "γ", -- Ngas (Chadic/Afroasiatic)
["aou"] = "χ", -- A'ou (Kra-Dai)
["art-blk"] = "ч", -- Bolak (conlang)
["awg"] = "β", -- Anguthimri (Pama-Nyungan)
["az"] = "ь", -- Azerbaijani (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["ba"] = "ь", -- Bashkir (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["bhp"] = "β", -- Bima (Austronesian)
["bjz"] = "β", -- Baruga (Trans-New Guinea)
["byk"] = "θ", -- Biao (Kra-Dai)
["cdy"] = "θ", -- Chadong (Kra-Dai)
["chp"] = "θ", -- Chipewyan (Athabaskan)
["cjh"] = "χ", -- Upper Chehalis (Salishan)
["clm"] = "χ", -- Klallam (Salishan)
["col"] = "χ", -- Colombia-Wenatchi (Salishan)
["coo"] = "χθ", -- Comox (Salishan)
["crx"] = "θ", -- Carrier (Athabaskan)
["ets"] = "θ", -- Yekhee (Edoid/Niger-Congo)
["ett"] = "χ", -- Etruscan (isolate; in romanizations)
["fla"] = "χ", -- Montana Salish (Salishan)
["grt"] = "་", -- Garo (South Asian Sino-Tibetan)
["gmw-gts"] = "χ", -- Gottscheerish (Bavarian variant spoken in Slovenia)
["hur"] = "χθ", -- Halkomelem (Salishan)
["itc-psa"] = "f", -- Pre-Samnite (Italic; normally written in Greek)
["izh"] = "ь", -- Ingrian (Finnic)
["kic"] = "θ", -- Kickapoo (Algonquian)
["kk"] = "ь", -- Kazakh (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["ky"] = "ь", -- Kyrgyz (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["lil"] = "χ", -- Lillooet (Salishan)
["lsi"] = "ꓹ", -- Lashi (Lolo-Burmese/Sino-Tibetan; represents a glottal stop)
["mhz"] = "β", -- Mor (Austronesian)
["mqn"] = "β", -- Moronene (Austronesian)
["neg"]= "ӡā", -- Negidal (Tungusic; normally in Cyrillic)
["oka"] = "χ", -- Okanagan (Salishan)
["ole"] = "θ", -- Olekha (Sino-Tibetan)
["oui"] = "γβ", -- Old Uyghur (Turkic; FIXME: others? E.g. Greek delta (δ)?)
["pox"] = "χ", -- Polabian (West Slavic)
["rif"] = "ε", -- Tarifit (Berber)
["rom"] = "Θθ", -- Romani (Indic: International Standard; two different thetas???)
["rpn"] = "β", -- Repanbitip (Austronesian)
["sah"] = "ь", -- Yakut (Turkic; 1929 - 1939 Latin spelling)
["sit-jap"] = "χ", -- Japhug (Sino-Tibetan)
["sjw"] = "θ", -- Shawnee (Algonquian)
["squ"] = "χ", -- Squamish (Salishan)
["str"] = "χθ", -- Saanich (Salishan)
["teh"] = "χ", -- Tehuelche (Chonan; spoken in Argentina)
["tep"] = "η", -- Tepecano (Uto-Aztecan)
["thp"] = "χ", -- Thompson (Salishan)
["tk"] = "ь", -- Turkmen (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["tt"] = "ь", -- Kazakh (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["twa"] = "χ", -- Twana (Salishan)
["wbl"] = "ы", -- Wakhi (Iranian)
["xbc"] = "ϸ", -- Bactrian (Iranian; represents š; normally written in Greek)
["yha"] = "θ", -- Baha (Kra-Dai)
["za"] = "зч", -- Zhuang (Tai/Kra-Dai); 1957-1982 alphabet used two Cyrillic letters (as well as some others like
-- ƃ, ƅ, ƨ, ɯ and ɵ that look like Cyrillic or Greek but are actually Latin)
["zlw-slv"] = "χђћ", -- Slovincian (West Slavic; FIXME: χ is Greek, the other two are Cyrillic, but I'm not sure
-- the currect characters are being chosen in the entry names)
["zng"] = "θ", -- Mang (Mon-Khmer)
["ztp"] = "θ", -- Loxicha Zapotec (Zapotecan)
}
-- Determine how many real scripts are found in the pagename, where we exclude symbols and such. We exclude
-- scripts whose `character_category` is false as well as Zmth (mathematical notation symbols), which has a
-- category of "Mathematical notation symbols". When counting scripts, we need to elide language-specific
-- variants because e.g. Beng and as-Beng have slightly different characters but we don't want to consider them
-- two different scripts (e.g. [[এৰ]] has two characters which are detected respectively as Beng and as-Beng).
local seen_scripts = {}
local num_seen_scripts = 0
local num_loops = 0
local canon_pagename = page.pagename
local ch_to_ignore = characters_to_ignore[full_langcode]
if ch_to_ignore then
canon_pagename = ugsub(canon_pagename, "[" .. ch_to_ignore .. "]", "")
end
while true do
if canon_pagename == "" or num_seen_scripts >= 2 or num_loops >= 10 then
break
end
-- Make sure we don't get into a loop checking the same script over and over again; happens with e.g. [[ᠪᡳ]]
num_loops = num_loops + 1
local pagename_script = find_best_script_without_lang(canon_pagename, "None only as last resort")
local script_chars = pagename_script.characters
if not script_chars then
-- we are stuck; this happens with None
break
end
local script_code = pagename_script:getCode()
local replaced
canon_pagename, replaced = ugsub(canon_pagename, "[" .. script_chars .. "]", "")
if (
replaced and
script_code ~= "Zmth" and
(script_data or get_script_data())[script_code] and
script_data[script_code].character_category ~= false
) then
script_code = script_code:gsub("^.-%-", "")
if not seen_scripts[script_code] then
seen_scripts[script_code] = true
num_seen_scripts = num_seen_scripts + 1
end
end
end
if num_seen_scripts > 1 then
insert(data.categories, full_langname .. " terms written in multiple scripts")
end
end
-- Categorise for unusual characters. Takes into account combining characters, so that we can categorise for characters with diacritics that aren't encoded as atomic characters (e.g. U̠). These can be in two formats: single combining characters (i.e. character + diacritic(s)) or double combining characters (i.e. character + diacritic(s) + character). Each can have any number of diacritics.
local standard = data.lang:getStandardCharacters()
if not is_varform_only and standard and not non_categorizable(page.full_raw_pagename) then
local function char_category(char)
local specials = {
["#"] = "number sign",
["("] = "parentheses",
[")"] = "parentheses",
["<"] = "angle brackets",
[">"] = "angle brackets",
["["] = "square brackets",
["]"] = "square brackets",
["_"] = "underscore",
["{"] = "braces",
["|"] = "vertical line",
["}"] = "braces",
["ß"] = "ẞ",
["\205\133"] = "", -- this is UTF-8 for U+0345 ( ͅ)
["\239\191\189"] = "replacement character",
}
char = toNFD(char)
:gsub(".[\128-\191]*", function(m)
local new_m = specials[m]
new_m = new_m or m:uupper()
return new_m
end)
return toNFC(char)
end
if full_langcode ~= "hi" and full_langcode ~= "lo" then
local standard_chars_scripts = {}
for _, head in ipairs(data.heads) do
standard_chars_scripts[head.sc:getCode()] = true
end
-- Iterate over the scripts, in case there is more than one (as they can have different sets of standard characters).
for code in pairs(standard_chars_scripts) do
local sc_standard = data.lang:getStandardCharacters(code)
if sc_standard then
if page.pagename_len > 1 then
local explode_standard = {}
local function explode(char)
explode_standard[char] = true
return ""
end
local sc_standard_exploded = ugsub(sc_standard, page.comb_chars.combined_double, explode)
-- The following is correct; it relies on side-effecing the explode_standard[] table.
ugsub(sc_standard_exploded, page.comb_chars.combined_single, explode):gsub(".[\128-\191]*", explode)
local num_cat_inserted
for char in pairs(page.explode_pagename) do
if not explode_standard[char] then
if char:find("[0-9]") then
if not num_cat_inserted then
insert(data.categories, full_langname .. " terms spelled with numbers")
num_cat_inserted = true
end
elseif ufind(char, page.emoji_pattern) then
insert(data.categories, full_langname .. " terms spelled with emoji")
else
local upper = char_category(char)
if not explode_standard[upper] then
char = upper
end
insert(data.categories, full_langname .. " terms spelled with " .. char)
end
end
end
end
-- If a diacritic doesn't appear in any of the standard characters, also categorise for it generally.
sc_standard = toNFD(sc_standard)
for diacritic in ugmatch(page.decompose_pagename, page.comb_chars.diacritics_single) do
if not umatch(sc_standard, diacritic) then
insert(data.categories, full_langname .. " terms spelled with ◌" .. diacritic)
end
end
for diacritic in ugmatch(page.decompose_pagename, page.comb_chars.diacritics_double) do
if not umatch(sc_standard, diacritic) then
insert(data.categories, full_langname .. " terms spelled with ◌" .. diacritic .. "◌")
end
end
end
end
-- Ancient Greek, Hindi and Lao handled the old way for now, as their standard chars still need to be converted to the new format (because there are a lot of them).
elseif ulen(page.pagename) ~= 1 then
for character in ugmatch(page.pagename, "([^" .. standard .. "])") do
local upper = char_category(character)
if not umatch(upper, "[" .. standard .. "]") then
character = upper
end
insert(data.categories, full_langname .. " terms spelled with " .. character)
end
end
end
if not is_varform_only and data.heads[1].sc:isSystem("alphabet") then
local pagename, i = page.pagename:ulower(), 2
while umatch(pagename, "(%a)" .. ("%1"):rep(i)) do
i = i + 1
insert(data.categories, full_langname .. " terms with " .. i .. " consecutive instances of the same letter")
end
end
-- Categorise for palindromes
if not is_varform_only and not data.nopalindromecat and namespace ~= "Reconstruction" and ulen(page.pagename) > 2
-- FIXME: Use of first script here seems hacky. What is the clean way of doing this in the presence of
-- multiple scripts?
and is_palindrome(page.pagename, data.lang, data.heads[1].sc) then
insert(data.categories, full_langname .. " palindromes")
end
if namespace == "" and not lang_reconstructed then
for _, head in ipairs(data.heads) do
if page.full_raw_pagename ~= get_link_page(remove_links(head.term), data.lang, head.sc) then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/pagename spelling mismatch]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/pagename spelling mismatch/LANGCODE]]
track("pagename spelling mismatch", data.lang)
break
end
end
end
-- Add red link category if called for and we're not a "large" page, where such checks are disabled.
if data.checkredlinks and not m_headword_data.large_pages[m_headword_data.pagename] then
local plposcat = type(data.checkredlinks) == "string" and data.checkredlinks or data.pos_category
check_red_link_inflections_top_level(data, plposcat)
end
-- Add to various maintenance categories.
export.maintenance_cats(page, data.lang, data.categories, data.whole_page_categories)
------------ 10. Format and return headwords, genders, inflections and categories. ------------
-- Format and return all the gathered information. This may add more categories (e.g. gender/number categories),
-- so make sure we do it before evaluating `data.categories`.
local text = '<span class="headword-line">' ..
format_headword(data) ..
format_headword_genders(data, is_varform_only) ..
format_top_level_inflections(data) .. '</span>'
-- Language-specific categories.
local cats = format_categories(
data.categories, data.lang, data.sort_key, page.encoded_pagename,
data.force_cat_output or test_force_categories, data.heads[1].sc
)
-- Language-agnostic categories.
local whole_page_cats = format_categories(
data.whole_page_categories, nil, "-"
)
return text .. cats .. whole_page_cats
end
return export
sbw12qmfvdznqsvxzenremj9qtba2yi
ground
0
8026
54930
54790
2026-09-29T18:50:13Z
Deadend0914
7211
/* Wordstǣr */
54930
wikitext
text/x-wiki
==Nīwenglisc==
===Rihtstefn===
* IPA: /ɡɹaʊnd/
===Wordstǣr===
Of {{inh|en|enm|ground}}
===Nama===
{{en-noun|~}}
# [[grund]]
===Wendunga===
* Englisc: [[grund]]
2yv2mpv6zcq8vus2082szz6lhzjzvb4
Module:en-headword
828
8056
54931
54895
2026-09-29T18:55:53Z
Deadend0914
7211
54931
Scribunto
text/plain
local export = {}
local pos_functions = {}
--[==[
Author from 2020 on: mostly Benwing2, with significant contributions from Theknightwho. Based on a prior version by Rua
(by now mostly rewritten), with contributions from Erutuon and others (see history for full attribution).
]==]
local force_cat = false -- for testing; if true, categories appear in non-mainspace pages
local require = require
local require_when_needed = require("Module:require when needed")
local en_utilities_module = "Module:en-utilities"
local headword_utilities_module = "Module:headword utilities"
local headword_module = "Module:headword"
local inflection_utilities_module = "Module:inflection utilities"
local parse_utilities_module = "Module:parse utilities"
local JSON_module = "Module:JSON"
local labels_module = "Module:labels"
local links_module = "Module:links"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local yesno_module = "Module:yesno"
local iut = require_when_needed(inflection_utilities_module)
local put = require_when_needed(parse_utilities_module)
local m_headword_utilities = require_when_needed(headword_utilities_module)
local add_links_to_multiword_term = require_when_needed(headword_utilities_module, "add_links_to_multiword_term")
local add_suffix = require_when_needed(en_utilities_module, "add_suffix")
local apply_link_modifiers = require_when_needed(headword_utilities_module, "apply_link_modifiers")
local concat = table.concat
local deepEquals = require_when_needed(table_module, "deepEquals")
local dump = mw.dumpObject
local format_categories = require_when_needed(utilities_module, "format_categories")
local full_headword = require_when_needed(headword_module, "full_headword")
local get_label_info = require_when_needed(labels_module, "get_label_info")
local get_link_page = require_when_needed(links_module, "get_link_page")
local glossary_link = require_when_needed(headword_utilities_module, "glossary_link")
local insert = table.insert
local insertIfNot = require_when_needed(table_module, "insertIfNot")
local ipairs = ipairs
local is_regular_plural = require_when_needed(en_utilities_module, "is_regular_plural")
local list_to_set = require_when_needed(table_module, "listToSet")
local pairs = pairs
local process_params = require_when_needed(parameters_module, "process")
local remove = table.remove
local remove_links = require_when_needed(links_module, "remove_links")
local replacement_escape = require_when_needed(string_utilities_module, "replacement_escape")
local shallowCopy = require_when_needed(table_module, "shallowCopy")
local singularize = require_when_needed(en_utilities_module, "singularize")
local split = require_when_needed(string_utilities_module, "split")
local toJSON = require_when_needed(JSON_module, "toJSON")
local toNFD = mw.ustring.toNFD
local type = type
local ulen = require_when_needed(string_utilities_module, "len")
local ulower = require_when_needed(string_utilities_module, "lower")
local umatch = require_when_needed(string_utilities_module, "match")
local u = require_when_needed(string_utilities_module, "char")
local ugsub = require_when_needed(string_utilities_module, "gsub")
local lang = require("Module:languages").getByCode("en")
local langname = lang:getCanonicalName()
local list_param = {list = true, disallow_holes = true}
local list_allow_holes = {list = true, allow_holes = true}
local boolean_param = {type = "boolean"}
local function ine(val)
if val == "" then return nil else return val end
end
local function track(page)
require("Module:debug/track")("en-headword/" .. page)
return true
end
------------------------------------------- UTILITY FUNCTIONS ------------------------------------------
-- Parse and return an inflection not requiring additional processing. The raw arguments come from `args[field]`, which
-- is parsed for inline modifiers.
local function parse_inflection(args, field, is_head)
local argfield = field
if type(argfield) == "table" then
argfield = argfield[1]
end
return m_headword_utilities.parse_term_list_with_modifiers {
paramname = field,
forms = args[argfield],
splitchar = ",",
is_head = is_head,
}
end
-- Insert the parsed inflections in `terms` (as parsed by `parse_inflection`) into `data.inflections`, with label
-- `label` and optional accelerator spec `accel`.
local function insert_inflection(data, terms, label, accel, no_label)
for _, termobj in ipairs(terms) do
m_headword_utilities.remove_termobj_field_modifiers(termobj)
end
m_headword_utilities.insert_inflection {
headdata = data,
terms = terms,
label = label,
no_label = no_label,
accel = accel and {form = accel} or nil,
}
end
-- Insert a fixed label `label` into the inflections for `data`. If `originating_term` is supplied, copy the decorations
-- from it into the fixed label.
local function insert_fixed_inflection(data, label, originating_term)
m_headword_utilities.insert_fixed_inflection {
headdata = data,
originating_term = originating_term,
label = label,
}
end
-- Parse and insert an inflection not requiring additional processing into `data.inflections`. The raw arguments come
-- from `args[field]`, which is parsed for inline modifiers. `label` is the label that the inflections are given;
-- `accel` is the accelerator form, or nil.
local function parse_and_insert_inflection(data, args, field, label, accel)
m_headword_utilities.parse_and_insert_inflection {
headdata = data,
forms = args[field],
paramname = field,
splitchar = ",",
label = label,
accel = accel and {form = accel} or nil,
}
end
-- These functions are used directly in the <> format as well as in the utility functions #2 below.
local function compute_double_last_cons_stem(term)
local last_cons = term:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$")
if not last_cons then
error("Verb stem '" .. term .. "' must end in a consonant to use ++")
end
return term .. last_cons
end
local function compute_plusplus_s_form(term, default_s_form)
if term:find("[szx]$") then
-- regas -> regasses, derez -> derezzes
return compute_double_last_cons_stem(term) .. "es"
else
return default_s_form
end
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local iparams = {
[1] = true,
}
local iargs = require("Module:parameters").process(frame.args, iparams)
local parargs = frame:getParent().args
local poscat = iargs[1]
local pos_in_1 = not poscat
if pos_in_1 then
poscat = ine(parargs[1]) or
mw.title.getCurrentTitle().fullText == "Template:en-head" and "interjection" or
error("Part of speech must be specified in 1=")
poscat = require(headword_module).canonicalize_pos(poscat)
end
local indexing_poscat = pos_in_1 and "head" or poscat
local params = {
["head"] = list_param,
["id"] = true,
["json"] = boolean_param,
["sort"] = true,
["splithyph"] = boolean_param,
["nosplithyph"] = boolean_param,
["hyphspace"] = boolean_param,
["nolink"] = boolean_param,
["nolinkhead"] = {type = "boolean_param", alias_of = "nolink"},
["suffix"] = boolean_param,
["nosuffix"] = boolean_param,
["nomultiwordcat"] = boolean_param,
["abbr"] = list_param,
["the"] = true,
["def"] = {alias_of = "the"},
["pagename"] = true, -- for testing
}
if pos_in_1 then
params[1] = {required = true} -- required but ignored as already processed above
end
local pos_data = pos_functions[indexing_poscat]
local pos_func
if pos_data then
local pos_params = pos_data.params
if pos_params then
for key, val in pairs(pos_params) do
params[key] = val
end
end
pos_func = pos_data.func
end
local args = process_params(parargs, params)
-- Account for unsupported titles, e.g. 'C|N>K' instead of 'Unsupported titles/C through N to K'.
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
local user_specified_heads = parse_inflection(args, "head", "is_head")
local heads = user_specified_heads
local autohead
if args.nolink or not pagename:find("[ '%-]") then
autohead = pagename
else
local en_no_split_apostrophe_words = list_to_set {
"one's",
"someone's",
"he's",
"she's",
"it's",
}
local en_include_hyphen_prefixes = list_to_set {
-- We don't include things that are also words even though they are often (perhaps mostly) prefixes, e.g.
-- "be", "counter", "cross", "extra", "half", "mid", "over", "pan", "under".
"acro",
"acousto",
"Afro",
"agro",
"anarcho",
"angio",
"Anglo",
"ante",
"anti",
"arch",
"auto",
"bi",
"bio",
"cis",
"co",
"cryo",
"crypto",
"de",
"demi",
"eco",
"electro",
"Euro",
"ex",
"Greco",
"hemi",
"hydro",
"hyper",
"hypo",
"infra",
"Indo",
"inter",
"intra",
"Judeo",
"macro",
"meta",
"micro",
"mini",
"multi",
"neo",
"neuro",
"non",
"para",
"peri",
"post",
"pre",
"pro",
"proto",
"pseudo",
"re",
"semi",
"sub",
"super",
"trans",
"un",
"vice",
}
local function is_english(term)
local title = mw.title.new(term)
if title and title.exists then
local content = title:getContent()
if content and content:find("==English==\n") then
return true
end
end
return false
end
local function en_split_hyphen_when_space(word)
if not word:find("-", nil, true) then
return nil
end
if args.hyphspace then
return "[[" .. word:gsub("%-+", " ") .. "|" .. word .. "]]"
end
if args.nosplithyph then
return "[[" .. word .. "]]"
end
if not args.splithyph then
local space_word = word:gsub("%-+", " ")
if is_english(space_word) then
return "[[" .. space_word .. "|" .. word .. "]]"
end
if is_english(word) then
return "[[" .. word .. "]]"
end
end
return nil
end
local function en_split_apostrophe(word)
local base = word:match("^(.*)'s$")
if base then
return "[[" .. base .. "]][[-'s|'s]]"
end
-- Only treat final apostrophe as possessive if preceded by something that looks like a plural ending in /z/.
-- In particular we don't want to do it for words like [[truckin']].
base = word:match("^(.*[sxz])'$")
if base then
if base:find("s$") then
local sg = singularize(base)
if is_english(sg) then
return "[[" .. sg .. "|" .. base .. "]][[-'|']]"
end
end
return "[[" .. base .. "]][[-'|']]"
end
return "[[" .. word .. "]]"
end
autohead = add_links_to_multiword_term(pagename, {
split_hyphen_when_space = en_split_hyphen_when_space,
split_apostrophe = en_split_apostrophe,
no_split_apostrophe_words = en_no_split_apostrophe_words,
include_hyphen_prefixes = en_include_hyphen_prefixes,
})
end
if not heads[1] then
heads = {{term = autohead}}
else
for _, headobj in ipairs(heads) do
local head = headobj.term
if head:find("^~") then
head = apply_link_modifiers(autohead, head:sub(2), lang)
headobj.term = head
elseif head:find("^[!?]$") then
-- If explicit head= just consists of ! or ?, add it to the end of the default head.
headobj.term = autohead .. head
end
if head == autohead then
track("redundant-head")
end
end
end
-- handle the=/def=
if args.the == "~" then
local newheads = {}
for _, headobj in ipairs(heads) do
local barehead = shallowCopy(headobj)
insert(newheads, barehead)
headobj.term = "the " .. headobj.term
insert(newheads, headobj)
end
heads = newheads
elseif args.the then
local the = require(yesno_module)(args.the)
if the then
for _, headobj in ipairs(heads) do
headobj.term = "the " .. headobj.term
end
end
end
local data = {
lang = lang,
pos_category = poscat,
categories = {},
heads = heads,
user_specified_heads = user_specified_heads,
-- We use our own splitting algorithm so the redundant head cat will be inaccurate.
no_redundant_head_cat = true,
inflections = {},
nomultiwordcat = args.nomultiwordcat,
sort_key = args.sort,
pagename = pagename,
id = args.id,
force_cat_output = force_cat,
}
local function inscat(cat)
insert(data.categories, langname .. " " .. cat)
end
local is_suffix = false
if args.suffix or not args.nosuffix and pagename:find("^%-") and not pagename:find("^%-%-") and poscat ~= "suffix forms" then
is_suffix = true
data.pos_category = "suffixes"
local singular_poscat = singularize(poscat)
inscat(singular_poscat .. "-forming suffixes")
insert(data.inflections, {label = singular_poscat .. "-forming suffix"})
end
if pos_func then
pos_func(args, data, is_suffix)
end
local extra_categories = {}
if pagename:find("[Qq]") then
-- Check for q not followed by u. We want to exclude things like [[13q deletion syndrome]] and [[BFOQ]] that
-- don't have a lowercase letter on either side, as well as things like [[& seq.]] and [[acq.]] that are
-- abbreviations for words containing a following u.
--
-- Approximate range of combining diacritics; we want to remove them so the checks below for
-- a lowercase letter next to the q aren't tripped up by diacritics on the letter.
local u300 = u(0x0300)
local u36F = u(0x036F)
local pagename_no_diacritics = ugsub(toNFD(pagename), "[" .. u300 .. "-" .. u36F .. "]", "")
if pagename_no_diacritics:find("[Qq][a-tv-z]") or pagename_no_diacritics:find("[a-z]q[^u.]") or
pagename_no_diacritics:find("[a-z]q$") then
inscat("words containing Q not followed by U")
end
end
-- toNFD performs decomposition, so letters that decompose to an ASCII
-- vowel and a diacritic, such as é, are counted as vowels and do not do not
-- need to be included in the pattern.
if not umatch(ulower(toNFD(pagename)), "[aeiouyæœøəªºαεηιουω]") then
inscat("words spelled without vowels")
end
if pagename:find("yre$") then
inscat('words ending in "-yre"')
end
if not pagename:find(" ") and ulen(pagename) >= 25 then
insert(extra_categories, "Long " .. langname .. " words")
end
if pagename:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then
inscat("words that use all vowels in alphabetical order")
end
parse_and_insert_inflection(data, args, "abbr", "abbreviation")
if args.json then
return toJSON(data)
end
return full_headword(data)
.. (extra_categories[1]
and format_categories(extra_categories, lang, args.sort)
or "")
end
local function make_default_comparative(word)
if word == "good" or word == "well" then
return {"better"}
elseif word == "bad" or word == "badly" then
return {"worse"}
elseif word == "far" then
return {"further", "farther"}
else
return {add_suffix(word, "r")}
end
end
local function make_default_superlative(word)
if word == "good" or word == "well" then
return {"best"}
elseif word == "bad" or word == "badly" then
return {"worst"}
elseif word == "far" then
return {"furthest", "farthest"}
else
return {add_suffix(word, "st.superlative")}
end
end
-- This function does the common work between adjectives and adverbs.
local function process_comparative_args(data, args, plpos)
local pagename = data.pagename
local comps = parse_inflection(args, 1)
local sups = parse_inflection(args, "sup")
local outcomps, outsups
if args.componly then
if comps[1] then
error("Can't specify comparatives of comparative-only " .. plpos)
end
insert(data.inflections, {label = glossary_link("comparative") .. " form only"})
insert(data.categories, langname .. " comparative-only " .. plpos)
-- Set to empty list so we don't get any comparatives output, but process superlatives if specified.
outcomps = {}
if not sups[1] then
-- Set to empty list so we don't get any superlatives output unless explicitly given.
outsups = {}
end
elseif args.suponly then
if comps[1] or sups[1] then
error("Can't specify comparatives or superlatives of or superlative-only " .. plpos)
end
insert(data.inflections, {label = glossary_link("superlative") .. " form only"})
insert(data.categories, langname .. " superlative-only " .. plpos)
return
end
-- If the first parameter is ?, then don't show anything, just return.
if comps[1] and comps[1].term == "?" then
if comps[2] then
error("Can't specify additional comparatives along with '?'")
end
if sups[1] then
error("Can't specify superlatives along with '?' for the comparative")
end
return
end
if comps[1] and comps[1].term == "-" then
local hyphencomp = remove(comps, 1) -- Remove the "-" but retain for decorations.
-- Not (generally) comparable; may occasionally have a comparative
if comps[1] then
insert_fixed_inflection(data, "not generally <<comparable>>", hyphencomp)
elseif not sups[1] then
insert_fixed_inflection(data, "not <<comparable>>", hyphencomp)
insert(data.categories, langname .. " uncomparable " .. plpos)
return
else
-- No comparative, but a superlative. insert_inflection() will correctly generate 'no comparative' if we
-- pass in "-" as the value.
outcomps = {hyphencomp}
end
elseif not comps[1] then
comps = {{term = "more"}}
end
if not outcomps then -- not if we set `outcomps` to "-" above or processed a comparative-only term
outcomps = {}
-- Go over each parameter given and create a comparative and superlative form.
for _, compobj in ipairs(comps) do
local comp = compobj.term
if comp == "-" then
error("Comparative of '-' only allowed as first comparative")
end
if comp == "+" then
comp = "+more"
elseif comp == "more" and pagename ~= "many" and pagename ~= "much" then
comp = "+more"
elseif comp == "further" and pagename ~= "far" then
comp = "+further"
elseif comp == "better" and pagename ~= "good" and pagename ~= "well" then
comp = "+better"
elseif comp:find("~") then
comp = comp:gsub("~", replacement_escape(pagename))
end
compobj.origterm = comp
if comp == "+more" then
comp = "more [[" .. pagename .. "]]"
elseif comp == "+further" then
comp = {"further [[" .. pagename .. "]]", "farther [[" .. pagename .. "]]"}
elseif comp == "+better" then
comp = "better [[" .. pagename .. "]]"
elseif comp == "er" then
-- Add -er.
comp = add_suffix(pagename, "r")
elseif comp == "ier" then
if pagename:sub(-1) ~= "y" then
error("Can't specify 'ier' comparative unless the term ends with 'y': " .. pagename)
end
comp = pagename:gsub("e?y$", "ier")
elseif comp:find("^%+") then
local special = m_headword_utilities.get_special_indicator(comp, "noerror")
if special then
comp = m_headword_utilities.handle_multiword(pagename, special, make_default_comparative)
end
end
if type(comp) == "table" and not comp[2] then
comp = comp[1]
end
if type(comp) == "table" then
for i = 1, #comp - 1 do
local outobj = shallowCopy(compobj)
outobj.term = comp[i]
insert(outcomps, outobj)
end
compobj.term = comp[#comp]
insert(outcomps, compobj)
else
compobj.term = comp
insert(outcomps, compobj)
end
end
end
if sups[1] and sups[1].term == "-" then
if sups[2] then
error("Can't specify '-' as superlative followed by further values")
end
-- No superlative. insert_inflection() will correctly generate 'no superlative' if we pass in "-" as the value.
outsups = sups
else
if not sups[1] then
sups = {{term = "+"}}
end
end
-- `outsups` will be set if we set `outsups` to "-" above or processed a comparative-only term without superlatives.
if not outsups then
outsups = {}
local function process_sup(sup, special, supobj, compobj)
if special then
sup = m_headword_utilities.handle_multiword(pagename, special, make_default_superlative)
elseif sup == "-" or sup == "+" then
error(("Internal error: Superlative value of '%s' should have been handled earlier"):format(sup))
elseif sup == "+most" then
sup = "most [[" .. pagename .. "]]"
elseif sup == "+furthest" then
sup = {"furthest [[" .. pagename .. "]]", "farthest [[" .. pagename .. "]]"}
elseif sup == "+best" then
sup = "best [[" .. pagename .. "]]"
elseif sup == "est" then
-- Add -est.
sup = add_suffix(pagename, "st.superlative")
elseif sup == "iest" then
if pagename:sub(-1) ~= "y" then
error("Can't specify 'iest' superlative unless the term ends with 'y': " .. pagename)
end
sup = pagename:gsub("e?y$", "iest")
end
if type(sup) == "table" and not sup[2] then
sup = sup[1]
end
if compobj then
supobj = shallowCopy(supobj)
supobj = m_headword_utilities.combine_termobj_decorations(supobj, compobj)
end
if type(sup) == "table" then
for i = 1, #sup - 1 do
local outobj = shallowCopy(supobj)
outobj.term = sup[i]
insert(outsups, outobj)
end
supobj.term = sup[#sup]
insert(outsups, supobj)
else
supobj.term = sup
insert(outsups, supobj)
end
end
for _, supobj in ipairs(sups) do
local sup = supobj.term
if sup == "-" then
error("Superlative of '-' only allowed as first superlative")
end
if sup == "+" then
if not comps[1] then
error("Superlative of '+' can't be specified when there are no comparatives")
end
for _, compobj in ipairs(comps) do
local comp = compobj.origterm
local special
if comp == "+more" then
sup = "+most"
elseif comp == "+further" then
sup = "+furthest"
elseif comp == "+better" then
sup = "+best"
elseif comp == "er" then
sup = "est"
elseif comp == "ier" then
sup = "iest"
else
if comp:find("^%+") then
special = m_headword_utilities.get_special_indicator(comp, "noerror")
end
if not special then
-- If the full comparative was given, then derive the superlative by replacing -er with
-- -est.
if comp:sub(-2) == "er" then
sup = comp:sub(1, -3) .. "est"
else
error(("The superlative cannot be derived automatically from comparative '%s' because it doesn't end in -er"):format(comp))
end
end
end
process_sup(sup, special, supobj, compobj)
end
else
local special = m_headword_utilities.get_special_indicator(sup, "noerror")
-- Do some work here rather than in process_sup() so we don't end up double-processing a term with a '~'
-- in it or a term that happens to be 'most' or similar after substitution of ~ in the comparative.
if not special then
if sup == "most" and pagename ~= "many" and pagename ~= "much" then
sup = "+most"
elseif sup == "furthest" and pagename ~= "far" then
sup = "+furthest"
elseif sup == "best" and pagename ~= "good" and pagename ~= "well" then
sup = "+best"
elseif sup:find("~") then
sup = sup:gsub("~", replacement_escape(pagename))
end
end
process_sup(sup, special, supobj)
end
end
end
insert_inflection(data, outcomps, "<<comparative>>", "comparative")
insert_inflection(data, outsups, "<<superlative>>", "superlative")
end
pos_functions["adjectives"] = {
params = {
[1] = list_param,
["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the comparative value",
},
["sup"] = list_param,
["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the superlative value",
},
["componly"] = boolean_param,
["suponly"] = boolean_param,
},
func = function(args, data)
-- Process the comparatives and superlatives.
process_comparative_args(data, args, "adjectives")
end,
}
pos_functions["adverbs"] = {
params = {
[1] = list_param,
["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the comparative value",
},
["sup"] = list_param,
["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the superlative value",
},
["componly"] = boolean_param,
["suponly"] = boolean_param,
},
func = function(args, data)
-- Process the comparatives and superlatives.
process_comparative_args(data, args, "adverbs")
end,
}
local function escape(str)
return (str:gsub("\\([:#])", "\\\\%1")
:gsub("[:#]", "\\%0"))
end
local function canonicalize_plural(pl, pagename, pos)
if pl == "+" then
return escape(add_suffix(pagename, "s.plural", pos))
elseif pl == "++" then
return escape(compute_plusplus_s_form(pagename, add_suffix(pagename, "s.plural", pos)))
elseif pl == "*" then
return escape(pagename)
elseif pl == "ies" then
if pagename:sub(-1) == "y" then
return escape(pagename:gsub("e?y$", pl))
end
error("Can't specify 'ies' plural unless the term ends with 'y'.")
elseif pl == "s" or pl == "es" or pl == "'s" then
return escape(pagename .. pl)
end
end
local function do_nouns(args, data, pos)
local pagename = data.pagename
pos = pos or "noun"
local plurals = parse_inflection(args, 1)
local function insert_plurale_tantum_inflections(is_plural_only, originating_label)
if args.sg[1] then
insert_fixed_inflection(data, "normally plural", originating_label)
parse_and_insert_inflection(data, args, "sg", "singular")
elseif is_plural_only then
insert_fixed_inflection(data, "plural only", originating_label)
end
if args.attr[1] then
parse_and_insert_inflection(data, args, "attr", "attributive")
end
end
local function first_pl_term()
return plurals[1] and plurals[1].term or nil
end
if first_pl_term() == "p" then
-- plurale tantum
if plurals[2] then
error("With plurale tantum noun, can't specify more than one plural")
end
data.genders = {"p"} -- this should auto-insert the correct 'pluralia tantum' category
insert_plurale_tantum_inflections("plural only", plurals[1])
return
end
local function inscat(cat)
insert(data.categories, langname .. " " .. cat)
end
local need_default_plural = pos == "noun"
if first_pl_term() == "sp" then
-- construed as singular or plural
sp = remove(plurals, 1) -- Remove the "sp" but retain it for its decorations.
inscat("nouns construed as singular or plural")
data.genders = {"s", "p"} -- this should auto-insert the correct 'pluralia tantum' category
insert_plurale_tantum_inflections(nil, sp)
need_default_plural = false
elseif first_pl_term() == "-" then
-- Untellendlīc noun; may occasionally have a plural
local hyphpl = remove(plurals, 1) -- Remove the "-" but retain for decorations.
inscat("untellendlīc nouns")
-- If plural forms were given explicitly, then show "oft"
if plurals[1] then
insert_fixed_inflection(data, "oft <<untellendlīc>>", hyphpl)
else
insert_fixed_inflection(data, "<<untellendlīc>>", hyphpl)
end
need_default_plural = false
elseif first_pl_term() == "#" then
-- oft tellendlīc (e.g., "grilled cheese")
local hashpl = remove(plurals, 1) -- Remove the "#" but retain for decorations.
insert_fixed_inflection(data, "oft <<tellendlīc>>", hashpl)
inscat("untellendlīc nouns")
inscat("tellendlīc nouns")
-- If no plural was given, add a default one now
if not plurals[1] then
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
elseif first_pl_term() == "~" then
-- Mixed tellendlīc/untellendlīc noun, always has a plural
local tildepl = remove(plurals, 1) -- Remove the "~" but retain for decorations.
insert_fixed_inflection(data, "<<tellendlīc>> and <<untellendlīc>>", tildepl)
inscat("untellendlīc nouns")
inscat("tellendlīc nouns")
-- If no plural was given, add a default one now
if not plurals[1] then
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
end
-- Plural is unknown
if first_pl_term() == "?" then
local questionpl = remove(plurals, 1) -- Remove the "?" but retain for decorations.
-- Not desired; see [[Wiktionary:Tea_room/2021/August#"Plural unknown or uncertain"]]
-- insert_fixed_inflection(data, "plural unknown or uncertain", questionpl)
inscat("nouns with unknown or uncertain plurals")
if plurals[1] then
error("Can't specify explicit plurals along with '?' for unknown/uncertain plural")
end
return
end
-- Plural is not attested
if first_pl_term() == "!" then
local exclampl = remove(plurals, 1) -- Remove the "!" but retain for decorations.
insert_fixed_inflection(data, "plural not attested", exclampl)
inscat("nouns with unattested plurals")
if plurals[1] then
error("Can't specify explicit plurals along with '!' for unattested plural")
end
return
end
-- If no plural was given, maybe add a default one, otherwise (when "-" was given or proper noun) return.
if not plurals[1] then
if not need_default_plural then
inscat("untellendlīc nouns")
return
end
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
-- There are plural forms to show, so show them.
inscat("tellendlīc nouns")
local irregular, indeclinable
for i, pl in ipairs(plurals) do
local canon_pl = canonicalize_plural(pl.term, pagename, pos)
if canon_pl then
pl.term = canon_pl
end
local pl_term = get_link_page(pl.term, lang)
if not (pagename:find(" ") or is_regular_plural(pl_term, pagename)) then
irregular = true
if pl_term == pagename then
indeclinable = true
end
end
end
if irregular then
inscat("nouns with irregular plurals")
end
if indeclinable then
inscat("indeclinable nouns")
end
insert_inflection(data, plurals, "plural", "p")
end
-- Return the parameters to be used for nouns and proper nouns. Currently the same.
local noun_params = {
[1] = list_param,
["pl\1qual"] = {list = true, allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the plural",
},
-- The following four only used for pluralia tantum (1=p)
["sg"] = list_param,
["attr"] = list_param,
}
pos_functions["nouns"] = {
params = noun_params,
func = do_nouns,
}
pos_functions["proper nouns"] = {
params = noun_params,
func = function(args, data)
return do_nouns(args, data, "proper noun")
end,
}
local function base_default_verb_forms(verb)
return escape(add_suffix(verb, "s.verb")), escape(add_suffix(verb, "ing")), escape(add_suffix(verb, "d"))
end
local function default_verb_forms(verb)
local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb)
if verb:find(" ") then
local first, rest = verb:match("^(.-)( .*)$")
local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first)
return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest,
first_ed_form .. rest, first, rest
else
return full_s_form, full_ing_form, full_ed_form, nil, nil, nil, nil, nil
end
end
local function compute_double_last_cons_stem_of_split_verb(verb, ending)
local first, rest = verb:match("^(.-)( .*)$")
if not first then
error("Verb '" .. verb .. "' must have a space in it to use **")
end
local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$")
if not last_cons then
error("First word '" .. first .. "' must end in a consonant to use **")
end
return first .. last_cons .. ending .. rest
end
local function check_non_nil_star_form(form, pagename)
if form == nil then
error("Verb '" .. pagename .. "' must have a space in it to use *, **, *l, *! or *'")
end
return form
end
local function sub_tilde(form, pagename)
if not form then
return nil
end
if form:find("~") then
form = form:gsub("~", replacement_escape(pagename))
end
return form
end
local deprecated_qual_replaced_by_inline_modifier = {
list = true, allow_holes = true, replaced_by = false,
instead = "use an inline modifier <q:...> or <l:...> on the value"
}
pos_functions["verbs"] = {
params = {
[1] = {list = "pres_3sg", disallow_holes = true},
["pres_3sg\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[2] = {list = "pres_ptc", disallow_holes = true},
["pres_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[3] = {list = "past", disallow_holes = true},
["past\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[4] = {list = "past_ptc", allow_holes = true},
["past_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
["noautolinkverb"] = boolean_param,
["angle_bracket"] = boolean_param,
},
func = function(args, data)
-- Get parameters
local par1s
local par2s = parse_inflection(args, {2, "pres_ptc"})
local par3s = parse_inflection(args, {3, "past"})
local par4s = parse_inflection(args, {4, "past_ptc"})
local pres_3sgs, pres_ptcs, pasts, past_ptcs
local pagename = data.pagename
------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------
-- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=.
local full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed
local lemma
local function set_lemma_and_default_forms(the_lemma)
lemma = the_lemma
full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed,
lemma_first, lemma_rest = default_verb_forms(the_lemma)
end
local function canonicalize_s_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_s
elseif form == "*" then
return check_non_nil_star_form(split_default_s, lemma)
elseif form == "++" then
return compute_plusplus_s_form(lemma, full_default_s)
elseif form == "**" then
if lemma:find("^[^ ]*[szx] ") then
return compute_double_last_cons_stem_of_split_verb(lemma, "es")
else
return check_non_nil_star_form(split_default_s, lemma)
end
elseif form == "+!" then
return lemma .. "s"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "s" .. lemma_rest
elseif form == "+'" then
return lemma .. "'s"
elseif form == "*'" then
return check_non_nil_star_form(lemma_first) .. "'s" .. lemma_rest
elseif form == "+l" then
if lemma:find("[szx]$") then
return {{term = full_default_s, l = {"US"}},
{term = compute_plusplus_s_form(lemma, full_default_s), l = {"UK"}}}
else
return compute_plusplus_s_form(lemma, full_default_s)
end
elseif form == "*l" then
if lemma:find("^[^ ]*[szx] ") then
return {{term = check_non_nil_star_form(split_default_s, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "es"), l = {"UK"}}}
else
return check_non_nil_star_form(split_default_s, lemma)
end
else
return sub_tilde(form, lemma)
end
end
local function canonicalize_ing_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_ing
elseif form == "*" then
return check_non_nil_star_form(split_default_ing, lemma)
elseif form == "++" then
return compute_double_last_cons_stem(lemma) .. "ing"
elseif form == "**" then
return compute_double_last_cons_stem_of_split_verb(lemma, "ing")
elseif form == "+!" then
return lemma .. "ing"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "ing" .. lemma_rest
elseif form == "+'" then
return lemma .. "'ing"
elseif form == "*'" then
return check_non_nil_star_form(lemma_first) .. "'ing" .. lemma_rest
elseif form == "+l" then
return {{term = full_default_ing, l = {"US"}},
{term = compute_double_last_cons_stem(lemma) .. "ing", l = {"UK"}}}
elseif form == "*l" then
return {{term = check_non_nil_star_form(split_default_ing, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "ing"), l = {"UK"}}}
else
return sub_tilde(form, lemma)
end
end
local function canonicalize_ed_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_ed
elseif form == "*" then
return check_non_nil_star_form(split_default_ed, lemma)
elseif form == "++" then
return compute_double_last_cons_stem(lemma) .. "ed"
elseif form == "+!" then
return lemma .. "ed"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "ed" .. lemma_rest
elseif form == "+'" then
return {{term = lemma .. "'d"}, {term = lemma .. "'ed"}}
elseif form == "*'" then
return {{term = check_non_nil_star_form(lemma_first) .. "'d" .. lemma_rest},
{term = check_non_nil_star_form(lemma_first) .. "'ed" .. lemma_rest}}
elseif form == "**" then
return compute_double_last_cons_stem_of_split_verb(lemma, "ed")
elseif form == "+l" then
return {{term = full_default_ed, l = {"US"}},
{term = compute_double_last_cons_stem(lemma) .. "ed", l = {"UK"}}}
elseif form == "*l" then
return {{term = check_non_nil_star_form(split_default_ed, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "ed"), l = {"UK"}}}
else
return sub_tilde(form, lemma)
end
end
-- FIXME: options should be "+", "*", "++", "**", "+n", "*n", "++n" and "**n", but not "n"
local function canonicalize_en_form(form)
if form == "n" then
track("n4")
return add_suffix(lemma, "n")
end
return canonicalize_ed_form(form)
end
--------------------------------- MAIN PARSING/CONJUGATING CODE --------------------------------
local is_angle_bracket = args.angle_bracket
if is_angle_bracket then
if par2s[1] or par3s[1] or par4s[1] then
error("Can't specify explicit values for 2=, 3= or 4= along with the angle-bracket format")
end
elseif is_angle_bracket == nil and not par2s[1] and not par3s[1] and not par4s[1] and not args[1][2] and
args[1][1] and args[1][1]:find("<") then
if put.term_contains_top_level_html(args[1][1]) then
-- Often, term_contains_top_level_html() returns true on the angle-bracket format, which would
-- make the pcall() below succeed but leave the angle brackets as-is. Check for this and only do the
-- pcall() if term_contains_top_level_html() returns false.
is_angle_bracket = true
else
-- If it's ambiguous whether it's an angle-bracket format or separate params with an inline modifier,
-- try to parse as the latter. If an error occurs, treat as the former.
local ok
ok, par1s = pcall(parse_inflection, args, {1, "pres_3sg"})
if not ok then
par1s = nil
is_angle_bracket = true
end
end
end
if is_angle_bracket then
-------------------------- ANGLE-BRACKET FORMAT --------------------------
-- (0) Expand multiword term with angle brackets just on the first word.
local arg11 = args[1][1]
if arg11:find("^<.*>$") and pagename:find(" ") then
local first, rest = pagename:match("^(.-)( .*)$")
arg11 = first .. arg11 .. rest
end
-- (1) Parse the indicator specs inside of angle brackets.
local function parse_indicator_spec(angle_bracket_spec)
local inside = angle_bracket_spec:match("^<(.*)>$")
assert(inside)
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local comma_separated_groups = put.split_alternating_runs(segments, ",")
if #comma_separated_groups > 4 then
error("Too many comma-separated parts in indicator spec, expected at most 4: " ..
angle_bracket_spec)
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
error("Extraneous text after bracketed footnotes: '" .. concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
insert(footnotes, separated_group[j])
end
return footnotes
end
local function fetch_specs(comma_separated_group)
if not comma_separated_group then
return {{term = "+"}}
end
local specs = {}
local colon_separated_groups = put.split_alternating_runs(comma_separated_group, ":")
for _, colon_separated_group in ipairs(colon_separated_groups) do
local form = colon_separated_group[1]
if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
error("*, **, *l, *! and *' not allowed inside of indicator specs: " .. angle_bracket_spec)
end
if form == "" then
form = "+"
end
local termobj = {
term = form
}
local footnotes = fetch_footnotes(colon_separated_group)
if footnotes then
for _, footnote in ipairs(footnotes) do
m_headword_utilities.add_footnote_to_termobj(termobj, footnote)
end
end
insert(specs, termobj)
end
return specs
end
local s_specs = fetch_specs(comma_separated_groups[1])
local ing_specs = fetch_specs(comma_separated_groups[2])
local ed_specs = fetch_specs(comma_separated_groups[3])
local en_specs = fetch_specs(comma_separated_groups[4])
return {
forms = {},
s_specs = s_specs,
ing_specs = ing_specs,
ed_specs = ed_specs,
en_specs = en_specs,
}
end
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg11, parse_props)
-- (2) Check for user-specified brackets; remove any links from the lemma, but remember the original
-- form so we can use it below in the 'lemma_linked' form.
-- Check to see if there are brackets in the pre-text or post-text. If so, use the linked lemma (with the
-- verb autolinked unless noautolinkverb is given). Otherwise, use the default headword algorithm.
local function check_bracket(val)
if val:find("%[%[") then
alternant_multiword_spec.saw_bracket = true
end
end
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
check_bracket(alternant_or_word_spec.before_text)
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for _, word_spec in ipairs(multiword_spec.word_specs) do
check_bracket(word_spec.before_text)
end
check_bracket(multiword_spec.post_text)
end
end
end
check_bracket(alternant_multiword_spec.post_text)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.lemma == "" then
base.lemma = pagename
end
base.orig_lemma = base.lemma
base.lemma = remove_links(base.lemma)
if args.noautolinkverb or base.orig_lemma:find("%[%[") then
base.linked_lemma = base.orig_lemma
else
base.linked_lemma = "[[" .. base.orig_lemma .. "]]"
end
end)
-- (3) Conjugate the verbs according to the indicator specs parsed above.
local all_verb_slots = {
lemma = "infinitive",
lemma_linked = "infinitive",
s_form = "3|s|pres",
ing_form = "pres|ptcp",
ed_form = "past",
en_form = "past|ptcp",
}
local function conjugate_verb(base)
local function process_specs(slot, specs, canon_func, default_values, default_already_formobj)
local function insert_termobj_into_slot(termobj)
local formobj = m_headword_utilities.convert_termobj_to_formobj(termobj)
-- If the form is -, don't insert any forms, which will result in there being no overall forms
-- (in fact it will be nil). We check for that down below and substitute a single "-" as the
-- form, which in turn gets turned into special labels like "no present participle".
if formobj.form == "-" then
if formobj.footnotes then
error("Unable to preserve footnotes specified on missing form '-': FIXME: " ..
dump(formobj.footnotes))
end
else
iut.insert_form(base.forms, slot, formobj)
end
end
local function canonicalize_and_insert(arg)
local canon_arg = canon_func(arg)
if type(canon_arg) == "string" then
arg.term = canon_arg
insert_termobj_into_slot(arg)
else
for _, canon in ipairs(canon_arg) do
m_headword_utilities.combine_termobj_decorations(canon, arg)
insert_termobj_into_slot(canon)
end
end
end
for _, arg in ipairs(specs) do
if arg.term == "+" then
if default_values then -- will be nil if past tense specified as - and no past ptc given
for _, val in ipairs(default_values) do
val = shallowCopy(val)
if default_already_formobj then
local argformobj = m_headword_utilities.convert_termobj_to_formobj(arg)
val.footnotes = iut.combine_footnotes(val.footnotes, argformobj.footnotes)
iut.insert_form(base.forms, slot, val)
else
m_headword_utilities.combine_termobj_decorations(val, arg)
canonicalize_and_insert(val)
end
end
end
else
canonicalize_and_insert(arg)
end
end
end
set_lemma_and_default_forms(base.lemma)
local all_part_default_specs = {}
local function process_and_canonicalize_s_form(arg)
local form = arg.term
if form == "+" then
error("Internal error: '+' should have been converted to '^' by now")
end
if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
error(("Internal error: '%s' should have already thrown an error"):format(form))
end
if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" then
insert(all_part_default_specs, shallowCopy(arg))
end
return canonicalize_s_form(form)
end
process_specs("s_form", base.s_specs, process_and_canonicalize_s_form, {{term = "^"}})
if not all_part_default_specs[1] then
all_part_default_specs[1] = {term = "^"}
end
process_specs("ing_form", base.ing_specs, function(arg) return canonicalize_ing_form(arg.term) end,
all_part_default_specs)
process_specs("ed_form", base.ed_specs, function(arg) return canonicalize_ed_form(arg.term) end,
all_part_default_specs)
process_specs("en_form", base.en_specs, function(arg) return canonicalize_en_form(arg.term) end,
base.forms.ed_form, "default already formobj")
iut.insert_form(base.forms, "lemma", {form = base.lemma})
-- Add linked version of lemma for use in head=. We write this in a general fashion in case
-- there are multiple lemma forms (which isn't possible currently at this level, although it's
-- possible overall using the ((...,...)) notation).
iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form)
if form == base.lemma and base.linked_lemma:find("%[%[") then
return base.linked_lemma
else
return form
end
end))
end
local inflect_props = {
slot_table = all_verb_slots,
inflect_word_spec = conjugate_verb,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given.
local function fetch_termobjs(slot)
local forms = alternant_multiword_spec.forms[slot]
-- See above. This should only occur if the user explicitly used - for a spec.
if not forms or not forms[1] then
return {{term = "-"}}
end
local termobjs = {}
for _, formobj in ipairs(forms) do
insert(termobjs, m_headword_utilities.convert_formobj_to_termobj(formobj))
end
return termobjs
end
pres_3sgs = fetch_termobjs("s_form")
pres_ptcs = fetch_termobjs("ing_form")
pasts = fetch_termobjs("ed_form")
past_ptcs = fetch_termobjs("en_form")
-- Use the "linked" form of the lemma as the head if no head= explicitly given and the user specified
-- brackets in one of the lemmas. Otherwise we use the default headword-linking algorithm.
if not data.user_specified_heads[1] and alternant_multiword_spec.saw_bracket then
data.heads = {}
for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do
insert(data.heads, m_headword_utilities.convert_formobj_to_termobj(lemma_obj))
end
end
else
-------------------------- SEPARATE-PARAM FORMAT --------------------------
set_lemma_and_default_forms(pagename)
par1s = par1s or parse_inflection(args, {1, "pres_3sg"})
pres_3sgs = {}
pres_ptcs = {}
pasts = {}
past_ptcs = {}
if not par1s[1] then
par1s = {{term = "+"}}
end
if not par2s[1] then
par2s = {{term = "+"}}
end
if not par3s[1] then
par3s = {{term = "+"}}
end
if not par4s[1] then
par4s = {{term = "+"}}
end
local function process_argument(args, dest, canon_func, default_values, default_already_canonicalized)
local function canonicalize_and_insert(arg)
local canon_arg = canon_func(arg)
if type(canon_arg) == "string" then
arg.term = canon_arg
m_headword_utilities.insert_termobj_combining_duplicates(dest, arg)
else
for _, canon in ipairs(canon_arg) do
m_headword_utilities.combine_termobj_decorations(canon, arg)
m_headword_utilities.insert_termobj_combining_duplicates(dest, canon)
end
end
end
for _, arg in ipairs(args) do
if arg.term == "+" then
for _, val in ipairs(default_values) do
val = shallowCopy(val)
m_headword_utilities.combine_termobj_decorations(val, arg)
if default_already_canonicalized then
m_headword_utilities.insert_termobj_combining_duplicates(dest, val)
else
canonicalize_and_insert(val)
end
end
else
canonicalize_and_insert(arg)
end
end
end
local all_part_default_specs = {}
local function process_and_canonicalize_s_form(arg)
local form = arg.term
if form == "+" then
error("Internal error: '+' should have been converted to '^' by now")
end
if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" or
form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
insert(all_part_default_specs, shallowCopy(arg))
end
return canonicalize_s_form(form)
end
process_argument(par1s, pres_3sgs, process_and_canonicalize_s_form, {{term = "^"}})
if not all_part_default_specs[1] then
all_part_default_specs[1] = {term = "^"}
end
process_argument(par2s, pres_ptcs, function(arg) return canonicalize_ing_form(arg.term) end,
all_part_default_specs)
process_argument(par3s, pasts, function(arg) return canonicalize_ed_form(arg.term) end,
all_part_default_specs)
process_argument(par4s, past_ptcs, function(arg) return canonicalize_en_form(arg.term) end,
pasts, "default already canonicalized")
end
------------------------------------------- INSERT INFLECTIONS ------------------------------------------
insert_inflection(data, pres_3sgs, "third-person singular simple present", "s-verb-form")
insert_inflection(data, pres_ptcs, "present participle", "ing-form")
if deepEquals(pasts, past_ptcs) then
insert_inflection(data, pasts, "simple past and past participle", "ed-form",
"no simple past or past participle")
else
insert_inflection(data, pasts, "simple past", "spast")
insert_inflection(data, past_ptcs, "past participle", "past|part")
end
if pagename:find(" ") then
-- Check for placeholder "it"
local words = split(pagename, " ")
for _, word in ipairs(words) do
if word == "it" or word == "its" or word == "it's" then
insert(data.categories, langname .. ' terms with placeholder "it"')
break
end
end
-- Check for phrasal verbs
local phrasal_adverbs = list_to_set{
-- NOTE: This should only contain common phrasal adverbs, not random words like [[low]],
-- [[adrift]], etc.
"aback",
"about",
"above",
"across",
"after",
"against",
"ahead",
"along",
"apart",
"around",
"as",
"aside",
"at",
"away",
"back",
"before",
"behind",
"below",
"between",
"beyond",
"by",
"down",
"for",
"forth",
"from",
"in",
"into",
"of",
"off",
"on",
"onto",
"out",
"over",
"past",
"round",
"through",
"to",
"together",
"towards",
"under",
"up",
"upon",
"with",
"without",
}
local allowed_non_adverb_words = list_to_set{
"it",
"one",
"oneself",
"someone",
}
local base = pagename
local seen_adverbs = {}
-- Only consider a verb to be phrasal if it consists of a single base verb followed exclusively by either
-- adverbs from `phrasal_adverbs` or placeholder words from `allowed_non_adverb_words`, where at
-- least one following word is from `phrasal_adverbs` (hence [[can it]] is not a phrasal verb).
while true do
local prev, word = base:match("^(.+) (.-)$")
if not prev then
break
end
if phrasal_adverbs[word] then
insert(seen_adverbs, word)
elseif allowed_non_adverb_words[word] then
-- do nothing
else
break
end
base = prev
end
if not base:find(" ") and seen_adverbs[1] then
insert(data.categories, langname .. " phrasal verbs")
for i = #seen_adverbs, 1, -1 do
insert(data.categories, langname .. ' phrasal verbs formed with "' .. seen_adverbs[i] ..
'"')
end
end
end
end,
}
-----------------------------------------------------------------------------------------
-- Suffix forms --
-----------------------------------------------------------------------------------------
pos_functions["suffix forms"] = {
params = {
[1] = {required = true, list = true, disallow_holes = true},
},
func = function(args, data, is_suffix)
local suffix_type = {}
for _, typ in ipairs(args[1]) do
insert(suffix_type, typ .. "-forming suffix")
end
insert(data.inflections, {label = "non-lemma form of " .. m_table.serialCommaJoin(suffix_type, {conj = "or"})})
end,
}
return export
0y7pjz4c7dizgg3z3q1tkbk5xwvaqqv
54932
54931
2026-09-29T19:26:17Z
Deadend0914
7211
54932
Scribunto
text/plain
local export = {}
local pos_functions = {}
--[==[
Author from 2020 on: mostly Benwing2, with significant contributions from Theknightwho. Based on a prior version by Rua
(by now mostly rewritten), with contributions from Erutuon and others (see history for full attribution).
]==]
local force_cat = false -- for testing; if true, categories appear in non-mainspace pages
local require = require
local require_when_needed = require("Module:require when needed")
local en_utilities_module = "Module:en-utilities"
local headword_utilities_module = "Module:headword utilities"
local headword_module = "Module:headword"
local inflection_utilities_module = "Module:inflection utilities"
local parse_utilities_module = "Module:parse utilities"
local JSON_module = "Module:JSON"
local labels_module = "Module:labels"
local links_module = "Module:links"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local yesno_module = "Module:yesno"
local iut = require_when_needed(inflection_utilities_module)
local put = require_when_needed(parse_utilities_module)
local m_headword_utilities = require_when_needed(headword_utilities_module)
local add_links_to_multiword_term = require_when_needed(headword_utilities_module, "add_links_to_multiword_term")
local add_suffix = require_when_needed(en_utilities_module, "add_suffix")
local apply_link_modifiers = require_when_needed(headword_utilities_module, "apply_link_modifiers")
local concat = table.concat
local deepEquals = require_when_needed(table_module, "deepEquals")
local dump = mw.dumpObject
local format_categories = require_when_needed(utilities_module, "format_categories")
local full_headword = require_when_needed(headword_module, "full_headword")
local get_label_info = require_when_needed(labels_module, "get_label_info")
local get_link_page = require_when_needed(links_module, "get_link_page")
local glossary_link = require_when_needed(headword_utilities_module, "glossary_link")
local insert = table.insert
local insertIfNot = require_when_needed(table_module, "insertIfNot")
local ipairs = ipairs
local is_regular_plural = require_when_needed(en_utilities_module, "is_regular_plural")
local list_to_set = require_when_needed(table_module, "listToSet")
local pairs = pairs
local process_params = require_when_needed(parameters_module, "process")
local remove = table.remove
local remove_links = require_when_needed(links_module, "remove_links")
local replacement_escape = require_when_needed(string_utilities_module, "replacement_escape")
local shallowCopy = require_when_needed(table_module, "shallowCopy")
local singularize = require_when_needed(en_utilities_module, "singularize")
local split = require_when_needed(string_utilities_module, "split")
local toJSON = require_when_needed(JSON_module, "toJSON")
local toNFD = mw.ustring.toNFD
local type = type
local ulen = require_when_needed(string_utilities_module, "len")
local ulower = require_when_needed(string_utilities_module, "lower")
local umatch = require_when_needed(string_utilities_module, "match")
local u = require_when_needed(string_utilities_module, "char")
local ugsub = require_when_needed(string_utilities_module, "gsub")
local lang = require("Module:languages").getByCode("en")
local langname = lang:getCanonicalName()
local list_param = {list = true, disallow_holes = true}
local list_allow_holes = {list = true, allow_holes = true}
local boolean_param = {type = "boolean"}
local function ine(val)
if val == "" then return nil else return val end
end
local function track(page)
require("Module:debug/track")("en-headword/" .. page)
return true
end
------------------------------------------- UTILITY FUNCTIONS ------------------------------------------
-- Parse and return an inflection not requiring additional processing. The raw arguments come from `args[field]`, which
-- is parsed for inline modifiers.
local function parse_inflection(args, field, is_head)
local argfield = field
if type(argfield) == "table" then
argfield = argfield[1]
end
return m_headword_utilities.parse_term_list_with_modifiers {
paramname = field,
forms = args[argfield],
splitchar = ",",
is_head = is_head,
}
end
-- Insert the parsed inflections in `terms` (as parsed by `parse_inflection`) into `data.inflections`, with label
-- `label` and optional accelerator spec `accel`.
local function insert_inflection(data, terms, label, accel, no_label)
for _, termobj in ipairs(terms) do
m_headword_utilities.remove_termobj_field_modifiers(termobj)
end
m_headword_utilities.insert_inflection {
headdata = data,
terms = terms,
label = label,
no_label = no_label,
accel = accel and {form = accel} or nil,
}
end
-- Insert a fixed label `label` into the inflections for `data`. If `originating_term` is supplied, copy the decorations
-- from it into the fixed label.
local function insert_fixed_inflection(data, label, originating_term)
m_headword_utilities.insert_fixed_inflection {
headdata = data,
originating_term = originating_term,
label = label,
}
end
-- Parse and insert an inflection not requiring additional processing into `data.inflections`. The raw arguments come
-- from `args[field]`, which is parsed for inline modifiers. `label` is the label that the inflections are given;
-- `accel` is the accelerator form, or nil.
local function parse_and_insert_inflection(data, args, field, label, accel)
m_headword_utilities.parse_and_insert_inflection {
headdata = data,
forms = args[field],
paramname = field,
splitchar = ",",
label = label,
accel = accel and {form = accel} or nil,
}
end
-- These functions are used directly in the <> format as well as in the utility functions #2 below.
local function compute_double_last_cons_stem(term)
local last_cons = term:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$")
if not last_cons then
error("Verb stem '" .. term .. "' must end in a consonant to use ++")
end
return term .. last_cons
end
local function compute_plusplus_s_form(term, default_s_form)
if term:find("[szx]$") then
-- regas -> regasses, derez -> derezzes
return compute_double_last_cons_stem(term) .. "es"
else
return default_s_form
end
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local iparams = {
[1] = true,
}
local iargs = require("Module:parameters").process(frame.args, iparams)
local parargs = frame:getParent().args
local poscat = iargs[1]
local pos_in_1 = not poscat
if pos_in_1 then
poscat = ine(parargs[1]) or
mw.title.getCurrentTitle().fullText == "Template:en-head" and "interjection" or
error("Part of speech must be specified in 1=")
poscat = require(headword_module).canonicalize_pos(poscat)
end
local indexing_poscat = pos_in_1 and "head" or poscat
local params = {
["head"] = list_param,
["id"] = true,
["json"] = boolean_param,
["sort"] = true,
["splithyph"] = boolean_param,
["nosplithyph"] = boolean_param,
["hyphspace"] = boolean_param,
["nolink"] = boolean_param,
["nolinkhead"] = {type = "boolean_param", alias_of = "nolink"},
["suffix"] = boolean_param,
["nosuffix"] = boolean_param,
["nomultiwordcat"] = boolean_param,
["abbr"] = list_param,
["the"] = true,
["def"] = {alias_of = "the"},
["pagename"] = true, -- for testing
}
if pos_in_1 then
params[1] = {required = true} -- required but ignored as already processed above
end
local pos_data = pos_functions[indexing_poscat]
local pos_func
if pos_data then
local pos_params = pos_data.params
if pos_params then
for key, val in pairs(pos_params) do
params[key] = val
end
end
pos_func = pos_data.func
end
local args = process_params(parargs, params)
-- Account for unsupported titles, e.g. 'C|N>K' instead of 'Unsupported titles/C through N to K'.
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
local user_specified_heads = parse_inflection(args, "head", "is_head")
local heads = user_specified_heads
local autohead
if args.nolink or not pagename:find("[ '%-]") then
autohead = pagename
else
local en_no_split_apostrophe_words = list_to_set {
"one's",
"someone's",
"he's",
"she's",
"it's",
}
local en_include_hyphen_prefixes = list_to_set {
-- We don't include things that are also words even though they are often (perhaps mostly) prefixes, e.g.
-- "be", "counter", "cross", "extra", "half", "mid", "over", "pan", "under".
"acro",
"acousto",
"Afro",
"agro",
"anarcho",
"angio",
"Anglo",
"ante",
"anti",
"arch",
"auto",
"bi",
"bio",
"cis",
"co",
"cryo",
"crypto",
"de",
"demi",
"eco",
"electro",
"Euro",
"ex",
"Greco",
"hemi",
"hydro",
"hyper",
"hypo",
"infra",
"Indo",
"inter",
"intra",
"Judeo",
"macro",
"meta",
"micro",
"mini",
"multi",
"neo",
"neuro",
"non",
"para",
"peri",
"post",
"pre",
"pro",
"proto",
"pseudo",
"re",
"semi",
"sub",
"super",
"trans",
"un",
"vice",
}
local function is_english(term)
local title = mw.title.new(term)
if title and title.exists then
local content = title:getContent()
if content and content:find("==English==\n") then
return true
end
end
return false
end
local function en_split_hyphen_when_space(word)
if not word:find("-", nil, true) then
return nil
end
if args.hyphspace then
return "[[" .. word:gsub("%-+", " ") .. "|" .. word .. "]]"
end
if args.nosplithyph then
return "[[" .. word .. "]]"
end
if not args.splithyph then
local space_word = word:gsub("%-+", " ")
if is_english(space_word) then
return "[[" .. space_word .. "|" .. word .. "]]"
end
if is_english(word) then
return "[[" .. word .. "]]"
end
end
return nil
end
local function en_split_apostrophe(word)
local base = word:match("^(.*)'s$")
if base then
return "[[" .. base .. "]][[-'s|'s]]"
end
-- Only treat final apostrophe as possessive if preceded by something that looks like a plural ending in /z/.
-- In particular we don't want to do it for words like [[truckin']].
base = word:match("^(.*[sxz])'$")
if base then
if base:find("s$") then
local sg = singularize(base)
if is_english(sg) then
return "[[" .. sg .. "|" .. base .. "]][[-'|']]"
end
end
return "[[" .. base .. "]][[-'|']]"
end
return "[[" .. word .. "]]"
end
autohead = add_links_to_multiword_term(pagename, {
split_hyphen_when_space = en_split_hyphen_when_space,
split_apostrophe = en_split_apostrophe,
no_split_apostrophe_words = en_no_split_apostrophe_words,
include_hyphen_prefixes = en_include_hyphen_prefixes,
})
end
if not heads[1] then
heads = {{term = autohead}}
else
for _, headobj in ipairs(heads) do
local head = headobj.term
if head:find("^~") then
head = apply_link_modifiers(autohead, head:sub(2), lang)
headobj.term = head
elseif head:find("^[!?]$") then
-- If explicit head= just consists of ! or ?, add it to the end of the default head.
headobj.term = autohead .. head
end
if head == autohead then
track("redundant-head")
end
end
end
-- handle the=/def=
if args.the == "~" then
local newheads = {}
for _, headobj in ipairs(heads) do
local barehead = shallowCopy(headobj)
insert(newheads, barehead)
headobj.term = "the " .. headobj.term
insert(newheads, headobj)
end
heads = newheads
elseif args.the then
local the = require(yesno_module)(args.the)
if the then
for _, headobj in ipairs(heads) do
headobj.term = "the " .. headobj.term
end
end
end
local data = {
lang = lang,
pos_category = poscat,
categories = {},
heads = heads,
user_specified_heads = user_specified_heads,
-- We use our own splitting algorithm so the redundant head cat will be inaccurate.
no_redundant_head_cat = true,
inflections = {},
nomultiwordcat = args.nomultiwordcat,
sort_key = args.sort,
pagename = pagename,
id = args.id,
force_cat_output = force_cat,
}
local function inscat(cat)
insert(data.categories, langname .. " " .. cat)
end
local is_suffix = false
if args.suffix or not args.nosuffix and pagename:find("^%-") and not pagename:find("^%-%-") and poscat ~= "suffix forms" then
is_suffix = true
data.pos_category = "suffixes"
local singular_poscat = singularize(poscat)
inscat(singular_poscat .. "-forming suffixes")
insert(data.inflections, {label = singular_poscat .. "-forming suffix"})
end
if pos_func then
pos_func(args, data, is_suffix)
end
local extra_categories = {}
if pagename:find("[Qq]") then
-- Check for q not followed by u. We want to exclude things like [[13q deletion syndrome]] and [[BFOQ]] that
-- don't have a lowercase letter on either side, as well as things like [[& seq.]] and [[acq.]] that are
-- abbreviations for words containing a following u.
--
-- Approximate range of combining diacritics; we want to remove them so the checks below for
-- a lowercase letter next to the q aren't tripped up by diacritics on the letter.
local u300 = u(0x0300)
local u36F = u(0x036F)
local pagename_no_diacritics = ugsub(toNFD(pagename), "[" .. u300 .. "-" .. u36F .. "]", "")
if pagename_no_diacritics:find("[Qq][a-tv-z]") or pagename_no_diacritics:find("[a-z]q[^u.]") or
pagename_no_diacritics:find("[a-z]q$") then
inscat("words containing Q not followed by U")
end
end
-- toNFD performs decomposition, so letters that decompose to an ASCII
-- vowel and a diacritic, such as é, are counted as vowels and do not do not
-- need to be included in the pattern.
if not umatch(ulower(toNFD(pagename)), "[aeiouyæœøəªºαεηιουω]") then
inscat("words spelled wiþūtan vowels")
end
if pagename:find("yre$") then
inscat('words ending in "-yre"')
end
if not pagename:find(" ") and ulen(pagename) >= 25 then
insert(extra_categories, "Long " .. langname .. " words")
end
if pagename:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then
inscat("words that use all vowels in alphabetical order")
end
parse_and_insert_inflection(data, args, "abbr", "abbreviation")
if args.json then
return toJSON(data)
end
return full_headword(data)
.. (extra_categories[1]
and format_categories(extra_categories, lang, args.sort)
or "")
end
local function make_default_comparative(word)
if word == "good" or word == "well" then
return {"better"}
elseif word == "bad" or word == "badly" then
return {"worse"}
elseif word == "far" then
return {"further", "farther"}
else
return {add_suffix(word, "r")}
end
end
local function make_default_superlative(word)
if word == "good" or word == "well" then
return {"best"}
elseif word == "bad" or word == "badly" then
return {"worst"}
elseif word == "far" then
return {"furthest", "farthest"}
else
return {add_suffix(word, "st.superlative")}
end
end
-- This function does the common work between adjectives and adverbs.
local function process_comparative_args(data, args, plpos)
local pagename = data.pagename
local comps = parse_inflection(args, 1)
local sups = parse_inflection(args, "sup")
local outcomps, outsups
if args.componly then
if comps[1] then
error("Can't specify comparatives of comparative-only " .. plpos)
end
insert(data.inflections, {label = glossary_link("comparative") .. " form only"})
insert(data.categories, langname .. " comparative-only " .. plpos)
-- Set to empty list so we don't get any comparatives output, but process superlatives if specified.
outcomps = {}
if not sups[1] then
-- Set to empty list so we don't get any superlatives output unless explicitly given.
outsups = {}
end
elseif args.suponly then
if comps[1] or sups[1] then
error("Can't specify comparatives or superlatives of or superlative-only " .. plpos)
end
insert(data.inflections, {label = glossary_link("superlative") .. " form only"})
insert(data.categories, langname .. " superlative-only " .. plpos)
return
end
-- If the first parameter is ?, then don't show anything, just return.
if comps[1] and comps[1].term == "?" then
if comps[2] then
error("Can't specify additional comparatives along wiþ '?'")
end
if sups[1] then
error("Can't specify superlatives along wiþ '?' for the comparative")
end
return
end
if comps[1] and comps[1].term == "-" then
local hyphencomp = remove(comps, 1) -- Remove the "-" but retain for decorations.
-- Not (generally) comparable; may occasionally have a comparative
if comps[1] then
insert_fixed_inflection(data, "not generally <<comparable>>", hyphencomp)
elseif not sups[1] then
insert_fixed_inflection(data, "not <<comparable>>", hyphencomp)
insert(data.categories, langname .. " uncomparable " .. plpos)
return
else
-- No comparative, but a superlative. insert_inflection() will correctly generate 'no comparative' if we
-- pass in "-" as the value.
outcomps = {hyphencomp}
end
elseif not comps[1] then
comps = {{term = "more"}}
end
if not outcomps then -- not if we set `outcomps` to "-" above or processed a comparative-only term
outcomps = {}
-- Go over each parameter given and create a comparative and superlative form.
for _, compobj in ipairs(comps) do
local comp = compobj.term
if comp == "-" then
error("Comparative of '-' only allowed as first comparative")
end
if comp == "+" then
comp = "+more"
elseif comp == "more" and pagename ~= "many" and pagename ~= "much" then
comp = "+more"
elseif comp == "further" and pagename ~= "far" then
comp = "+further"
elseif comp == "better" and pagename ~= "good" and pagename ~= "well" then
comp = "+better"
elseif comp:find("~") then
comp = comp:gsub("~", replacement_escape(pagename))
end
compobj.origterm = comp
if comp == "+more" then
comp = "more [[" .. pagename .. "]]"
elseif comp == "+further" then
comp = {"further [[" .. pagename .. "]]", "farther [[" .. pagename .. "]]"}
elseif comp == "+better" then
comp = "better [[" .. pagename .. "]]"
elseif comp == "er" then
-- Add -er.
comp = add_suffix(pagename, "r")
elseif comp == "ier" then
if pagename:sub(-1) ~= "y" then
error("Can't specify 'ier' comparative unless the term ends wiþ 'y': " .. pagename)
end
comp = pagename:gsub("e?y$", "ier")
elseif comp:find("^%+") then
local special = m_headword_utilities.get_special_indicator(comp, "noerror")
if special then
comp = m_headword_utilities.handle_multiword(pagename, special, make_default_comparative)
end
end
if type(comp) == "table" and not comp[2] then
comp = comp[1]
end
if type(comp) == "table" then
for i = 1, #comp - 1 do
local outobj = shallowCopy(compobj)
outobj.term = comp[i]
insert(outcomps, outobj)
end
compobj.term = comp[#comp]
insert(outcomps, compobj)
else
compobj.term = comp
insert(outcomps, compobj)
end
end
end
if sups[1] and sups[1].term == "-" then
if sups[2] then
error("Can't specify '-' as superlative followed by further values")
end
-- No superlative. insert_inflection() will correctly generate 'no superlative' if we pass in "-" as the value.
outsups = sups
else
if not sups[1] then
sups = {{term = "+"}}
end
end
-- `outsups` will be set if we set `outsups` to "-" above or processed a comparative-only term without superlatives.
if not outsups then
outsups = {}
local function process_sup(sup, special, supobj, compobj)
if special then
sup = m_headword_utilities.handle_multiword(pagename, special, make_default_superlative)
elseif sup == "-" or sup == "+" then
error(("Internal error: Superlative value of '%s' should have been handled earlier"):format(sup))
elseif sup == "+most" then
sup = "most [[" .. pagename .. "]]"
elseif sup == "+furthest" then
sup = {"furthest [[" .. pagename .. "]]", "farthest [[" .. pagename .. "]]"}
elseif sup == "+best" then
sup = "best [[" .. pagename .. "]]"
elseif sup == "est" then
-- Add -est.
sup = add_suffix(pagename, "st.superlative")
elseif sup == "iest" then
if pagename:sub(-1) ~= "y" then
error("Can't specify 'iest' superlative unless the term ends wiþ 'y': " .. pagename)
end
sup = pagename:gsub("e?y$", "iest")
end
if type(sup) == "table" and not sup[2] then
sup = sup[1]
end
if compobj then
supobj = shallowCopy(supobj)
supobj = m_headword_utilities.combine_termobj_decorations(supobj, compobj)
end
if type(sup) == "table" then
for i = 1, #sup - 1 do
local outobj = shallowCopy(supobj)
outobj.term = sup[i]
insert(outsups, outobj)
end
supobj.term = sup[#sup]
insert(outsups, supobj)
else
supobj.term = sup
insert(outsups, supobj)
end
end
for _, supobj in ipairs(sups) do
local sup = supobj.term
if sup == "-" then
error("Superlative of '-' only allowed as first superlative")
end
if sup == "+" then
if not comps[1] then
error("Superlative of '+' can't be specified when there are no comparatives")
end
for _, compobj in ipairs(comps) do
local comp = compobj.origterm
local special
if comp == "+more" then
sup = "+most"
elseif comp == "+further" then
sup = "+furthest"
elseif comp == "+better" then
sup = "+best"
elseif comp == "er" then
sup = "est"
elseif comp == "ier" then
sup = "iest"
else
if comp:find("^%+") then
special = m_headword_utilities.get_special_indicator(comp, "noerror")
end
if not special then
-- If the full comparative was given, then derive the superlative by replacing -er with
-- -est.
if comp:sub(-2) == "er" then
sup = comp:sub(1, -3) .. "est"
else
error(("The superlative cannot be derived automatically from comparative '%s' because it doesn't end in -er"):format(comp))
end
end
end
process_sup(sup, special, supobj, compobj)
end
else
local special = m_headword_utilities.get_special_indicator(sup, "noerror")
-- Do some work here rather than in process_sup() so we don't end up double-processing a term with a '~'
-- in it or a term that happens to be 'most' or similar after substitution of ~ in the comparative.
if not special then
if sup == "most" and pagename ~= "many" and pagename ~= "much" then
sup = "+most"
elseif sup == "furthest" and pagename ~= "far" then
sup = "+furthest"
elseif sup == "best" and pagename ~= "good" and pagename ~= "well" then
sup = "+best"
elseif sup:find("~") then
sup = sup:gsub("~", replacement_escape(pagename))
end
end
process_sup(sup, special, supobj)
end
end
end
insert_inflection(data, outcomps, "<<comparative>>", "comparative")
insert_inflection(data, outsups, "<<superlative>>", "superlative")
end
pos_functions["adjectives"] = {
params = {
[1] = list_param,
["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the comparative value",
},
["sup"] = list_param,
["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the superlative value",
},
["componly"] = boolean_param,
["suponly"] = boolean_param,
},
func = function(args, data)
-- Process the comparatives and superlatives.
process_comparative_args(data, args, "adjectives")
end,
}
pos_functions["adverbs"] = {
params = {
[1] = list_param,
["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the comparative value",
},
["sup"] = list_param,
["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the superlative value",
},
["componly"] = boolean_param,
["suponly"] = boolean_param,
},
func = function(args, data)
-- Process the comparatives and superlatives.
process_comparative_args(data, args, "adverbs")
end,
}
local function escape(str)
return (str:gsub("\\([:#])", "\\\\%1")
:gsub("[:#]", "\\%0"))
end
local function canonicalize_plural(pl, pagename, pos)
if pl == "+" then
return escape(add_suffix(pagename, "s.plural", pos))
elseif pl == "++" then
return escape(compute_plusplus_s_form(pagename, add_suffix(pagename, "s.plural", pos)))
elseif pl == "*" then
return escape(pagename)
elseif pl == "ies" then
if pagename:sub(-1) == "y" then
return escape(pagename:gsub("e?y$", pl))
end
error("Can't specify 'ies' plural unless the term ends wiþ 'y'.")
elseif pl == "s" or pl == "es" or pl == "'s" then
return escape(pagename .. pl)
end
end
local function do_nouns(args, data, pos)
local pagename = data.pagename
pos = pos or "noun"
local plurals = parse_inflection(args, 1)
local function insert_plurale_tantum_inflections(is_plural_only, originating_label)
if args.sg[1] then
insert_fixed_inflection(data, "normally plural", originating_label)
parse_and_insert_inflection(data, args, "sg", "singular")
elseif is_plural_only then
insert_fixed_inflection(data, "plural only", originating_label)
end
if args.attr[1] then
parse_and_insert_inflection(data, args, "attr", "attributive")
end
end
local function first_pl_term()
return plurals[1] and plurals[1].term or nil
end
if first_pl_term() == "p" then
-- plurale tantum
if plurals[2] then
error("Wiþ plurale tantum nama, can't specify more than one plural")
end
data.genders = {"p"} -- this should auto-insert the correct 'pluralia tantum' category
insert_plurale_tantum_inflections("plural only", plurals[1])
return
end
local function inscat(cat)
insert(data.categories, langname .. " " .. cat)
end
local need_default_plural = pos == "noun"
if first_pl_term() == "sp" then
-- construed as singular or plural
sp = remove(plurals, 1) -- Remove the "sp" but retain it for its decorations.
inscat("naman construed as singular or plural")
data.genders = {"s", "p"} -- this should auto-insert the correct 'pluralia tantum' category
insert_plurale_tantum_inflections(nil, sp)
need_default_plural = false
elseif first_pl_term() == "-" then
-- Untellendlīc noun; may occasionally have a plural
local hyphpl = remove(plurals, 1) -- Remove the "-" but retain for decorations.
inscat("untellendlīc naman")
-- If plural forms were given explicitly, then show "oft"
if plurals[1] then
insert_fixed_inflection(data, "oft <<untellendlīc>>", hyphpl)
else
insert_fixed_inflection(data, "<<untellendlīc>>", hyphpl)
end
need_default_plural = false
elseif first_pl_term() == "#" then
-- oft tellendlīc (e.g., "grilled cheese")
local hashpl = remove(plurals, 1) -- Remove the "#" but retain for decorations.
insert_fixed_inflection(data, "oft <<tellendlīc>>", hashpl)
inscat("untellendlīc naman")
inscat("tellendlīc naman")
-- If no plural was given, add a default one now
if not plurals[1] then
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
elseif first_pl_term() == "~" then
-- Mixed tellendlīc/untellendlīc noun, always has a plural
local tildepl = remove(plurals, 1) -- Remove the "~" but retain for decorations.
insert_fixed_inflection(data, "<<tellendlīc>> and <<untellendlīc>>", tildepl)
inscat("untellendlīc naman")
inscat("tellendlīc naman")
-- If no plural was given, add a default one now
if not plurals[1] then
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
end
-- Plural is unknown
if first_pl_term() == "?" then
local questionpl = remove(plurals, 1) -- Remove the "?" but retain for decorations.
-- Not desired; see [[Wiktionary:Tea_room/2021/August#"Plural unknown or uncertain"]]
-- insert_fixed_inflection(data, "manigfeald unġecnāwen oþþe ungewiss", questionpl)
inscat("naman wiþ unġecnāwen oþþe ungewiss manigfealde")
if plurals[1] then
error("Ne cann āmearcian sweotole manigfealde andlang wiþ '?' of unġecnāwen/ungewiss manigfeald")
end
return
end
-- Plural is not attested
if first_pl_term() == "!" then
local exclampl = remove(plurals, 1) -- Remove the "!" but retain for decorations.
insert_fixed_inflection(data, "plural not attested", exclampl)
inscat("naman wiþ unattested manigfealde")
if plurals[1] then
error("Ne cann āmearcian sweotole manigfealde andlang wiþ '!' of gecȳþed manigfeald")
end
return
end
-- If no plural was given, maybe add a default one, otherwise (when "-" was given or proper noun) return.
if not plurals[1] then
if not need_default_plural then
inscat("untellendlīc naman")
return
end
plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))}
end
-- There are plural forms to show, so show them.
inscat("tellendlīc naman")
local irregular, indeclinable
for i, pl in ipairs(plurals) do
local canon_pl = canonicalize_plural(pl.term, pagename, pos)
if canon_pl then
pl.term = canon_pl
end
local pl_term = get_link_page(pl.term, lang)
if not (pagename:find(" ") or is_regular_plural(pl_term, pagename)) then
irregular = true
if pl_term == pagename then
indeclinable = true
end
end
end
if irregular then
inscat("naman wiþ fremde manigfealde")
end
if indeclinable then
inscat("undeclīnigendlīce naman")
end
insert_inflection(data, plurals, "plural", "p")
end
-- Return the parameters to be used for nouns and proper nouns. Currently the same.
local noun_params = {
[1] = list_param,
["pl\1qual"] = {list = true, allow_holes = true, replaced_by = false,
instead = "use <l:...> or <q:...> inline modifier on the plural",
},
-- The following four only used for pluralia tantum (1=p)
["sg"] = list_param,
["attr"] = list_param,
}
pos_functions["naman"] = {
params = noun_params,
func = do_naman,
}
pos_functions["agennaman"] = {
params = noun_params,
func = function(args, data)
return do_nouns(args, data, "agennama")
end,
}
local function base_default_verb_forms(verb)
return escape(add_suffix(verb, "s.verb")), escape(add_suffix(verb, "ing")), escape(add_suffix(verb, "d"))
end
local function default_verb_forms(verb)
local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb)
if verb:find(" ") then
local first, rest = verb:match("^(.-)( .*)$")
local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first)
return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest,
first_ed_form .. rest, first, rest
else
return full_s_form, full_ing_form, full_ed_form, nil, nil, nil, nil, nil
end
end
local function compute_double_last_cons_stem_of_split_verb(verb, ending)
local first, rest = verb:match("^(.-)( .*)$")
if not first then
error("Word '" .. verb .. "' mōt hæfþ rum in sīde tō notienne **")
end
local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$")
if not last_cons then
error("Fyrest word '" .. first .. "' mōt ende wiþ samod swēgend tō notienne **")
end
return first .. last_cons .. ending .. rest
end
local function check_non_nil_star_form(form, pagename)
if form == nil then
error("Word '" .. pagename .. "' mōt hæfþ rum in sīde tō notienne *, **, *l, *! or *'")
end
return form
end
local function sub_tilde(form, pagename)
if not form then
return nil
end
if form:find("~") then
form = form:gsub("~", replacement_escape(pagename))
end
return form
end
local deprecated_qual_replaced_by_inline_modifier = {
list = true, allow_holes = true, replaced_by = false,
instead = "use an inline modifier <q:...> or <l:...> on the value"
}
pos_functions["verbs"] = {
params = {
[1] = {list = "pres_3sg", disallow_holes = true},
["pres_3sg\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[2] = {list = "pres_ptc", disallow_holes = true},
["pres_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[3] = {list = "past", disallow_holes = true},
["past\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
[4] = {list = "past_ptc", allow_holes = true},
["past_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier,
["noautolinkverb"] = boolean_param,
["angle_bracket"] = boolean_param,
},
func = function(args, data)
-- Get parameters
local par1s
local par2s = parse_inflection(args, {2, "pres_ptc"})
local par3s = parse_inflection(args, {3, "past"})
local par4s = parse_inflection(args, {4, "past_ptc"})
local pres_3sgs, pres_ptcs, pasts, past_ptcs
local pagename = data.pagename
------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------
-- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=.
local full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed
local lemma
local function set_lemma_and_default_forms(the_lemma)
lemma = the_lemma
full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed,
lemma_first, lemma_rest = default_verb_forms(the_lemma)
end
local function canonicalize_s_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_s
elseif form == "*" then
return check_non_nil_star_form(split_default_s, lemma)
elseif form == "++" then
return compute_plusplus_s_form(lemma, full_default_s)
elseif form == "**" then
if lemma:find("^[^ ]*[szx] ") then
return compute_double_last_cons_stem_of_split_verb(lemma, "es")
else
return check_non_nil_star_form(split_default_s, lemma)
end
elseif form == "+!" then
return lemma .. "s"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "s" .. lemma_rest
elseif form == "+'" then
return lemma .. "'s"
elseif form == "*'" then
return check_non_nil_star_form(lemma_first) .. "'s" .. lemma_rest
elseif form == "+l" then
if lemma:find("[szx]$") then
return {{term = full_default_s, l = {"US"}},
{term = compute_plusplus_s_form(lemma, full_default_s), l = {"UK"}}}
else
return compute_plusplus_s_form(lemma, full_default_s)
end
elseif form == "*l" then
if lemma:find("^[^ ]*[szx] ") then
return {{term = check_non_nil_star_form(split_default_s, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "es"), l = {"UK"}}}
else
return check_non_nil_star_form(split_default_s, lemma)
end
else
return sub_tilde(form, lemma)
end
end
local function canonicalize_ing_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_ing
elseif form == "*" then
return check_non_nil_star_form(split_default_ing, lemma)
elseif form == "++" then
return compute_double_last_cons_stem(lemma) .. "ing"
elseif form == "**" then
return compute_double_last_cons_stem_of_split_verb(lemma, "ing")
elseif form == "+!" then
return lemma .. "ing"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "ing" .. lemma_rest
elseif form == "+'" then
return lemma .. "'ing"
elseif form == "*'" then
return check_non_nil_star_form(lemma_first) .. "'ing" .. lemma_rest
elseif form == "+l" then
return {{term = full_default_ing, l = {"US"}},
{term = compute_double_last_cons_stem(lemma) .. "ing", l = {"UK"}}}
elseif form == "*l" then
return {{term = check_non_nil_star_form(split_default_ing, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "ing"), l = {"UK"}}}
else
return sub_tilde(form, lemma)
end
end
local function canonicalize_ed_form(form)
if form == "+" then
error("Internal error: Should not see '+' here")
elseif form == "^" then
return full_default_ed
elseif form == "*" then
return check_non_nil_star_form(split_default_ed, lemma)
elseif form == "++" then
return compute_double_last_cons_stem(lemma) .. "ed"
elseif form == "+!" then
return lemma .. "ed"
elseif form == "*!" then
return check_non_nil_star_form(lemma_first) .. "ed" .. lemma_rest
elseif form == "+'" then
return {{term = lemma .. "'d"}, {term = lemma .. "'ed"}}
elseif form == "*'" then
return {{term = check_non_nil_star_form(lemma_first) .. "'d" .. lemma_rest},
{term = check_non_nil_star_form(lemma_first) .. "'ed" .. lemma_rest}}
elseif form == "**" then
return compute_double_last_cons_stem_of_split_verb(lemma, "ed")
elseif form == "+l" then
return {{term = full_default_ed, l = {"US"}},
{term = compute_double_last_cons_stem(lemma) .. "ed", l = {"UK"}}}
elseif form == "*l" then
return {{term = check_non_nil_star_form(split_default_ed, lemma), l = {"US"}},
{term = compute_double_last_cons_stem_of_split_verb(lemma, "ed"), l = {"UK"}}}
else
return sub_tilde(form, lemma)
end
end
-- FIXME: options should be "+", "*", "++", "**", "+n", "*n", "++n" and "**n", but not "n"
local function canonicalize_en_form(form)
if form == "n" then
track("n4")
return add_suffix(lemma, "n")
end
return canonicalize_ed_form(form)
end
--------------------------------- MAIN PARSING/CONJUGATING CODE --------------------------------
local is_angle_bracket = args.angle_bracket
if is_angle_bracket then
if par2s[1] or par3s[1] or par4s[1] then
error("Can't specify explicit values for 2=, 3= or 4= along wiþ the angle-bracket format")
end
elseif is_angle_bracket == nil and not par2s[1] and not par3s[1] and not par4s[1] and not args[1][2] and
args[1][1] and args[1][1]:find("<") then
if put.term_contains_top_level_html(args[1][1]) then
-- Often, term_contains_top_level_html() returns true on the angle-bracket format, which would
-- make the pcall() below succeed but leave the angle brackets as-is. Check for this and only do the
-- pcall() if term_contains_top_level_html() returns false.
is_angle_bracket = true
else
-- If it's ambiguous whether it's an angle-bracket format or separate params with an inline modifier,
-- try to parse as the latter. If an error occurs, treat as the former.
local ok
ok, par1s = pcall(parse_inflection, args, {1, "pres_3sg"})
if not ok then
par1s = nil
is_angle_bracket = true
end
end
end
if is_angle_bracket then
-------------------------- ANGLE-BRACKET FORMAT --------------------------
-- (0) Expand multiword term with angle brackets just on the first word.
local arg11 = args[1][1]
if arg11:find("^<.*>$") and pagename:find(" ") then
local first, rest = pagename:match("^(.-)( .*)$")
arg11 = first .. arg11 .. rest
end
-- (1) Parse the indicator specs inside of angle brackets.
local function parse_indicator_spec(angle_bracket_spec)
local inside = angle_bracket_spec:match("^<(.*)>$")
assert(inside)
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local comma_separated_groups = put.split_alternating_runs(segments, ",")
if #comma_separated_groups > 4 then
error("Too many comma-separated parts in indicator spec, expected at most 4: " ..
angle_bracket_spec)
end
local function fetch_footnotes(separated_group)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
error("Extraneous text after bracketed footnotes: '" .. concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
insert(footnotes, separated_group[j])
end
return footnotes
end
local function fetch_specs(comma_separated_group)
if not comma_separated_group then
return {{term = "+"}}
end
local specs = {}
local colon_separated_groups = put.split_alternating_runs(comma_separated_group, ":")
for _, colon_separated_group in ipairs(colon_separated_groups) do
local form = colon_separated_group[1]
if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
error("*, **, *l, *! and *' not allowed inside of indicator specs: " .. angle_bracket_spec)
end
if form == "" then
form = "+"
end
local termobj = {
term = form
}
local footnotes = fetch_footnotes(colon_separated_group)
if footnotes then
for _, footnote in ipairs(footnotes) do
m_headword_utilities.add_footnote_to_termobj(termobj, footnote)
end
end
insert(specs, termobj)
end
return specs
end
local s_specs = fetch_specs(comma_separated_groups[1])
local ing_specs = fetch_specs(comma_separated_groups[2])
local ed_specs = fetch_specs(comma_separated_groups[3])
local en_specs = fetch_specs(comma_separated_groups[4])
return {
forms = {},
s_specs = s_specs,
ing_specs = ing_specs,
ed_specs = ed_specs,
en_specs = en_specs,
}
end
local parse_props = {
parse_indicator_spec = parse_indicator_spec,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg11, parse_props)
-- (2) Check for user-specified brackets; remove any links from the lemma, but remember the original
-- form so we can use it below in the 'lemma_linked' form.
-- Check to see if there are brackets in the pre-text or post-text. If so, use the linked lemma (with the
-- verb autolinked unless noautolinkverb is given). Otherwise, use the default headword algorithm.
local function check_bracket(val)
if val:find("%[%[") then
alternant_multiword_spec.saw_bracket = true
end
end
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
check_bracket(alternant_or_word_spec.before_text)
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for _, word_spec in ipairs(multiword_spec.word_specs) do
check_bracket(word_spec.before_text)
end
check_bracket(multiword_spec.post_text)
end
end
end
check_bracket(alternant_multiword_spec.post_text)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.lemma == "" then
base.lemma = pagename
end
base.orig_lemma = base.lemma
base.lemma = remove_links(base.lemma)
if args.noautolinkverb or base.orig_lemma:find("%[%[") then
base.linked_lemma = base.orig_lemma
else
base.linked_lemma = "[[" .. base.orig_lemma .. "]]"
end
end)
-- (3) Conjugate the verbs according to the indicator specs parsed above.
local all_verb_slots = {
lemma = "infinitive",
lemma_linked = "infinitive",
s_form = "3|s|pres",
ing_form = "pres|ptcp",
ed_form = "past",
en_form = "past|ptcp",
}
local function conjugate_verb(base)
local function process_specs(slot, specs, canon_func, default_values, default_already_formobj)
local function insert_termobj_into_slot(termobj)
local formobj = m_headword_utilities.convert_termobj_to_formobj(termobj)
-- If the form is -, don't insert any forms, which will result in there being no overall forms
-- (in fact it will be nil). We check for that down below and substitute a single "-" as the
-- form, which in turn gets turned into special labels like "no present participle".
if formobj.form == "-" then
if formobj.footnotes then
error("Unable to preserve footnotes specified on missing form '-': FIXME: " ..
dump(formobj.footnotes))
end
else
iut.insert_form(base.forms, slot, formobj)
end
end
local function canonicalize_and_insert(arg)
local canon_arg = canon_func(arg)
if type(canon_arg) == "string" then
arg.term = canon_arg
insert_termobj_into_slot(arg)
else
for _, canon in ipairs(canon_arg) do
m_headword_utilities.combine_termobj_decorations(canon, arg)
insert_termobj_into_slot(canon)
end
end
end
for _, arg in ipairs(specs) do
if arg.term == "+" then
if default_values then -- will be nil if past tense specified as - and no past ptc given
for _, val in ipairs(default_values) do
val = shallowCopy(val)
if default_already_formobj then
local argformobj = m_headword_utilities.convert_termobj_to_formobj(arg)
val.footnotes = iut.combine_footnotes(val.footnotes, argformobj.footnotes)
iut.insert_form(base.forms, slot, val)
else
m_headword_utilities.combine_termobj_decorations(val, arg)
canonicalize_and_insert(val)
end
end
end
else
canonicalize_and_insert(arg)
end
end
end
set_lemma_and_default_forms(base.lemma)
local all_part_default_specs = {}
local function process_and_canonicalize_s_form(arg)
local form = arg.term
if form == "+" then
error("Internal error: '+' should have been converted to '^' by now")
end
if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
error(("Internal error: '%s' should have already thrown an error"):format(form))
end
if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" then
insert(all_part_default_specs, shallowCopy(arg))
end
return canonicalize_s_form(form)
end
process_specs("s_form", base.s_specs, process_and_canonicalize_s_form, {{term = "^"}})
if not all_part_default_specs[1] then
all_part_default_specs[1] = {term = "^"}
end
process_specs("ing_form", base.ing_specs, function(arg) return canonicalize_ing_form(arg.term) end,
all_part_default_specs)
process_specs("ed_form", base.ed_specs, function(arg) return canonicalize_ed_form(arg.term) end,
all_part_default_specs)
process_specs("en_form", base.en_specs, function(arg) return canonicalize_en_form(arg.term) end,
base.forms.ed_form, "default already formobj")
iut.insert_form(base.forms, "lemma", {form = base.lemma})
-- Add linked version of lemma for use in head=. We write this in a general fashion in case
-- there are multiple lemma forms (which isn't possible currently at this level, although it's
-- possible overall using the ((...,...)) notation).
iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form)
if form == base.lemma and base.linked_lemma:find("%[%[") then
return base.linked_lemma
else
return form
end
end))
end
local inflect_props = {
slot_table = all_verb_slots,
inflect_word_spec = conjugate_verb,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
-- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given.
local function fetch_termobjs(slot)
local forms = alternant_multiword_spec.forms[slot]
-- See above. This should only occur if the user explicitly used - for a spec.
if not forms or not forms[1] then
return {{term = "-"}}
end
local termobjs = {}
for _, formobj in ipairs(forms) do
insert(termobjs, m_headword_utilities.convert_formobj_to_termobj(formobj))
end
return termobjs
end
pres_3sgs = fetch_termobjs("s_form")
pres_ptcs = fetch_termobjs("ing_form")
pasts = fetch_termobjs("ed_form")
past_ptcs = fetch_termobjs("en_form")
-- Use the "linked" form of the lemma as the head if no head= explicitly given and the user specified
-- brackets in one of the lemmas. Otherwise we use the default headword-linking algorithm.
if not data.user_specified_heads[1] and alternant_multiword_spec.saw_bracket then
data.heads = {}
for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do
insert(data.heads, m_headword_utilities.convert_formobj_to_termobj(lemma_obj))
end
end
else
-------------------------- SEPARATE-PARAM FORMAT --------------------------
set_lemma_and_default_forms(pagename)
par1s = par1s or parse_inflection(args, {1, "pres_3sg"})
pres_3sgs = {}
pres_ptcs = {}
pasts = {}
past_ptcs = {}
if not par1s[1] then
par1s = {{term = "+"}}
end
if not par2s[1] then
par2s = {{term = "+"}}
end
if not par3s[1] then
par3s = {{term = "+"}}
end
if not par4s[1] then
par4s = {{term = "+"}}
end
local function process_argument(args, dest, canon_func, default_values, default_already_canonicalized)
local function canonicalize_and_insert(arg)
local canon_arg = canon_func(arg)
if type(canon_arg) == "string" then
arg.term = canon_arg
m_headword_utilities.insert_termobj_combining_duplicates(dest, arg)
else
for _, canon in ipairs(canon_arg) do
m_headword_utilities.combine_termobj_decorations(canon, arg)
m_headword_utilities.insert_termobj_combining_duplicates(dest, canon)
end
end
end
for _, arg in ipairs(args) do
if arg.term == "+" then
for _, val in ipairs(default_values) do
val = shallowCopy(val)
m_headword_utilities.combine_termobj_decorations(val, arg)
if default_already_canonicalized then
m_headword_utilities.insert_termobj_combining_duplicates(dest, val)
else
canonicalize_and_insert(val)
end
end
else
canonicalize_and_insert(arg)
end
end
end
local all_part_default_specs = {}
local function process_and_canonicalize_s_form(arg)
local form = arg.term
if form == "+" then
error("Internal error: '+' should have been converted to '^' by now")
end
if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" or
form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then
insert(all_part_default_specs, shallowCopy(arg))
end
return canonicalize_s_form(form)
end
process_argument(par1s, pres_3sgs, process_and_canonicalize_s_form, {{term = "^"}})
if not all_part_default_specs[1] then
all_part_default_specs[1] = {term = "^"}
end
process_argument(par2s, pres_ptcs, function(arg) return canonicalize_ing_form(arg.term) end,
all_part_default_specs)
process_argument(par3s, pasts, function(arg) return canonicalize_ed_form(arg.term) end,
all_part_default_specs)
process_argument(par4s, past_ptcs, function(arg) return canonicalize_en_form(arg.term) end,
pasts, "default already canonicalized")
end
------------------------------------------- INSERT INFLECTIONS ------------------------------------------
insert_inflection(data, pres_3sgs, "third-person singular simple present", "s-verb-form")
insert_inflection(data, pres_ptcs, "present participle", "ing-form")
if deepEquals(pasts, past_ptcs) then
insert_inflection(data, pasts, "simple past and past participle", "ed-form",
"no simple past or past participle")
else
insert_inflection(data, pasts, "simple past", "spast")
insert_inflection(data, past_ptcs, "past participle", "past|part")
end
if pagename:find(" ") then
-- Check for placeholder "it"
local words = split(pagename, " ")
for _, word in ipairs(words) do
if word == "it" or word == "its" or word == "it's" then
insert(data.categories, langname .. ' terms wiþ placeholder "it"')
break
end
end
-- Check for phrasal verbs
local phrasal_adverbs = list_to_set{
-- NOTE: This should only contain common phrasal adverbs, not random words like [[low]],
-- [[adrift]], etc.
"aback",
"about",
"above",
"across",
"after",
"against",
"ahead",
"along",
"apart",
"around",
"as",
"aside",
"at",
"away",
"back",
"before",
"behind",
"below",
"between",
"beyond",
"by",
"down",
"for",
"forth",
"from",
"in",
"into",
"of",
"off",
"on",
"onto",
"out",
"over",
"past",
"round",
"through",
"to",
"together",
"towards",
"under",
"up",
"upon",
"with",
"without",
}
local allowed_non_adverb_words = list_to_set{
"it",
"one",
"oneself",
"someone",
}
local base = pagename
local seen_adverbs = {}
-- Only consider a verb to be phrasal if it consists of a single base verb followed exclusively by either
-- adverbs from `phrasal_adverbs` or placeholder words from `allowed_non_adverb_words`, where at
-- least one following word is from `phrasal_adverbs` (hence [[can it]] is not a phrasal verb).
while true do
local prev, word = base:match("^(.+) (.-)$")
if not prev then
break
end
if phrasal_adverbs[word] then
insert(seen_adverbs, word)
elseif allowed_non_adverb_words[word] then
-- do nothing
else
break
end
base = prev
end
if not base:find(" ") and seen_adverbs[1] then
insert(data.categories, langname .. " phrasal verbs")
for i = #seen_adverbs, 1, -1 do
insert(data.categories, langname .. ' phrasal verbs formed wiþ "' .. seen_adverbs[i] ..
'"')
end
end
end
end,
}
-----------------------------------------------------------------------------------------
-- Suffix forms --
-----------------------------------------------------------------------------------------
pos_functions["suffix forms"] = {
params = {
[1] = {required = true, list = true, disallow_holes = true},
},
func = function(args, data, is_suffix)
local suffix_type = {}
for _, typ in ipairs(args[1]) do
insert(suffix_type, typ .. "-forming suffix")
end
insert(data.inflections, {label = "non-lemma form of " .. m_table.serialCommaJoin(suffix_type, {conj = "or"})})
end,
}
return export
7yz04om8j9bmmi4vvftkrnwf9u8nbds
Module:etymology
828
8064
54937
54922
2026-09-30T02:25:24Z
Deadend0914
7211
54937
Scribunto
text/plain
local export = {}
-- For testing
local force_cat = false
local debug_track_module = "Module:debug/track"
local languages_module = "Module:languages"
local links_module = "Module:links"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local concat = table.concat
local insert = table.insert
local new_title = mw.title.new
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function full_link(...)
full_link = require(links_module).full_link
return full_link(...)
end
local function get_language_data_module_name(...)
get_language_data_module_name = require(languages_module).getDataModuleName
return get_language_data_module_name(...)
end
local function get_link_page(...)
get_link_page = require(links_module).get_link_page
return get_link_page(...)
end
local function language_link(...)
language_link = require(links_module).language_link
return language_link(...)
end
local function serial_comma_join(...)
serial_comma_join = require(table_module).serialCommaJoin
return serial_comma_join(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
-- Old English localization: language names come from [[Module:sprǣcnaman]], which is also what
-- [[Bysen:sprǣc]] (the ==L2== heading template) uses, so headings, wordstǣr lines and categories
-- can never disagree with each other. The module is optional: if it is missing, the English names
-- are used exactly as before.
local ang_names_module = "Module:sprǣcnaman"
local ang_names
local function get_ang_names()
if ang_names == nil then
local ok, mod = pcall(require, ang_names_module)
ang_names = ok and mod or false
end
return ang_names or nil
end
-- Old English name of the language, or nil.
local function ang_name(lang)
local mod = get_ang_names()
return mod and mod.get_name(lang) or nil
end
-- Old English "of"-form of the language, or nil.
local function ang_of(lang)
local mod = get_ang_names()
return mod and mod.get_of(lang) or nil
end
-- Replace the visible text of a language link, e.g. "[[w:Old English|Old English]]" -> "Englisce",
-- keeping the link target.
local function replace_display(display, text)
local target = display:match("^%[%[(.-)|.-%]%]$")
if target then
return "[[" .. target .. "|" .. text .. "]]"
end
return text
end
-- Localized display text and category name for a source language. Returns nil when the language has
-- no Old English name, in which case the original English name is used.
-- Old English localization: category wordings come from [[Module:floccnaman]] (see that module);
-- the English wording is kept when a translation is missing. Loaded lazily and optionally, so a
-- missing module can never break a page.
local floccnaman_module = "Module:floccnaman"
local floccnaman
local function get_floccnaman()
if floccnaman == nil then
local ok, mod = pcall(require, floccnaman_module)
floccnaman = ok and mod or false
end
return floccnaman or nil
end
-- Old English wording for one category word, or the English wording unchanged.
local function cat_word(lang, text)
local mod = get_floccnaman()
return mod and mod.get(lang, text) or text
end
local function ang_display_and_cat_name(source, raw)
local name = ang_name(source)
if not name then
return nil
end
local display
if raw then
display = name
else
display = replace_display(source:makeWikipediaLink(), ang_of(source) or name)
end
return display, name
end
local function track(page, code)
local tracking_page = "etymology/" .. page
debug_track(tracking_page)
if code then
debug_track(tracking_page .. "/" .. code)
end
end
local function join_segs(segs, conj)
if not segs[2] then
return segs[1]
elseif conj == "and" or conj == "or" then
return serial_comma_join(segs, {conj = conj})
end
local sep
if conj == "," or conj == ";" then
sep = conj .. " "
elseif conj == "/" then
sep = "/"
elseif conj == "~" then
sep = " ~ "
elseif conj then
error(("Internal error: Unrecognized conjunction \"%s\""):format(conj))
else
error(("Internal error: No value supplied for conjunction"):format(conj))
end
return concat(segs, sep)
end
-- Returns true if `lang` is the same as `source`, or a variety of it.
local function lang_is_source(lang, source)
return lang:getCode() == source:getCode() or lang:hasParent(source)
end
--[==[
Format one or more links as specified in `termobjs`, a list of term objects of the format accepted by `full_link()` in
[[Module:links]], including decorations (qualifiers, labels and references). `conj` is used to join multiple terms
and must be specified if there is more than one term. `template_name` is the template name used in debug tracking and
must be specified. Optional `sourcetext` is text to prepend to the concatenated terms, separated by a space if the
concatenated terms are non-empty (which is always the case unless there is a single term with the value "-"). If
`decorations_on_outside` is given, any decorations specified in the first term go on the outside of (i.e before)
`sourcetext`; otherwise they will end up on the inside.
]==]
function export.format_links(termobjs, conj, template_name, sourcetext, decorations_on_outside)
if not template_name then
error("Internal error: Must specify `template_name` to format_links()")
end
for i, termobj in ipairs(termobjs) do
if termobj.lang:hasType("family") or termobj.lang:getFamilyCode() == "qfa-sub" then
if termobj.term and termobj.term ~= "-" then
debug_track(template_name .. "/family-with-term")
end
termobj.term = "-"
end
if termobj.term == "-" then
--[=[
[[Special:WhatLinksHere/Wiktionary:Tracking/cognate/no-term]]
[[Special:WhatLinksHere/Wiktionary:Tracking/derived/no-term]]
[[Special:WhatLinksHere/Wiktionary:Tracking/borrowed/no-term]]
[[Special:WhatLinksHere/Wiktionary:Tracking/calque/no-term]]
]=]
debug_track(template_name .. "/no-term")
termobjs[i] = i == 1 and sourcetext or ""
else
if i == 1 and decorations_on_outside and sourcetext then
termobj.pretext = sourcetext .. " "
sourcetext = nil
end
termobjs[i] = (i == 1 and sourcetext and sourcetext .. " " or "") .. full_link(termobj, "term")
end
end
return join_segs(termobjs, conj)
end
function export.get_display_and_cat_name(source, raw)
local display, cat_name
if source:getCode() == "und" then
display = "undetermined"
cat_name = cat_word(source, "other languages")
elseif source:getCode() == "mul" then
display = raw and "translingual" or "[[w:Translingualism|translingual]]"
cat_name = cat_word(source, "Translingual")
elseif source:getCode() == "mul-tax" then
display = raw and "taxonomic name" or "[[w:Biological nomenclature|taxonomic name]]"
cat_name = cat_word(source, "taxonomic names")
else
-- Old English localization: use the "of"-form of the name, e.g. "Of Englisce and".
local ang_display, ang_cat_name = ang_display_and_cat_name(source, raw)
display = ang_display or raw and source:getCanonicalName() or source:makeWikipediaLink()
cat_name = ang_cat_name or source:getDisplayForm()
end
return display, cat_name
end
function export.insert_source_cat_get_display(data)
local categories, lang, source = data.categories, data.lang, data.source
local display, cat_name = export.get_display_and_cat_name(source, data.raw)
if lang and not data.nocat then
-- Add the category, but only if there is a current language
if not categories then
categories = {}
end
local langname = ang_name(lang) or lang:getFullName()
-- If `lang` is an etym-only language, we need to check both it and its parent full language against `source`.
-- Otherwise if e.g. `lang` is Medieval Latin and `source` is Latin, we'll end up wrongly constructing a
-- category 'Latin terms derived from Latin'.
-- Old English localization: the whole phrase is looked up at once (e.g. "terms derived from",
-- "learned borrowings from"), so that [[Module:floccnaman]] can word the complete phrase and the word
-- order does not have to follow English. When it is not translated the English wording is kept.
local borrowing_phrase
if lang_is_source(lang, source) then
borrowing_phrase = "terms borrowed back into"
else
borrowing_phrase = (data.borrowing_type or "terms derived") .. " from"
end
insert(categories, langname .. " " .. cat_word(lang, borrowing_phrase) .. " " .. cat_name)
end
return display, categories
end
function export.format_source(data)
local lang, sort_key = data.lang, data.sort_key
-- [[Special:WhatLinksHere/Wiktionary:Tracking/etymology/sortkey]]
if sort_key then
track("sortkey")
end
local display, categories = export.insert_source_cat_get_display(data)
if lang and not data.nocat then
-- Format categories, but only if there is a current language; {{cog}} currently gets no categories
categories = format_categories(categories, lang, sort_key, nil, data.force_cat or force_cat)
else
categories = ""
end
return "<span class=\"etyl\">" .. display .. categories .. "</span>"
end
--[==[
Format sources for etymology templates such as {{tl|bor}}, {{tl|der}}, {{tl|inh}} and {{tl|cog}}. There may potentially
be more than one source language (except currently {{tl|inh}}, which doesn't support it because it doesn't really
make sense). In that case, all but the last source language is linked to the first term, but only if there is such a
term and this linking makes sense, i.e. either (1) the term page exists after stripping diacritics according to the
source language in question, or (2) the result of stripping diacritics according to the source language in question
results in a different page from the same process applied with the last source language. For example, {{m|ru|соля́нка}}
will link to [[солянка]] but {{m|en|соля́нка}} will link to [[соля́нка]] with an accent, and since they are different
pages, the use of English as a non-final source with term 'соля́нка' will link to [[соля́нка]] even though it doesn't
exist, on the assumption that it is merely a redlink that might exist. If none of the above criteria apply, a non-final
source language will be linked to the Wikipedia entry for the language, just as final source languages always are.
`data` contains the following fields:
* `lang`: The destination language object into which the terms were borrowed, inherited or otherwise derived. Used for
categorization and can be nil, as with {{tl|cog}}.
* `sources`: List of source objects. Most commonly there is only one. If there are multiple, the non-final ones are
handled specially; see above.
* `terms`: List of term objects. Most commonly there is only one. If there are multiple source objects as well as
multiple term objects, the non-final source objects link to the first term object.
* `sort_key`: Sort key for categories. Usually nil.
* `categories`: Categories to add to the page. Additional categories may be added to `categories` based on the source
languages ('''in which case `categories` is destructively modified'''). If `lang` is nil, no categories will be
added.
* `nocat`: Don't add any categories to the page.
* `sourceconj`: Conjunction used to separate multiple source languages. Defaults to {"and"}. Currently recognized
values are `and`, `or`, `,`, `;`, `/` and `~`.
* `borrowing_type`: Borrowing type used in categories, such as {"learned borrowings"}. Defaults to {"terms derived"}.
* `force_cat`: Force category generation on non-mainspace pages.
]==]
function export.format_sources(data)
local lang, sources, terms, borrowing_type, sort_key, categories, nocat =
data.lang, data.sources, data.terms, data.borrowing_type, data.sort_key, data.categories, data.nocat
local term1, sources_n, source_segs = terms[1], #sources, {}
local final_link_page
local term1_term, term1_sc = term1.term, term1.sc
if sources_n > 1 and term1_term and term1_term ~= "-" then
final_link_page = get_link_page(term1_term, sources[sources_n], term1_sc)
end
for i, source in ipairs(sources) do
local seg, display_term
if i < sources_n and term1_term and term1_term ~= "-" then
local link_page = get_link_page(term1_term, source, term1_sc)
display_term = (link_page ~= final_link_page) or (link_page and not not new_title(link_page):getContent())
end
-- TODO: if the display forms or transliterations are different, display the terms separately.
if display_term then
local display, this_cats = export.insert_source_cat_get_display{
lang = lang,
source = source,
borrowing_type = borrowing_type,
raw = true,
categories = categories,
nocat = nocat,
}
seg = language_link {
lang = source,
term = term1_term,
alt = display,
tr = "-",
}
if lang and not nocat then
-- Format categories, but only if there is a current language; {{cog}} currently gets no categories
this_cats = format_categories(this_cats, lang, sort_key, nil, data.force_cat or force_cat)
else
this_cats = ""
end
seg = "<span class=\"etyl\">" .. seg .. this_cats .. "</span>"
else
seg = export.format_source{
lang = lang,
source = source,
borrowing_type = borrowing_type,
sort_key = sort_key,
categories = categories,
nocat = nocat,
}
end
insert(source_segs, seg)
end
return join_segs(source_segs, data.sourceconj or "and")
end
-- Internal implementation of {{cognate}}/{{cog}} template.
function export.format_cognate(data)
return export.format_derived {
sources = data.sources,
terms = data.terms,
sort_key = data.sort_key,
sourceconj = data.sourceconj,
conj = data.conj,
template_name = "cognate",
force_cat = data.force_cat,
}
end
--[==[
Internal implementation of {{derived}}/{{der}} template. This is called externally from [[Module:affix]],
[[Module:affixusex]] and [[Module:see]] and needs to support decorations (qualifiers, labels and references) on the
outside of the sources for use by those modules.
`data` contains the following fields:
* `lang`: The destination language object into which the terms were derived. Used for categorization and can be nil, as
with {{tl|cog}}; in this case, no categories are added.
* `sources`: List of source objects. Most commonly there is only one. If there are multiple, the non-final ones are
handled specially; see `format_sources()`.
* `terms`: List of term objects. Most commonly there is only one. If there are multiple source objects as well as
multiple term objects, the non-final source objects link to the first term object.
* `conj`: Conjunction used to separate multiple terms. '''Required'''. Currently recognized values are `and`, `or`, `,`,
`;`, `/` and `~`.
* `sourceconj`: Conjunction used to separate multiple source languages. Defaults to {"and"}. Currently recognized
values are as for `conj` above.
* `decorations_on_outside`: If specified, any decorations (qualifiers, labels or references) in the first term in
`terms` will be displayed on the outside of (before) the source language(s) in `sources`. Normally this should be
specified if there is only one term possible in `terms`.
* `template_name`: Name of the template invoking this function. Must be specified. Only used for tracking pages.
* `sort_key`: Sort key for categories. Usually nil.
* `categories`: Categories to add to the page. Additional categories may be added to `categories` based on the source
languages ('''in which case `categories` is destructively modified'''). If `lang` is nil, no categories will be
added.
* `nocat`: Don't add any categories to the page.
* `borrowing_type`: Borrowing type used in categories, such as {"learned borrowings"}. Defaults to {"terms derived"}.
* `force_cat`: Force category generation on non-mainspace pages.
]==]
function export.format_derived(data)
local terms = data.terms
local sourcetext = export.format_sources(data)
return export.format_links(terms, data.conj, data.template_name, sourcetext, data.decorations_on_outside)
end
function export.insert_borrowed_cat(categories, lang, source)
if lang_is_source(lang, source) then
return
end
-- If both are the same, we want e.g. [[:Category:English terms borrowed back into English]] not
-- [[:Category:English terms borrowed from English]]; the former is inserted automatically by format_source().
-- The second parameter here doesn't matter as it only affects `display`, which we don't use.
insert(categories, (ang_name(lang) or lang:getFullName()) .. " " .. cat_word(lang, "terms borrowed from") .. " " .. select(2, export.get_display_and_cat_name(source, "raw")))
end
-- Internal implementation of {{borrowed}}/{{bor}} template.
function export.format_borrowed(data)
local categories = {}
if not data.nocat then
local lang = data.lang
for _, source in ipairs(data.sources) do
export.insert_borrowed_cat(categories, lang, source)
end
end
data = shallow_copy(data)
data.categories = categories
return export.format_links(data.terms, data.conj, "borrowed", export.format_sources(data))
end
do
-- Generate the non-ancestor error message.
local function show_language(lang)
local retval = ("%s (%s)"):format(lang:makeCategoryLink(), lang:getCode())
if lang:hasType("etymology-only") then
retval = retval .. (" (an etymology-only language whose regular parent is %s)"):format(
show_language(lang:getParent()))
end
return retval
end
-- Check that `lang` has `otherlang` (which may be an etymology-only language) as an ancestor. Throw an error if
-- not. When `lang` is a family, verifies that `otherlang` is a language in that family.
function export.check_ancestor(lang, otherlang)
-- When `lang` is a family, verify `otherlang` is in that family or in its parent family.
if lang.hasType and lang:hasType("family") then
local family_code = lang:getCode()
local function in_family_code(fcode, other)
if not fcode or fcode == "" then return false end
if other.inFamily and other:inFamily(fcode) then return true end
if other.getFamilyCode and other:getFamilyCode() == fcode then return true end
return false
end
local in_family = in_family_code(family_code, otherlang)
if not in_family then
local parent_code
if lang.getParent then
local parent_family = lang:getParent()
if parent_family and parent_family.getCode then
parent_code = parent_family:getCode()
end
end
if not parent_code and family_code:find("-", 1, true) then
parent_code = family_code:match("^(.+)-[^-]+$")
end
if parent_code then
in_family = in_family_code(parent_code, otherlang)
end
end
if not in_family then
local other_display = (otherlang.getCanonicalName and otherlang:getCanonicalName()) or (otherlang.getCode and otherlang:getCode()) or tostring(otherlang)
local fam_display = (lang.getCanonicalName and lang:getCanonicalName()) or family_code
error(("%s is not in family %s; inherited ancestor under a family must be a language in that family or its parent family.")
:format(other_display, fam_display))
end
return
end
-- FIXME: I don't know if this function works correctly with etym-only languages in `lang`. I have fixed up
-- the module link code appropriately (June 2024) but the remaining logic is untouched.
if lang:hasAncestor(otherlang) then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/etymology/variety]]
-- Track inheritance from varieties of Latin that shouldn't have any descendants (everything except Old Latin, Classical Latin and Vulgar Latin).
if otherlang:getFullCode() == "la" then
otherlang = otherlang:getCode()
if not (otherlang == "itc-ola" or otherlang == "la-cla" or otherlang == "la-vul") then
track("bad ancestor", otherlang)
end
end
return
end
local ancestors = lang:getAncestors()
local postscript
local etym_module_link = lang:hasType("etymology-only") and "[[Module:etymology languages/data]] or " or ""
local module_link = "[[" .. get_language_data_module_name(lang:getFullCode()) .. "]]"
if not ancestors[1] then
postscript = show_language(lang) .. " has no ancestors."
else
local ancestor_list = {}
for _, ancestor in ipairs(ancestors) do
insert(ancestor_list, show_language(ancestor))
end
postscript = ("The ancestor%s of %s %s %s."):format(
ancestors[2] and "s" or "", lang:getCanonicalName(),
ancestors[2] and "are" or "is", concat(ancestor_list, " and "))
end
error(("%s is not set as an ancestor of %s in %s%s. %s")
:format(show_language(otherlang), show_language(lang), etym_module_link, module_link, postscript))
end
end
-- Internal implementation of {{inherited}}/{{inh}} template.
function export.format_inherited(data)
local lang, terms, nocat = data.lang, data.terms, data.nocat
local source = terms[1].lang
local categories = {}
if not nocat then
insert(categories, (ang_name(lang) or lang:getFullName()) .. " " .. cat_word(lang, "terms inherited from") .. " " .. (ang_name(source) or source:getCanonicalName()))
end
export.check_ancestor(lang, source)
data = shallow_copy(data)
data.categories = categories
data.source = source
return export.format_links(terms, data.conj, "inherited", export.format_source(data))
end
-- Internal implementation of "misc variant" templates such as {{abbrev}}, {{clipping}}, {{reduplication}} and the like.
function export.format_misc_variant(data)
local lang, notext, terms, cats, parts = data.lang, data.notext, data.terms, data.cats, {}
if not notext then
insert(parts, data.text)
end
if terms[1] then
if not notext then
-- FIXME: If term is given as '-', we should consider displaying just "Clipping" not "Clipping of".
insert(parts, " " .. (data.oftext or "of"))
end
local termparts = {}
-- Make links out of all the parts.
for _, termobj in ipairs(terms) do
local result
if termobj.lang then
result = export.format_derived {
lang = lang,
terms = {termobj},
sources = termobj.termlangs or {termobj.lang},
template_name = "misc_variant",
decorations_on_outside = true,
force_cat = data.force_cat,
}
else
termobj.lang = lang
result = export.format_links({termobj}, nil, "misc_variant")
end
table.insert(termparts, result)
end
local linktext = join_segs(termparts, data.conj)
if not notext and linktext ~= "" then
insert(parts, " ")
end
insert(parts, linktext)
end
local categories = {}
if not data.nocat and cats then
for _, cat in ipairs(cats) do
insert(categories, (ang_name(lang) or lang:getFullName()) .. " " .. cat_word(lang, cat))
end
end
if categories[1] then
insert(parts, format_categories(categories, lang, data.sort_key, nil, data.force_cat or force_cat))
end
return concat(parts)
end
-- Implementation of miscellaneous templates such as {{unknown}} and {{onomatopoeia}} that have no associated terms.
function export.format_misc_variant_no_term(data)
local parts = {}
if not data.notext then
insert(parts, data.title)
end
if not data.nocat and data.cat then
local lang, categories = data.lang, {}
insert(categories, (ang_name(lang) or lang:getFullName()) .. " " .. cat_word(lang, data.cat))
insert(parts, format_categories(categories, lang, data.sort_key, nil, data.force_cat or force_cat))
end
return concat(parts)
end
return export
acsw4gr8o71fllncz0s0ybi7f6s2pvf
Module:sprǣcnaman
828
8074
54954
54901
2026-09-30T03:22:50Z
Deadend0914
7211
54954
Scribunto
text/plain
--[=[
Rēgister of sprǣcnaman (language names) for the Old English Wiktionary.
This is the single place where the Old English name of a language is entered. Everything that
displays a language name on this wiki reads it from here:
* [[Bysen:sprǣc]] (the ==L2== heading template) is a thin wrapper around sprǣc() below.
* [[Module:etymology]] and [[Module:etymology/templates]] use get_name() for headings and
category names, and get_of() for the "of"-form, because Old English uses "of" + genitive
when an ancestor or source language is mentioned, e.g. "Of Englisce and".
Names are entered without leading or trailing spaces. get_of() applies the following rules in
order:
1. an explicit entry in `of_names` (for names that follow no rule);
2. `-isc` + "e" (Englisc -> Englisce, Nīwenglisc -> Nīwenglisce, Þēodisc -> Þēodisce);
3. otherwise the nominative name is returned unchanged and the miss is tracked in
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] so that an entry can be supplied.
Codes with no name at all display "?" (as [[Bysen:sprǣc]] always has) and are tracked in
[[Wiktionary:Tracking/sprǣc/unknown code]], see [[Special:WhatLinksHere/Wiktionary:Tracking/sprǣc/unknown code]].
]=]
local export = {}
local names = {
af = "Affricanisc",
ang = "Englisc",
bn = "Bengalisc",
ca = "Catalānisc",
cs = "Bæmisc",
da = "Denisc",
de = "Þēodisc",
el = "Crēacisc",
en = "Nīwenglisc",
eo = "Esperantisc",
es = "Spēonisc",
et = "Eotolisc",
eu = "Wascisc",
fa = "Persisc",
fi = "Finnisc",
fo = "Faerisc",
fr = "Frencisc",
frk = "Frencisc",
frp = "Profencalisc",
ga = "Īrisc",
gl = "Galizisc",
gn = "Awaisc",
goh = "Ealdhēahþēodisc",
got = "Gotisc",
gv = "Manisc",
haw = "Hawaiisc",
hi = "Hindisc",
hu = "Hungarisc",
id = "Indonesisc",
io = "Idoisc",
is = "Īslendisc",
it = "Italisc",
iu = "Inuctitutisc",
la = "Lǣden",
li = "Limburgisc",
lt = "Litwisc",
lv = "Lettisc",
mul = "Þēodeorþe",
nap = "Neapolitisc",
nl = "Niðerlendisc",
no = "Norþwegisc",
non = "Eald Noren",
ovd = "Ælfdælisc",
pl = "Polisc",
pt = "Portugisc",
qu = "Kescwisc",
ro = "Rumǣnisc",
sa = "Sanscritisc",
sco = "Niderscyttisc",
sq = "Albānisc",
sv = "Swēonisc",
tpi = "Tok Pisin",
vo = "Volapük",
}
--[=[
Codes that are needed in etymology lines (ancestors and source languages) but that have no
name yet. They currently display their '''English''' name (via [[Module:languages]]) and should
be given an Old English name here. The forms below are suggestions only and are deliberately
commented out until they have been checked against a source.
-- gem-pro = "?", -- Proto-Germanic
-- gmw-pro = "?", -- Proto-West Germanic
-- ine-pro = "?", -- Proto-Indo-European
-- enm = "Middelenglisc", -- Middle English
-- gmh = "Middelhēahþēodisc", -- Middle High German
-- odt = "Ealdniðerlendisc", -- Old Dutch
-- dum = "Middelniðerlendisc", -- Middle Dutch
-- ofs = "?", -- Old Frisian
-- osx = "Ealdseaxisc", -- Old Saxon
-- gml = "Middelniðersaxisc", -- Middle Low German
-- cel-pro = "?", -- Proto-Celtic
-- gmq-pro = "?", -- Proto-North Germanic
]=]
--[=[
Explicit "of"-forms, for names that the `-isc` rule cannot handle. Add an entry whenever
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] lists a code that needs one. Suggestions
(commented out until checked against a source):
-- la = "Lǣdenes", -- Latin
-- non = "Eald Norðrena", -- Old Norse
-- mul = "Þēodeorðan", -- Translingual
-- vo = "Volapük", -- Volapük (no ending to inflect)
-- tpi = "Tok Pisin", -- Tok Pisin (no ending to inflect)
]=]
local of_names = {}
-- Spellings that may be passed to {{sprǣc}} or found in a ==L2== heading, mapped to their code.
local aliases = {
["Ænglisc"] = "ang",
}
-- Codes with no name display "?" and are tracked, so that the gaps are visible.
local function track(key)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module(key)
end
end
function export.track_missing_name(code)
code = tostring(code)
if code == "" then
code = "(empty)"
end
track("sprǣc/unknown code/" .. code)
end
local function track_no_of_form(code)
track("sprǣcnaman/no of-form/" .. tostring(code))
end
-- Accept either a language code or a language object (from [[Module:languages]]).
local function code_candidates(x)
if type(x) ~= "table" then
return { x }
end
local codes = {}
local code = x.getCode and x:getCode()
if code then
codes[#codes + 1] = code
end
local full_code = x.getFullCode and x:getFullCode()
if full_code and full_code ~= code then
codes[#codes + 1] = full_code
end
return codes
end
--[==[
Return the Old English name of the given language (code or language object), or nil if the
language has no name yet. Used for ==L2== headings and for category names.
]==]
function export.get_name(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return names[code]
end
end
return nil
end
--[==[
Return the "of"-form of the given language (code or language object), or nil if the language
has no name yet. Used wherever Old English needs "of" + genitive, e.g. "Of Englisce and".
Names that follow no rule fall back to the nominative and are tracked.
]==]
function export.get_of(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return export.get_of_for_code(code)
end
end
return nil
end
function export.get_of_for_code(code)
local name = names[code]
if not name then
return nil
end
if of_names[code] then
return of_names[code]
end
if name:sub(-3) == "isc" then
return name .. "e"
end
track_no_of_form(code)
return name
end
local code_of_name, lower_code_of_name
local function make_reverse_maps()
if code_of_name then
return
end
code_of_name, lower_code_of_name = {}, {}
for alias, code in pairs(aliases) do
code_of_name[alias] = code
lower_code_of_name[mw.ustring.lower(alias)] = code
end
for code, name in pairs(names) do
code_of_name[name] = code_of_name[name] or code
local lower = mw.ustring.lower(name)
lower_code_of_name[lower] = lower_code_of_name[lower] or code
end
end
--[==[
Return the code of the language with the given Old English name, or nil. Used by
[[Module:etymology/templates]] to match an ==L2== heading back to its language.
]==]
function export.get_code(name)
if type(name) ~= "string" then
return nil
end
name = mw.text.trim(name)
if name == "" then
return nil
end
make_reverse_maps()
return code_of_name[name] or lower_code_of_name[mw.ustring.lower(name)]
end
--[==[
Entry point for [[Bysen:sprǣc]]: {{sprǣc|CODE}} gives the name, {{sprǣc|CODE|of}} the
"of"-form. A code with no name gives "?" and is tracked, exactly as the template always has.
]==]
export["sprǣc"] = function(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
local mode = mw.text.trim(args[2] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name
if mode == "of" or mode == "gen" or mode == "genitive" then
name = export.get_of(code)
else
name = export.get_name(code)
if not name then
-- The argument may be a name rather than a code (e.g. "Englisc").
local matched_code = export.get_code(code)
name = matched_code and names[matched_code] or nil
end
end
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
--[==[
Entry point for templates that need the "of"-form only:
{{#invoke:sprǣcnaman|of|CODE}}.
]==]
function export.of(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name = export.get_of(code)
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
-- The tables are exposed for tests and maintenance scripts; use the getters elsewhere.
export.names = names
export.of_names = of_names
return export
7dllstpv35uopuydhj4chavheatxq8y
54955
54954
2026-09-30T03:24:21Z
Deadend0914
7211
54955
Scribunto
text/plain
--[=[
Rēgister of sprǣcnaman (language names) for the Old English Wiktionary.
This is the single place where the Old English name of a language is entered. Everything that
displays a language name on this wiki reads it from here:
* [[Bysen:sprǣc]] (the ==L2== heading template) is a thin wrapper around sprǣc() below.
* [[Module:etymology]] and [[Module:etymology/templates]] use get_name() for headings and
category names, and get_of() for the "of"-form, because Old English uses "of" + genitive
when an ancestor or source language is mentioned, e.g. "Of Englisce and".
Names are entered without leading or trailing spaces. get_of() applies the following rules in
order:
1. an explicit entry in `of_names` (for names that follow no rule);
2. `-isc` + "e" (Englisc -> Englisce, Nīwenglisc -> Nīwenglisce, Þēodisc -> Þēodisce);
3. otherwise the nominative name is returned unchanged and the miss is tracked in
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] so that an entry can be supplied.
Codes with no name at all display "?" (as [[Bysen:sprǣc]] always has) and are tracked in
[[Wiktionary:Tracking/sprǣc/unknown code]], see [[Special:WhatLinksHere/Wiktionary:Tracking/sprǣc/unknown code]].
]=]
local export = {}
local names = {
af = "Affricanisc",
ang = "Englisc",
bn = "Bengalisc",
ca = "Catalānisc",
cs = "Bæmisc",
da = "Denisc",
de = "Þēodisc",
el = "Crēacisc",
en = "Nīwenglisc",
eo = "Esperantisc",
es = "Spēonisc",
et = "Eotolisc",
eu = "Wascisc",
fa = "Persisc",
fi = "Finnisc",
fo = "Faerisc",
fr = "Frencisc",
frk = "Frencisc",
frp = "Profencalisc",
ga = "Īrisc",
gl = "Galizisc",
gn = "Awaisc",
goh = "Ealdhēahþēodisc",
got = "Gotisc",
gv = "Manisc",
haw = "Hawaiisc",
hi = "Hindisc",
hu = "Hungarisc",
id = "Indonesisc",
io = "Idoisc",
is = "Īslendisc",
it = "Italisc",
iu = "Inuctitutisc",
la = "Lǣden",
li = "Limburgisc",
lt = "Litwisc",
lv = "Lettisc",
mul = "Þēodeorþe",
nap = "Neapolitisc",
nl = "Niðerlendisc",
no = "Norþwegisc",
non = "Eald Noren",
ovd = "Ælfdælisc",
pl = "Polisc",
pt = "Portugisc",
qu = "Kescwisc",
ro = "Rumǣnisc",
sa = "Sanscritisc",
sco = "Niderscyttisc",
sq = "Albānisc",
sv = "Swēonisc",
tpi = "Tok Pisin",
vo = "Volapük",
xpi = "Pihtisc"
}
--[=[
Codes that are needed in etymology lines (ancestors and source languages) but that have no
name yet. They currently display their '''English''' name (via [[Module:languages]]) and should
be given an Old English name here. The forms below are suggestions only and are deliberately
commented out until they have been checked against a source.
-- gem-pro = "?", -- Proto-Germanic
-- gmw-pro = "?", -- Proto-West Germanic
-- ine-pro = "?", -- Proto-Indo-European
-- enm = "Middelenglisc", -- Middle English
-- gmh = "Middelhēahþēodisc", -- Middle High German
-- odt = "Ealdniðerlendisc", -- Old Dutch
-- dum = "Middelniðerlendisc", -- Middle Dutch
-- ofs = "?", -- Old Frisian
-- osx = "Ealdseaxisc", -- Old Saxon
-- gml = "Middelniðersaxisc", -- Middle Low German
-- cel-pro = "?", -- Proto-Celtic
-- gmq-pro = "?", -- Proto-North Germanic
]=]
--[=[
Explicit "of"-forms, for names that the `-isc` rule cannot handle. Add an entry whenever
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] lists a code that needs one. Suggestions
(commented out until checked against a source):
-- la = "Lǣdenes", -- Latin
-- non = "Eald Norðrena", -- Old Norse
-- mul = "Þēodeorðan", -- Translingual
-- vo = "Volapük", -- Volapük (no ending to inflect)
-- tpi = "Tok Pisin", -- Tok Pisin (no ending to inflect)
]=]
local of_names = {}
-- Spellings that may be passed to {{sprǣc}} or found in a ==L2== heading, mapped to their code.
local aliases = {
["Ænglisc"] = "ang",
}
-- Codes with no name display "?" and are tracked, so that the gaps are visible.
local function track(key)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module(key)
end
end
function export.track_missing_name(code)
code = tostring(code)
if code == "" then
code = "(empty)"
end
track("sprǣc/unknown code/" .. code)
end
local function track_no_of_form(code)
track("sprǣcnaman/no of-form/" .. tostring(code))
end
-- Accept either a language code or a language object (from [[Module:languages]]).
local function code_candidates(x)
if type(x) ~= "table" then
return { x }
end
local codes = {}
local code = x.getCode and x:getCode()
if code then
codes[#codes + 1] = code
end
local full_code = x.getFullCode and x:getFullCode()
if full_code and full_code ~= code then
codes[#codes + 1] = full_code
end
return codes
end
--[==[
Return the Old English name of the given language (code or language object), or nil if the
language has no name yet. Used for ==L2== headings and for category names.
]==]
function export.get_name(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return names[code]
end
end
return nil
end
--[==[
Return the "of"-form of the given language (code or language object), or nil if the language
has no name yet. Used wherever Old English needs "of" + genitive, e.g. "Of Englisce and".
Names that follow no rule fall back to the nominative and are tracked.
]==]
function export.get_of(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return export.get_of_for_code(code)
end
end
return nil
end
function export.get_of_for_code(code)
local name = names[code]
if not name then
return nil
end
if of_names[code] then
return of_names[code]
end
if name:sub(-3) == "isc" then
return name .. "e"
end
track_no_of_form(code)
return name
end
local code_of_name, lower_code_of_name
local function make_reverse_maps()
if code_of_name then
return
end
code_of_name, lower_code_of_name = {}, {}
for alias, code in pairs(aliases) do
code_of_name[alias] = code
lower_code_of_name[mw.ustring.lower(alias)] = code
end
for code, name in pairs(names) do
code_of_name[name] = code_of_name[name] or code
local lower = mw.ustring.lower(name)
lower_code_of_name[lower] = lower_code_of_name[lower] or code
end
end
--[==[
Return the code of the language with the given Old English name, or nil. Used by
[[Module:etymology/templates]] to match an ==L2== heading back to its language.
]==]
function export.get_code(name)
if type(name) ~= "string" then
return nil
end
name = mw.text.trim(name)
if name == "" then
return nil
end
make_reverse_maps()
return code_of_name[name] or lower_code_of_name[mw.ustring.lower(name)]
end
--[==[
Entry point for [[Bysen:sprǣc]]: {{sprǣc|CODE}} gives the name, {{sprǣc|CODE|of}} the
"of"-form. A code with no name gives "?" and is tracked, exactly as the template always has.
]==]
export["sprǣc"] = function(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
local mode = mw.text.trim(args[2] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name
if mode == "of" or mode == "gen" or mode == "genitive" then
name = export.get_of(code)
else
name = export.get_name(code)
if not name then
-- The argument may be a name rather than a code (e.g. "Englisc").
local matched_code = export.get_code(code)
name = matched_code and names[matched_code] or nil
end
end
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
--[==[
Entry point for templates that need the "of"-form only:
{{#invoke:sprǣcnaman|of|CODE}}.
]==]
function export.of(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name = export.get_of(code)
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
-- The tables are exposed for tests and maintenance scripts; use the getters elsewhere.
export.names = names
export.of_names = of_names
return export
l9mti4shau7m5vh0nzsxtx7u6l1e9kw
54956
54955
2026-09-30T03:26:37Z
Deadend0914
7211
54956
Scribunto
text/plain
--[=[
Rēgister of sprǣcnaman (language names) for the Old English Wiktionary.
This is the single place where the Old English name of a language is entered. Everything that
displays a language name on this wiki reads it from here:
* [[Bysen:sprǣc]] (the ==L2== heading template) is a thin wrapper around sprǣc() below.
* [[Module:etymology]] and [[Module:etymology/templates]] use get_name() for headings and
category names, and get_of() for the "of"-form, because Old English uses "of" + genitive
when an ancestor or source language is mentioned, e.g. "Of Englisce and".
Names are entered without leading or trailing spaces. get_of() applies the following rules in
order:
1. an explicit entry in `of_names` (for names that follow no rule);
2. `-isc` + "e" (Englisc -> Englisce, Nīwenglisc -> Nīwenglisce, Þēodisc -> Þēodisce);
3. otherwise the nominative name is returned unchanged and the miss is tracked in
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] so that an entry can be supplied.
Codes with no name at all display "?" (as [[Bysen:sprǣc]] always has) and are tracked in
[[Wiktionary:Tracking/sprǣc/unknown code]], see [[Special:WhatLinksHere/Wiktionary:Tracking/sprǣc/unknown code]].
]=]
local export = {}
local names = {
af = "Affricanisc",
ang = "Englisc",
bn = "Bengalisc",
ca = "Catalānisc",
cs = "Bæmisc",
da = "Denisc",
de = "Þēodisc",
el = "Crēacisc",
en = "Nīwenglisc",
eo = "Esperantisc",
es = "Spēonisc",
et = "Eotolisc",
eu = "Wascisc",
fa = "Persisc",
fi = "Finnisc",
fo = "Faerisc",
fr = "Frencisc",
frk = "Frencisc",
frp = "Profencalisc",
ga = "Īrisc",
gl = "Galizisc",
gn = "Awaisc",
goh = "Ealdhēahþēodisc",
got = "Gotisc",
gv = "Manisc",
haw = "Hawaiisc",
hi = "Hindisc",
hu = "Hungarisc",
id = "Indonesisc",
io = "Idoisc",
is = "Īslendisc",
it = "Italisc",
iu = "Inuctitutisc",
la = "Lǣden",
li = "Limburgisc",
lt = "Litwisc",
lv = "Lettisc",
mul = "Þēodeorþe",
nap = "Neapolitisc",
nl = "Niðerlendisc",
no = "Norþwegisc",
non = "Eald Noren",
ovd = "Ælfdælisc",
pl = "Polisc",
pt = "Portugisc",
qu = "Kescwisc",
ro = "Rumǣnisc",
ru = "Rusisc",
sa = "Sanscritisc",
sco = "Niderscyttisc",
sq = "Albānisc",
sv = "Swēonisc",
tpi = "Tok Pisin",
vo = "Volapük",
xpi = "Pihtisc"
}
--[=[
Codes that are needed in etymology lines (ancestors and source languages) but that have no
name yet. They currently display their '''English''' name (via [[Module:languages]]) and should
be given an Old English name here. The forms below are suggestions only and are deliberately
commented out until they have been checked against a source.
-- gem-pro = "?", -- Proto-Germanic
-- gmw-pro = "?", -- Proto-West Germanic
-- ine-pro = "?", -- Proto-Indo-European
-- enm = "Middelenglisc", -- Middle English
-- gmh = "Middelhēahþēodisc", -- Middle High German
-- odt = "Ealdniðerlendisc", -- Old Dutch
-- dum = "Middelniðerlendisc", -- Middle Dutch
-- ofs = "?", -- Old Frisian
-- osx = "Ealdseaxisc", -- Old Saxon
-- gml = "Middelniðersaxisc", -- Middle Low German
-- cel-pro = "?", -- Proto-Celtic
-- gmq-pro = "?", -- Proto-North Germanic
]=]
--[=[
Explicit "of"-forms, for names that the `-isc` rule cannot handle. Add an entry whenever
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] lists a code that needs one. Suggestions
(commented out until checked against a source):
-- la = "Lǣdenes", -- Latin
-- non = "Eald Norðrena", -- Old Norse
-- mul = "Þēodeorðan", -- Translingual
-- vo = "Volapük", -- Volapük (no ending to inflect)
-- tpi = "Tok Pisin", -- Tok Pisin (no ending to inflect)
]=]
local of_names = {}
-- Spellings that may be passed to {{sprǣc}} or found in a ==L2== heading, mapped to their code.
local aliases = {
["Ænglisc"] = "ang",
}
-- Codes with no name display "?" and are tracked, so that the gaps are visible.
local function track(key)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module(key)
end
end
function export.track_missing_name(code)
code = tostring(code)
if code == "" then
code = "(empty)"
end
track("sprǣc/unknown code/" .. code)
end
local function track_no_of_form(code)
track("sprǣcnaman/no of-form/" .. tostring(code))
end
-- Accept either a language code or a language object (from [[Module:languages]]).
local function code_candidates(x)
if type(x) ~= "table" then
return { x }
end
local codes = {}
local code = x.getCode and x:getCode()
if code then
codes[#codes + 1] = code
end
local full_code = x.getFullCode and x:getFullCode()
if full_code and full_code ~= code then
codes[#codes + 1] = full_code
end
return codes
end
--[==[
Return the Old English name of the given language (code or language object), or nil if the
language has no name yet. Used for ==L2== headings and for category names.
]==]
function export.get_name(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return names[code]
end
end
return nil
end
--[==[
Return the "of"-form of the given language (code or language object), or nil if the language
has no name yet. Used wherever Old English needs "of" + genitive, e.g. "Of Englisce and".
Names that follow no rule fall back to the nominative and are tracked.
]==]
function export.get_of(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return export.get_of_for_code(code)
end
end
return nil
end
function export.get_of_for_code(code)
local name = names[code]
if not name then
return nil
end
if of_names[code] then
return of_names[code]
end
if name:sub(-3) == "isc" then
return name .. "e"
end
track_no_of_form(code)
return name
end
local code_of_name, lower_code_of_name
local function make_reverse_maps()
if code_of_name then
return
end
code_of_name, lower_code_of_name = {}, {}
for alias, code in pairs(aliases) do
code_of_name[alias] = code
lower_code_of_name[mw.ustring.lower(alias)] = code
end
for code, name in pairs(names) do
code_of_name[name] = code_of_name[name] or code
local lower = mw.ustring.lower(name)
lower_code_of_name[lower] = lower_code_of_name[lower] or code
end
end
--[==[
Return the code of the language with the given Old English name, or nil. Used by
[[Module:etymology/templates]] to match an ==L2== heading back to its language.
]==]
function export.get_code(name)
if type(name) ~= "string" then
return nil
end
name = mw.text.trim(name)
if name == "" then
return nil
end
make_reverse_maps()
return code_of_name[name] or lower_code_of_name[mw.ustring.lower(name)]
end
--[==[
Entry point for [[Bysen:sprǣc]]: {{sprǣc|CODE}} gives the name, {{sprǣc|CODE|of}} the
"of"-form. A code with no name gives "?" and is tracked, exactly as the template always has.
]==]
export["sprǣc"] = function(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
local mode = mw.text.trim(args[2] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name
if mode == "of" or mode == "gen" or mode == "genitive" then
name = export.get_of(code)
else
name = export.get_name(code)
if not name then
-- The argument may be a name rather than a code (e.g. "Englisc").
local matched_code = export.get_code(code)
name = matched_code and names[matched_code] or nil
end
end
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
--[==[
Entry point for templates that need the "of"-form only:
{{#invoke:sprǣcnaman|of|CODE}}.
]==]
function export.of(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name = export.get_of(code)
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
-- The tables are exposed for tests and maintenance scripts; use the getters elsewhere.
export.names = names
export.of_names = of_names
return export
n6cgjhdwd3iiqjerrhpss7n01t5qbo8
54957
54956
2026-09-30T03:33:29Z
Deadend0914
7211
54957
Scribunto
text/plain
--[=[
Rēgister of sprǣcnaman (language names) for the Old English Wiktionary.
This is the single place where the Old English name of a language is entered. Everything that
displays a language name on this wiki reads it from here:
* [[Bysen:sprǣc]] (the ==L2== heading template) is a thin wrapper around sprǣc() below.
* [[Module:etymology]] and [[Module:etymology/templates]] use get_name() for headings and
category names, and get_of() for the "of"-form, because Old English uses "of" + genitive
when an ancestor or source language is mentioned, e.g. "Of Englisce and".
Names are entered without leading or trailing spaces. get_of() applies the following rules in
order:
1. an explicit entry in `of_names` (for names that follow no rule);
2. `-isc` + "e" (Englisc -> Englisce, Nīwenglisc -> Nīwenglisce, Þēodisc -> Þēodisce);
3. otherwise the nominative name is returned unchanged and the miss is tracked in
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] so that an entry can be supplied.
Codes with no name at all display "?" (as [[Bysen:sprǣc]] always has) and are tracked in
[[Wiktionary:Tracking/sprǣc/unknown code]], see [[Special:WhatLinksHere/Wiktionary:Tracking/sprǣc/unknown code]].
]=]
local export = {}
local names = {
aa = "Cafarisc",
ab = "Apscwisc",
af = "Affricanisc",
ak = "Ækanisc",
ang = "Englisc",
bn = "Bengalisc",
ca = "Catalānisc",
cs = "Bæmisc",
da = "Denisc",
de = "Þēodisc",
el = "Crēacisc",
en = "Nīwenglisc",
eo = "Esperantisc",
es = "Spēonisc",
et = "Eotolisc",
eu = "Wascisc",
fa = "Persisc",
fi = "Finnisc",
fo = "Faerisc",
fr = "Frencisc",
frk = "Frencisc",
frp = "Profencalisc",
ga = "Īrisc",
gl = "Galizisc",
gn = "Awaisc",
goh = "Ealdhēahþēodisc",
got = "Gotisc",
gv = "Manisc",
haw = "Hawaiisc",
hi = "Hindisc",
hu = "Hungarisc",
id = "Indonesisc",
io = "Idoisc",
is = "Īslendisc",
it = "Italisc",
iu = "Inuctitutisc",
la = "Lǣden",
li = "Limburgisc",
lt = "Litwisc",
lv = "Lettisc",
mul = "Þēodeorþe",
nap = "Neapolitisc",
nl = "Niðerlendisc",
no = "Norþwegisc",
non = "Eald Noren",
ovd = "Ælfdælisc",
pl = "Polisc",
pt = "Portugisc",
qu = "Kescwisc",
ro = "Rumǣnisc",
ru = "Rusisc",
sa = "Sanscritisc",
sco = "Niderscyttisc",
sq = "Albānisc",
sv = "Swēonisc",
tpi = "Tok Pisin",
vo = "Volapük",
xpi = "Pihtisc"
}
--[=[
Codes that are needed in etymology lines (ancestors and source languages) but that have no
name yet. They currently display their '''English''' name (via [[Module:languages]]) and should
be given an Old English name here. The forms below are suggestions only and are deliberately
commented out until they have been checked against a source.
-- gem-pro = "?", -- Proto-Germanic
-- gmw-pro = "?", -- Proto-West Germanic
-- ine-pro = "?", -- Proto-Indo-European
-- enm = "Middelenglisc", -- Middle English
-- gmh = "Middelhēahþēodisc", -- Middle High German
-- odt = "Ealdniðerlendisc", -- Old Dutch
-- dum = "Middelniðerlendisc", -- Middle Dutch
-- ofs = "?", -- Old Frisian
-- osx = "Ealdseaxisc", -- Old Saxon
-- gml = "Middelniðersaxisc", -- Middle Low German
-- cel-pro = "?", -- Proto-Celtic
-- gmq-pro = "?", -- Proto-North Germanic
]=]
--[=[
Explicit "of"-forms, for names that the `-isc` rule cannot handle. Add an entry whenever
[[Wiktionary:Tracking/sprǣcnaman/no of-form]] lists a code that needs one. Suggestions
(commented out until checked against a source):
-- la = "Lǣdenes", -- Latin
-- non = "Eald Norðrena", -- Old Norse
-- mul = "Þēodeorðan", -- Translingual
-- vo = "Volapük", -- Volapük (no ending to inflect)
-- tpi = "Tok Pisin", -- Tok Pisin (no ending to inflect)
]=]
local of_names = {}
-- Spellings that may be passed to {{sprǣc}} or found in a ==L2== heading, mapped to their code.
local aliases = {
["Ænglisc"] = "ang",
}
-- Codes with no name display "?" and are tracked, so that the gaps are visible.
local function track(key)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module(key)
end
end
function export.track_missing_name(code)
code = tostring(code)
if code == "" then
code = "(empty)"
end
track("sprǣc/unknown code/" .. code)
end
local function track_no_of_form(code)
track("sprǣcnaman/no of-form/" .. tostring(code))
end
-- Accept either a language code or a language object (from [[Module:languages]]).
local function code_candidates(x)
if type(x) ~= "table" then
return { x }
end
local codes = {}
local code = x.getCode and x:getCode()
if code then
codes[#codes + 1] = code
end
local full_code = x.getFullCode and x:getFullCode()
if full_code and full_code ~= code then
codes[#codes + 1] = full_code
end
return codes
end
--[==[
Return the Old English name of the given language (code or language object), or nil if the
language has no name yet. Used for ==L2== headings and for category names.
]==]
function export.get_name(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return names[code]
end
end
return nil
end
--[==[
Return the "of"-form of the given language (code or language object), or nil if the language
has no name yet. Used wherever Old English needs "of" + genitive, e.g. "Of Englisce and".
Names that follow no rule fall back to the nominative and are tracked.
]==]
function export.get_of(x)
for _, code in ipairs(code_candidates(x)) do
if names[code] then
return export.get_of_for_code(code)
end
end
return nil
end
function export.get_of_for_code(code)
local name = names[code]
if not name then
return nil
end
if of_names[code] then
return of_names[code]
end
if name:sub(-3) == "isc" then
return name .. "e"
end
track_no_of_form(code)
return name
end
local code_of_name, lower_code_of_name
local function make_reverse_maps()
if code_of_name then
return
end
code_of_name, lower_code_of_name = {}, {}
for alias, code in pairs(aliases) do
code_of_name[alias] = code
lower_code_of_name[mw.ustring.lower(alias)] = code
end
for code, name in pairs(names) do
code_of_name[name] = code_of_name[name] or code
local lower = mw.ustring.lower(name)
lower_code_of_name[lower] = lower_code_of_name[lower] or code
end
end
--[==[
Return the code of the language with the given Old English name, or nil. Used by
[[Module:etymology/templates]] to match an ==L2== heading back to its language.
]==]
function export.get_code(name)
if type(name) ~= "string" then
return nil
end
name = mw.text.trim(name)
if name == "" then
return nil
end
make_reverse_maps()
return code_of_name[name] or lower_code_of_name[mw.ustring.lower(name)]
end
--[==[
Entry point for [[Bysen:sprǣc]]: {{sprǣc|CODE}} gives the name, {{sprǣc|CODE|of}} the
"of"-form. A code with no name gives "?" and is tracked, exactly as the template always has.
]==]
export["sprǣc"] = function(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
local mode = mw.text.trim(args[2] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name
if mode == "of" or mode == "gen" or mode == "genitive" then
name = export.get_of(code)
else
name = export.get_name(code)
if not name then
-- The argument may be a name rather than a code (e.g. "Englisc").
local matched_code = export.get_code(code)
name = matched_code and names[matched_code] or nil
end
end
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
--[==[
Entry point for templates that need the "of"-form only:
{{#invoke:sprǣcnaman|of|CODE}}.
]==]
function export.of(frame)
local args = frame and frame.args or {}
local code = mw.text.trim(args[1] or "")
if code == "" then
export.track_missing_name("")
return "?"
end
local name = export.get_of(code)
if not name then
export.track_missing_name(code)
return "?"
end
return name
end
-- The tables are exposed for tests and maintenance scripts; use the getters elsewhere.
export.names = names
export.of_names = of_names
return export
sgc9l1eqwlrgbxt8y3rtjmc1scca4jd
Module:floccnaman
828
8082
54927
54916
2026-09-29T18:38:46Z
Deadend0914
7211
54927
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["feminine"] = "wīflic",
["neuter"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["intitialisms"] = "styrtende stæfgefēg",
["particles"] = "grot"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
81gb5qns9m5g8rypr89ksxwfrzlv9ep
54928
54927
2026-09-29T18:47:52Z
Deadend0914
7211
54928
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["feminine"] = "wīflic",
["neuter"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
3ek4e428gigpe51ubr9770jt8awwrvf
54933
54928
2026-09-29T19:32:19Z
Deadend0914
7211
54933
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine POS"] = "werlic",
["feminine"] = "wīflic",
["feminine POS"] = "wīflic",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
ge27748q3cadj1onl8rfnliji9ar93v
54934
54933
2026-09-29T19:35:46Z
Deadend0914
7211
54934
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
jqebh8sq3vw1sx2z2oj36dlw9m4gt2z
54939
54934
2026-09-30T02:33:21Z
Deadend0914
7211
54939
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot",
["terms spelled with"] = "word areahton mid"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
i6ii8kfhwerjuopxt2ct9561oz8btq2
54940
54939
2026-09-30T02:41:37Z
Deadend0914
7211
54940
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot",
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
["terms spelled with "] = "word areahton mid "
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
0vow1i981cy0uu16tdmg257noh1s7zv
54942
54940
2026-09-30T02:50:39Z
Deadend0914
7211
54942
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot",
["pages with entries"] = "trāmetas mid word"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
["terms spelled with "] = "word areahton mid "
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
634cion56y820opxapsi6n863racdsm
54943
54942
2026-09-30T02:52:07Z
Deadend0914
7211
54943
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["masculine a-stem nouns"] = "werlic a-stefn naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot",
["pages with entries"] = "trāmetas mid word"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
["terms spelled with "] = "word areahton mid "
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
g8a7cyhrcmtznl8xtvj6hotn0sice9s
54944
54943
2026-09-30T03:02:03Z
Deadend0914
7211
54944
Scribunto
text/plain
--[=[
Floccnaman (category names) for the Old English Wiktionary.
Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or
"<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki
("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need
translating, never the word order.
The modules that build such categories ([[Module:headword]], [[Module:headword utilities]],
[[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]],
[[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English
wording first and keep the English wording if it is not here yet. Every missing wording is
tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs
to be added is always up to date:
[[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]]
Words are entered without leading or trailing spaces, in the singular for parts of speech
("nama", not "naman"), because that is what the pre-existing categories use. The plural forms
used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...).
Only categories a reader sees on an entry page are translated here. Maintenance and tracking
categories (sortkeys, script codes, requests, pages with ...), the categories of the template
namespace and the ones produced by MediaWiki itself stay English on purpose.
]=]
local export = {}
--[=[
English wording -> Old English wording.
The words in this first group are already used by categories and template names that exist on
this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc
fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender
words match the existing "Eald Noren werlic nama" style.
]=]
local words = {
-- Parts of speech.
["nouns"] = "naman",
["verbs"] = "word",
["adjectives"] = "tōgeīecendlice word",
["adverbs"] = "bīword",
["conjunctions"] = "fégunga",
["pronouns"] = "bīnaman",
["prepositions"] = "foresetnessa",
["participles"] = "dǣlnimend",
["past participles"] = "forþgewiten dǣlnimend",
["present participles"] = "andweard dǣlnimend",
["masculine"] = "werlic",
["masculine nouns"] = "werlic naman",
["masculine a-stem nouns"] = "werlic a-stefn naman",
["feminine"] = "wīflic",
["feminine nouns"] = "wīflic naman",
["neuter"] = "nāhwæðer",
["neuter POS"] = "nāhwæðer",
["lemmas"] = "frumcennede word",
["non-lemma forms"] = "gebīegede word",
["variant lemmas"] = "ōþre frumcennede word",
["variant non-lemma forms"] = "ōþre gebīegede word",
["proper nouns"] = "āgennama",
["numerals"] = "getælu",
["letters"] = "stafas",
["proverbs"] = "gecyndesprǣce",
["other languages"] = "ōþre sprǣce",
["terms borrowed from"] = "word borgodon of",
["terms borrowed back into"] = "word borgodon tō",
["terms inherited from"] = "word ierfde of",
["terms derived from"] = "word ofgangende fram",
["learned borrowings"] = "leornode borgiende",
["compound words"] = "manigfeald word",
["abbreviations"] = "scortnessa",
["phrases"] = "cwidas",
["determiners"] = "bīnama",
["symbols"] = "rūna",
["countable nouns"] = "tellendlīc naman",
["uncountable nouns"] = "untellendlīc naman",
["initialisms"] = "styrtende stæfgefēg",
["particles"] = "grot",
["pages with entries"] = "trāmetas mid word"
}
--[=[
Wording still to be translated. Anything listed here (or used in a module but not listed at
all) falls back to its English form and shows up in
[[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in.
Suggestions, commented out until checked against a source:
-- ["suffixes"] = "?", -- "Englisc ?"
-- ["prefixes"] = "?",
-- ["interjections"] = "?",
-- ["Translingual"] = "?",
-- ["taxonomic names"] = "?",
]=]
--[=[
Wording that carries a variable part, as a leading phrase. For example the affix templates
build categories such as "terms suffixed with -kas", where only the beginning is fixed; the
language name is prepended by the caller. Longest phrase first, so the most specific rule wins.
]=]
local prefixes = {
{"terms spelled with ", "word areahton mid "}
-- {"terms suffixed with ", "?"},
-- {"terms prefixed with ", "?"},
-- {"terms circumfixed with ", "?"},
-- {"terms infixed with ", "?"},
-- {"terms interfixed with ", "?"},
}
local function track(text)
local ok, track_module = pcall(require, "Module:debug/track")
if ok then
track_module("flocc/untranslated/" .. tostring(text))
end
end
--[==[
Return the Old English wording for one category name, or nil if it is not known yet. `lang` is
accepted so that a wording can later be made language-specific if that turns out to be needed.
]==]
function export.translate(lang, text)
if type(text) ~= "string" or text == "" then
return nil
end
if words[text] then
return words[text]
end
for _, rule in ipairs(prefixes) do
if text:sub(1, #rule[1]) == rule[1] then
return rule[2] .. text:sub(#rule[1] + 1)
end
end
track(text)
return nil
end
--[==[
Return the Old English wording for one category name, or the English wording unchanged if it is
not known yet. Use this in the modules that build categories: the language name is prepended by
the caller, so only the wording itself is passed in.
]==]
function export.get(lang, text)
return export.translate(lang, text) or text
end
-- The table is exposed for tests and maintenance scripts; use get() elsewhere.
export.words = words
return export
lv24gj2uyubglol30m1fhhvzkurs3ea
Flocc:Englisc werlic naman
14
8083
54947
2026-09-30T03:13:40Z
Deadend0914
7211
Gesceop tramet þe hafaþ 'Naman in þǽre Engliscan sprǽce, þe werlicne hád habbaþ. [[Category:Englisc nama]]'
54947
wikitext
text/x-wiki
Naman in þǽre Engliscan sprǽce, þe werlicne hád habbaþ.
[[Category:Englisc nama]]
cxrrtytsibpn1vcfeoub9jp36nfg8ej
Bysen:head
10
8084
54950
2026-09-30T03:18:45Z
Deadend0914
7211
Gesceop tramet þe hafaþ '<includeonly>{{#invoke:headword/templates|head_t}}<!-- --></includeonly><noinclude>{{head|und|nouns}}{{documentation}}</noinclude>'
54950
wikitext
text/x-wiki
<includeonly>{{#invoke:headword/templates|head_t}}<!--
--></includeonly><noinclude>{{head|und|nouns}}{{documentation}}</noinclude>
akjc34wkcxijofwsgfubqlbnq1w4fqs
Module:headword/templates
828
8085
54951
2026-09-30T03:19:21Z
Deadend0914
7211
Gesceop tramet þe hafaþ 'local export = {} local debug_track_module = "Module:debug/track" local headword_module = "Module:headword" local headword_data_module = "Module:headword/data" local parameters_module = "Module:parameters" local yesno_module = "Module:yesno" local insert = table.insert local require = require local function debug_track(...) debug_track = require(debug_track_module) return debug_track(...) end local function process_params(...) process_params = require(par...'
54951
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local headword_module = "Module:headword"
local headword_data_module = "Module:headword/data"
local parameters_module = "Module:parameters"
local yesno_module = "Module:yesno"
local insert = table.insert
local require = require
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function track(page)
debug_track("headword/templates/" .. page)
return true
end
local function get_args(frame)
local boolean = {type = "boolean"}
local boolean_list_allow_holes = {type = "boolean", list = true, allow_holes = true}
local list_allow_holes = {list = true, allow_holes = true}
return process_params(frame:getParent().args, {
[1] = {required = true, type = "language", template_default = "und"},
sc = {type = "script"},
sort = true,
[2] = {required = true, template_default = "nouns"},
sccat = boolean,
noposcat = boolean,
nomultiwordcat = boolean,
nogendercat = boolean,
nopalindromecat = boolean,
nolinkhead = boolean,
-- Don't track uses of this template for the purpose of finding direct calls to {{head}}.
-- Useful for templates that wrap {{tl|head}}.
notrackuses = boolean,
autotrinfl = boolean,
var = true,
checkredlinks = true,
cat2 = true,
cat3 = true,
cat4 = true,
pagename = true,
head = list_allow_holes,
image = true,
id = true,
tr = list_allow_holes,
ts = list_allow_holes,
gloss = true,
g = {list = true, type = "genders", flatten = true},
["g\1qual"] = {list = true, allow_holes = true, replaced_by = false, instead = "use <q:...> or <l:...> inline modifier on a gender"},
[3] = list_allow_holes,
["f\1accel-form"] = list_allow_holes,
["f\1accel-translit"] = list_allow_holes,
["f\1accel-lemma"] = list_allow_holes,
["f\1accel-lemma-translit"] = list_allow_holes,
["f\1accel-gender"] = list_allow_holes,
["f\1accel-nostore"] = boolean_list_allow_holes,
["f\1request"] = list_allow_holes,
["f\1alt"] = list_allow_holes,
["f\1lang"] = {list = true, allow_holes = true, type = "language"},
["f\1sc"] = {list = true, allow_holes = true, type = "script"},
["f\1id"] = list_allow_holes,
["f\1tr"] = list_allow_holes,
["f\1ts"] = list_allow_holes,
["f\1t"] = list_allow_holes,
["f\1lit"] = list_allow_holes,
["f\1pos"] = list_allow_holes,
["f\1ng"] = list_allow_holes,
["f\1g"] = {list = true, allow_holes = true, type = "genders"},
["f\1q"] = {list = true, allow_holes = true, type = "qualifier"},
["f\1qq"] = {list = true, allow_holes = true, type = "qualifier"},
["f\1qual"] = {list = true, allow_holes = true, replaced_by = false, instead = "use fNq= or fNl="},
["f\1l"] = {list = true, allow_holes = true, type = "labels"},
["f\1ll"] = {list = true, allow_holes = true, type = "labels"},
["f\1ref"] = {list = true, allow_holes = true, type = "references"},
["f\1autotr"] = boolean_list_allow_holes,
["f\1nolink"] = boolean_list_allow_holes,
})
end
function export.head_t(frame)
local m_headword = require(headword_module)
local args = get_args(frame)
-- Get language and script information
local data = {}
data.lang = args[1]
data.sc = args.sc
data.sccat = args.sccat
data.sort_key = args.sort
data.heads = args.head
data.image = args.image
data.pagename = args.pagename
data.id = args.id
data.translits = args.tr
data.transcriptions = args.ts
data.gloss = args.gloss
data.genders = args.g
-- TODO should throw an error if data.heads gets overwritten
if data.image then
data.heads = {"[[File:" .. data.image .. "|class=skin-invert-image]]"}
end
-- This shouldn't really happen.
for i = 1, args.head.maxindex do
if not args.head[i] then
track("head-with-holes")
end
end
-- Variant forms (lemmas or non-lemma forms)
if args.var then
data.var = require(yesno_module)(args.var, args.var)
end
-- Part-of-speech category
local pos_category = args[2]
data.noposcat = args.noposcat
-- Check for headword aliases and then pluralize if the POS term does not have an invariable plural.
data.pos_category = m_headword.canonicalize_pos(pos_category)
-- Track all direct uses of {{head}} for certain languages that have a {{XX-head}} template that should be
-- used instead. Examples: {{en-head}}, {{sa-head}}, {{hi-head}}, {{tl-head}}, etc.
if not args.notrackuses then
local langcode = data.lang:getCode()
local langfullcode = data.lang:getFullCode()
if mw.loadData(headword_data_module).track_head_template[langfullcode] then
track(langcode)
track(langcode .. "/" .. data.pos_category)
if langcode ~= langfullcode then
track(langfullcode)
track(langfullcode .. "/" .. data.pos_category)
end
end
end
-- Additional categories.
local categories = {}
data.whole_page_categories = {}
data.nomultiwordcat = args.nomultiwordcat
data.nogendercat = args.nogendercat
data.nopalindromecat = args.nopalindromecat
-- FIXME: add a minimum_index spec to [[Module:parameters]] list specs, so
-- that `cat` can be changed to a list parameter starting at index 2.
if args.cat2 then
insert(categories, data.lang:getFullName() .. " " .. args.cat2)
end
if args.cat3 then
insert(categories, data.lang:getFullName() .. " " .. args.cat3)
end
if args.cat4 then
insert(categories, data.lang:getFullName() .. " " .. args.cat4)
end
data.categories = categories
if args.checkredlinks then
data.checkredlinks = require(yesno_module)(args.checkredlinks, args.checkredlinks)
end
-- Headword linking
data.nolinkhead = args.nolinkhead
-- Inflected forms
data.inflections = {enable_auto_translit = args.autotrinfl}
local forms = args[3]
local n = forms.maxindex / 2
for i = 1, n + n % 1 do
local infl_part = {
label = forms[i * 2 - 1],
accel = args["faccel-form"][i] and {
form = args["faccel-form"][i],
translit = args["faccel-translit"][i],
lemma = args["faccel-lemma"][i],
lemma_translit = args["faccel-lemma-translit"][i],
gender = args["faccel-gender"][i],
nostore = args["faccel-nostore"][i],
} or nil,
request = args.frequest[i],
enable_auto_translit = args.fautotr[i],
}
local form = {
term = forms[i * 2],
alt = args.falt[i],
genders = args.fg[i],
id = args.fid[i],
lang = args.flang[i],
nolinkinfl = args.fnolink[i],
q = args.fq[i],
qq = args.fqq[i],
l = args.fl[i],
ll = args.fll[i],
refs = args.fref[i],
sc = args.fsc[i],
tr = args.ftr[i],
ts = args.fts[i],
gloss = args.ft[i],
lit = args.flit[i],
pos = args.fpos[i],
ng = args.fng[i],
}
-- If no term or alt is given, then the label is shown alone.
if form.term or form.alt then
insert(infl_part, form)
end
if infl_part.label == "or" then
-- Append to the previous inflection part, if one exists
if #infl_part > 0 and data.inflections[1] then
insert(data.inflections[#data.inflections], form)
end
elseif infl_part.label then
-- Add a new inflection part
insert(data.inflections, infl_part)
end
end
return m_headword.full_headword(data)
end
function export.canonicalize_pos(frame)
local iargs = process_params(frame.args, {
[1] = {required = true},
})
return require(headword_module).canonicalize_pos(iargs[1])
end
return export
5vszegxurqbvbqyoopsgo6g7edtgq1c