ဝိက်ရှေန်နရဳ
mnwwiktionary
https://mnw.wiktionary.org/wiki/%E1%80%9D%E1%80%AD%E1%80%80%E1%80%BA%E1%80%9B%E1%80%BE%E1%80%B1%E1%80%94%E1%80%BA%E1%80%94%E1%80%9B%E1%80%B3:%E1%80%99%E1%80%AF%E1%80%80%E1%80%BA%E1%80%9C%E1%80%AD%E1%80%80%E1%80%BA%E1%80%90%E1%80%99%E1%80%BA
MediaWiki 1.46.0-wmf.23
case-sensitive
မဳဒဳယာ
တၟေင်
ဓရီုကျာ
ညးလွပ်
ညးလွပ် ဓရီုကျာ
ဝိက်ရှေန်နရဳ
ဝိက်ရှေန်နရဳ ဓရီုကျာ
ဝှာင်
ဝှာင် ဓရီုကျာ
မဳဒဳယာဝဳကဳ
မဳဒဳယာဝဳကဳ ဓရီုကျာ
ထာမ်ပလိက်
ထာမ်ပလိက် ဓရီုကျာ
ရီု
ရီု ဓရီုကျာ
ကဏ္ဍ
ကဏ္ဍ ဓရီုကျာ
အဆက်လက္ကရဴ
အဆက်လက္ကရဴ ဓရီုကျာ
ကာရန်
ကာရန် ဓရီုကျာ
အဘိဓာန်
အဘိဓာန် ဓရီုကျာ
ဗီုပြၚ်သိုၚ်တၟိ
ဗီုပြၚ်သိုၚ်တၟိ ဓရီုကျာ
TimedText
TimedText talk
မဝ်ဂျူ
မဝ်ဂျူ ဓရီုကျာ
Event
Event talk
မဝ်ဂျူ:languages/data/3/l
828
712
392677
385042
2026-04-14T08:02:13Z
Intobesa.bot
1035
Bot: ပလေဝ်ဒါန်
392677
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["laa"] = {
"Lapuyan Subanun",
12635302,
"phi",
}
m["lab"] = {
"Linear A",
nil,
}
m["lac"] = {
"လပ်ခေန်ဒေါန်",
35766,
"myn",
}
m["lad"] = {
"လာဒဳနဝ်",
36196,
"roa-ibe",
"Hebr, Latn, Cyrl",
ancestors = "osp",
}
m["lae"] = {
"Pattani",
7148323,
"sit-whm",
}
m["laf"] = {
"Lafofa",
35711,
"alv",
}
m["lag"] = {
"Langi",
584983,
"bnt-mra",
}
m["lah"] = {
"Lahnda",
1334774,
"inc-pan",
"pa-Arab",
ancestors = "inc-opa",
}
m["lai"] = {
"Lambya",
6481626,
"bnt-mby",
}
m["laj"] = {
"Lango (Uganda)",
35670,
"sdv-los",
"Latn",
}
m["lak"] = {
"Laka",
6474529, -- also Q55616620
"csu-sar", -- formerly classified as "alv-mbm"; see [[w:လိုဝ် Laka language]]
}
m["lam"] = {
"Lamba",
36098,
"bnt-sbi",
"Latn",
}
m["lan"] = {
"Laru",
3913987,
"nic-knj",
"Latn",
}
m["lap"] = {
"Kabba-Laka",
6474528,
"csu-sar",
}
m["laq"] = {
"Qabiao",
3436700,
"qfa-kra",
}
m["lar"] = {
"Larteh",
35639,
"alv-gng",
"Latn",
}
m["las"] = {
"ဂူလာမာ",
35652,
"nic-gne",
"Latn",
}
m["lau"] = {
"Laba",
12952694,
"paa-nha"
}
m["law"] = {
"လိုဝ်je",
6498258,
"poz",
"Latn",
}
m["lax"] = {
"Tiwa",
7810466,
"tbq-bdg",
"Latn",
}
m["lay"] = {
"လာမာ ဗါဲ",
6480756,
"sit-nba",
"Hani, Latn",
sort_key = {Hani = "Hani-sortkey"},
}
m["laz"] = {
"Aribwatsa",
3502104,
"poz-ocw",
"Latn",
}
m["lbb"] = {
"Label",
3214296,
"poz-ocw",
"Latn",
}
m["lbc"] = {
"Lakkia",
3027879,
"qfa-tak",
}
m["lbe"] = {
"လံက်",
36206,
"cau-nec",
"Cyrl, Latn, Arab, Geor",
translit = "lbe-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {
Cyrl = s["cau-Cyrl-entryname"],
Latn = s["cau-Latn-entryname"],
},
sort_key = "lbe-sortkey",
}
m["lbf"] = {
"Tinani",
784502,
"sit-whm",
}
m["lbg"] = {
"Laopang",
12952711,
"tbq-bis",
}
m["lbi"] = {
"La'bi",
6460637,
"alv-mbm",
}
m["lbj"] = {
"လာဒါခဳ",
35833,
"sit-lab",
"Tibt",
translit = "Tibt-translit",
override_translit = true,
display_text = s["Tibt-displaytext"],
entry_name = s["Tibt-entryname"],
sort_key = "Tibt-sortkey",
}
m["lbk"] = {
"ဗန်တံက်ခ် မဇ္ဇျိမ",
63257803,
"phi",
"Latn",
}
m["lbl"] = {
"Libon Bikol",
18664462,
"phi",
"Latn",
}
m["lbm"] = {
"Lodhi",
6666374,
"mun",
}
m["lbn"] = {
"Lamet",
3216723,
"mkh-pal",
}
m["lbo"] = {
"Laven",
6298648,
"mkh-ban",
"Latn",
}
m["lbq"] = {
"Wampar",
7966946,
"poz-ocw",
"Latn",
}
m["lbr"] = {
"Northern Lorung",
6668040,
"sit-kie",
}
m["lbs"] = {
"Libyan Sign Language",
11775688,
"sgn",
}
m["lbt"] = {
"Lachi",
6583606,
"qfa-kra",
}
m["lbu"] = {
"Labu",
6467660,
"poz-ocw",
"Latn",
}
m["lbv"] = {
"Lavatbura-Lamusong",
2405981,
"poz-ocw",
"Latn",
}
m["lbw"] = {
"Tolaki",
3033597,
"poz-btk",
"Latn",
}
m["lbx"] = {
"လာဝါန်ဂါန်",
3120345,
"poz-bre",
"Latn",
}
m["lby"] = {
"Lamu-Lamu",
6482727,
nil,
"Latn",
}
m["lbz"] = {
"Lardil",
3915688,
"aus-tnk",
"Latn",
}
m["lcc"] = {
"Legenyem",
12952713,
"poz-hce",
"Latn",
}
m["lcd"] = {
"Lola",
6668867,
"poz-cet",
"Latn",
}
m["lce"] = {
"Loncong",
3058192,
}
m["lcf"] = {
"Lubu",
3264685,
}
m["lch"] = {
"Luchazi",
3265143,
"bnt-clu",
}
m["lcl"] = {
"Lisela",
6558753,
"poz-cma",
"Latn",
}
m["lcm"] = {
"Tungag",
3542085,
"poz-ocw",
"Latn",
}
m["lcp"] = {
"လဝါန်လ္ပာ်ပလိုတ်",
18644465,
"mkh-pal",
"Thai",
sort_key = "Thai-sortkey",
}
m["lcq"] = {
"Luhu",
6699890,
"poz-cma",
"Latn",
}
m["lcs"] = {
"Lisabata-Nuniali",
6558534,
}
m["lda"] = {
"Kla",
63257856,
"dmn-mda",
"Latn",
}
m["ldb"] = {
"Idun",
3914441,
"nic-plc",
"Latn",
}
m["ldd"] = {
"Luri (Nigeria)",
4701277,
"cdc-wst",
}
m["ldg"] = {
"Lenyima",
3914423,
"nic-uce",
"Latn",
}
m["ldh"] = {
"Lamja-Dengsa-Tola",
11001739,
"nic-dak",
}
m["ldj"] = {
"Lemoro",
3912761,
"nic-jer",
}
m["ldk"] = {
"Leelau",
3914465,
"alv-bwj",
}
m["ldl"] = {
"Kaan",
3914501,
"alv-yun",
}
m["ldm"] = {
"Landoma",
35568,
"alv-mel",
}
m["ldn"] = {
"လေဝ်ဒေန်",
35757,
"art",
"Latn",
type = "appendix-constructed",
}
m["ldo"] = {
"Loo",
3915378,
"alv-bwj",
}
m["ldp"] = {
"Tso",
3913953,
"alv-wjk",
}
m["ldq"] = {
"Lufu",
35796,
"nic-ykb",
"Latn",
}
m["lea"] = {
"Lega-Shabunda",
12952719,
"bnt-lgb",
}
m["leb"] = {
"Lala-Bisa",
6480112,
"bnt-sbi",
}
m["lec"] = {
"Leco",
2625398,
"qfa-iso",
}
m["led"] = {
"Lendu",
523823,
"csu-lnd",
"Latn",
}
m["lee"] = {
"Lyélé",
3089032,
"nic-gnn",
}
m["lef"] = {
"Lelemi",
35585,
"alv-ntg",
}
m["leh"] = {
"Lenje",
6522666,
"bnt-bot",
}
m["lei"] = {
"Lemio",
6521165,
"ngf-mad",
}
m["lej"] = {
"Lengola",
6522474,
"bnt-leb",
}
m["lek"] = {
"Leipon",
3229216,
"poz-aay",
"Latn",
}
m["lel"] = {
"Lele (Congo)",
56733,
"bnt-bsh",
}
m["lem"] = {
"Nomaande",
13479983,
"nic-mbw",
"Latn",
}
m["len"] = {
"Honduran Lenca",
36189,
"nai-len",
"Latn",
}
m["leo"] = {
"Mengisa",
1345684,
"nic-mba",
ancestors = "bag",
}
m["lep"] = {
"လပ်ချာ",
35990,
"sit",
"Lepc",
translit = "lep-translit",
}
m["leq"] = {
"Lembena",
6521067,
"paa-eng",
}
m["ler"] = {
"Lenkau",
3229472,
"poz-aay",
"Latn",
}
m["les"] = {
"Lese",
11033939,
"csu-mle",
}
m["let"] = {
"Lesing-Gelimi",
12635445,
"poz-ocw",
"Latn",
}
m["leu"] = {
"Kara (New Guinea)",
3192889,
"poz-ocw",
"Latn",
}
m["lev"] = {
"Lamma",
6583582,
"ngf",
}
m["lew"] = { -- this code was basically assigned as a catch-all for things that aren't brs, kzf or unz
"Ledo Kaili",
35877,
"poz-kal",
"Latn",
}
m["lex"] = {
"Luang",
6695015,
"poz-tim",
}
m["ley"] = {
"Lemolang",
3033560,
}
m["lez"] = {
"လေပ်သကဳ",
31746,
"cau-esm",
"Cyrl, Latn, Arab",
translit = "lez-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {
Cyrl = s["cau-Cyrl-entryname"],
Latn = s["cau-Latn-entryname"],
},
}
m["lfa"] = {
"Lefa",
35643,
"bnt-baf",
}
m["lfn"] = {
"Lingua Franca Nova",
146803,
"art",
"Latn, Cyrl",
type = "appendix-constructed",
}
m["lga"] = {
"Lungga",
3267590,
"poz-ocw",
"Latn",
}
m["lgb"] = {
"Laghu",
3216169,
"poz-ocw",
"Latn",
}
m["lgg"] = {
"ဋ္ဌူဗါရာ",
3272737,
"csu-mma",
}
m["lgh"] = {
"Laghuu",
6472114,
"tbq-muj",
}
m["lgi"] = {
"Lengilu",
6522465,
"poz-swa",
"Latn",
}
m["lgk"] = {
"Neverver",
3241515,
"poz-vnc",
"Latn",
}
m["lgl"] = {
"Wala",
3565284,
"poz-sls",
}
m["lgm"] = {
"Lega-Mwenga",
14916883,
"bnt-lgb",
}
m["lgn"] = {
"Opuuo",
3354339,
"ssa-kom",
}
m["lgq"] = {
"Logba",
35813,
"alv-ntg",
"Latn",
}
m["lgr"] = {
"Lengo",
3229454,
"poz-sls",
"Latn",
}
m["lgs"] = {
"Guinea-Bissau Sign Language",
5616441,
"sgn",
}
m["lgt"] = {
"Pahi",
7124545,
"paa-spk",
"Latn",
}
m["lgu"] = {
"Longgu",
3259105,
"poz-sls",
}
m["lgz"] = {
"Ligenza",
5531038,
"bnt-bun",
}
m["lha"] = {
"Laha (Vietnam)",
3112363,
"qfa-kra",
}
m["lhh"] = {
"Laha (Indonesia)",
6473107,
"poz-cma",
}
m["lhi"] = {
"Lahu Shi",
25559457,
"tbq-lho",
}
m["lhl"] = {
"Lahul Lohar",
12953672,
}
m["lhn"] = {
"Lahanan",
12953660,
}
m["lhp"] = {
"Lhokpu",
3436603,
"sit-dhi",
}
m["lhs"] = {
"Mlahsö",
3393063,
"sem-cna",
}
m["lht"] = {
"ဠဝ်-တိုဝ်ဂါ",
3257566,
"poz-vnn",
"Latn",
}
m["lhu"] = {
"လာဟူ",
35780,
"tbq-lho",
}
m["lia"] = {
"West-Central Limba",
32867815,
"alv-lim",
}
m["lib"] = {
"Likum",
3240737,
"poz-aay",
"Latn",
}
m["lic"] = {
"လာဲ",
934738,
"qfa-lic",
"Latn",
}
m["lid"] = {
"Nyindrou",
3346666,
"poz-aay",
"Latn",
}
m["lie"] = {
"Likila",
11011614,
"bnt-ngn",
}
m["lif"] = {
"လေန်ၜေါအ်",
56477,
"sit-kir",
"Limb",
translit = "lif-translit",
}
m["lig"] = {
"လေတ်ဗဳ",
33594,
"dmn-jje",
}
m["lih"] = {
"Lihir",
6546938,
"poz-ocw",
"Latn",
}
m["lii"] = {
"Lingkhim",
12635536,
}
m["lij"] = {
"လဳဂူရေဝ်ယာန်",
36106,
"roa-git",
"Latn",
}
m["lik"] = {
"Lika",
1530394,
"bnt-boa",
}
m["lil"] = {
"Lillooet",
34154,
"sal",
}
m["lio"] = {
"Liki",
4261493,
"poz-ocw",
"Latn",
}
m["lip"] = {
"Sekpele",
36257,
"alv-ntg",
}
m["liq"] = {
"Libido",
35691,
"cus-hec",
}
m["lir"] = {
"Liberian Kreyol",
6541128,
"crp",
"Latn",
ancestors = "en",
}
m["lis"] = {
"လဳသေုန်",
56480,
"tbq-lso",
"Lisu, Latn",
translit = {Lisu = "Lisu-translit"},
override_translit = true,
sort_key = {Lisu = s["Lisu-sortkey"]},
}
m["liu"] = {
"Logorik",
6667811,
"sdv-daj",
}
m["liv"] = {
"လဳၜိုနဳယာန်",
33698,
"urj-fin",
"Latn",
entry_name = {
remove_diacritics = "'" .. u(0x2019),
from = {"Ǭ", "ǭ"},
to = {"Ō", "ō"}
},
}
m["liw"] = {
"Col",
2981948,
}
m["lix"] = {
"Liabuku",
13580912,
}
m["liy"] = {
"Banda-Bambari",
11051591,
"bad-cnt",
}
m["liz"] = {
"Libinza",
4914576,
"bnt-zbi",
}
m["lja"] = {
"Golpa",
50934920,
"aus-yol",
"Latn",
}
m["lje"] = {
"Rampi",
7290041,
"poz",
}
m["lji"] = {
"Laiyolo",
6474218,
}
m["ljl"] = {
"Li'o",
2697010,
"poz",
}
m["ljp"] = {
"Lampung Api",
49215,
"poz-lgx",
"Latn",
}
m["ljw"] = {
"Yirandali",
17059380,
}
m["ljx"] = {
"Yuru",
63257867,
}
m["lka"] = {
"Lakalei",
12952700,
"poz-tim",
"Latn",
}
m["lkb"] = {
"Kabras",
63257894,
"bnt-msl",
ancestors = "luy",
}
m["lkc"] = {
"Kucong",
6441572,
"tbq-lho",
}
m["lkd"] = {
"Lakondê",
20527166,
"sai-nmk",
"Latn",
}
m["lke"] = {
"Kenyi",
12952628,
"bnt-nyg",
}
m["lkh"] = {
"Lakha",
56606,
"sit-tib",
}
m["lki"] = {
"လာခှဳ",
56483,
"ku",
"fa-Arab",
translit = "lki-translit",
entry_name = {remove_diacritics = c.kasra .. c.sukun},
}
m["lkj"] = {
"Remun",
7312239,
"poz-mly",
"Latn",
}
m["lkl"] = {
"Laeko-Libuat",
3504331,
"qfa-tor",
}
m["lkm"] = {
"Kalaamaya",
6349988,
}
m["lkn"] = {
"Lakon",
3216494,
"poz-vnn",
"Latn",
}
m["lko"] = {
"Khayo",
6401095,
"bnt-msl",
}
m["lkr"] = {
"Päri",
36487,
"sdv-lon",
}
m["lks"] = {
"Kisa",
63259208,
"bnt-msl",
ancestors = "luy",
}
m["lkt"] = {
"လာဂဝ်တ",
33537,
"sio-dkt",
"Latn",
}
m["lku"] = {
"Kungkari",
6444526,
}
m["lky"] = {
"Lokoya",
56687,
"sdv-lma",
}
m["lla"] = {
"Lala-Roba",
3914878,
"alv-yun",
}
m["llb"] = {
"Lolo",
11006056,
"bnt-mak",
ancestors = "vmw",
}
m["llc"] = {
"လေဝ်လဲန် (ဂေါတ်နဳ)",
6520837,
"dmn-mok",
}
m["lld"] = {
"လာဒေန်",
36202,
"roa-rhe",
"Latn",
}
m["lle"] = {
"Lele (Papua New Guinea)",
3229269,
"poz-aay",
"Latn",
}
m["llf"] = {
"Hermit",
3134240,
"poz-aay",
"Latn",
}
m["llg"] = {
"Lole",
6668883,
"poz-tim",
}
m["llh"] = {
"Lamu",
6482736,
"tbq-lso",
}
m["lli"] = {
"Teke-Laali",
36543,
"bnt-nze",
}
m["llj"] = {
"Ladji-Ladji",
6512694,
"aus-pam",
}
m["llk"] = {
"Lelak",
3229263,
"poz-swa",
"Latn",
}
m["lll"] = {
"Lilau",
6547570,
"qfa-tor",
}
m["llm"] = {
"Lasalimu",
6492774,
}
m["lln"] = {
"Lele (Chad)",
1641493,
"cdc-est",
}
m["llo"] = {
"Khlor",
27921409,
"mkh-kat",
}
m["llp"] = {
"North Efate",
3580152,
"poz-vnc",
"Latn",
}
m["llq"] = {
"Lolak",
12953679,
"phi",
}
m["lls"] = {
"Lithuanian Sign Language",
3915480,
"sgn",
}
m["llu"] = {
"လိုဝ်",
3218574,
"poz-sls",
"Latn",
}
m["llx"] = {
"လိုဝ်an",
35682,
"poz-pcc",
"Latn",
}
m["lma"] = {
"East Limba",
11034212,
"alv-lim",
}
m["lmb"] = {
"Merei",
12952843,
"poz-vnn",
"Latn",
}
m["lmc"] = {
"Limilngan",
6549414,
}
m["lmd"] = {
"Lumun",
35777,
"alv-tal",
}
m["lme"] = {
"Pévé",
56249,
"cdc-mas",
}
m["lmf"] = {
"South Lembata",
7567815,
}
m["lmg"] = {
"Lamogai",
278365,
"poz-ocw",
"Latn",
}
m["lmh"] = {
"Lambichhong",
6481472,
"sit-kie",
ancestors = "ybh",
}
m["lmi"] = {
"Lombi",
11259563,
"csu-maa",
}
m["lmj"] = {
"West Lembata",
6864697,
}
m["lmk"] = {
"Lamkang",
12952703,
"tbq-kuk",
}
m["lml"] = {
"ရာဂါ",
3063193,
"poz-vnn",
"Latn",
}
m["lmn"] = {
"လာမ်ဗါဒဳ",
33474,
"raj",
}
m["lmo"] = {
"လံဗာတ်",
33754,
"roa-git",
"Latn",
}
m["lmp"] = {
"Limbum",
35801,
"nic-nka",
"Latn",
}
m["lmq"] = {
"Lamatuka",
6480982,
}
m["lmr"] = {
"Lamalera",
6480787,
}
m["lmu"] = {
"Lamenu",
740604,
"poz-vnc",
"Latn",
}
m["lmv"] = {
"Lomaiviti",
3130221,
"poz-pcc",
"Latn",
}
m["lmw"] = {
"Lake Miwok",
3216471,
"nai-you",
"Latn",
}
m["lmx"] = {
"Laimbue",
6473933,
"nic-rnw",
}
m["lmy"] = {
"လာဗါဝ်ယျာ",
6481538,
"poz-cet",
"Latn",
sort_key = "lmy-sortkey",
}
m["lmz"] = {
"Lumbee",
12635887,
nil,
"Latn",
}
m["lna"] = {
"Langbashe",
11137550,
"bad",
}
m["lnb"] = {
"Mbalanhu",
12952830,
"bnt-ova",
}
m["lnd"] = {
"ဠုန် ၜအ်ဝါန်",
13479839,
"poz-swa",
"Latn",
}
m["lnh"] = {
"Lanoh",
6487291,
"mkh-asl",
}
m["lni"] = {
"Daantanai'",
5207384,
"paa-sbo",
}
m["lnj"] = {
"Linngithigh",
3915694,
"aus-pmn",
"Latn",
}
m["lnl"] = {
"South Central Banda",
41354532,
"bad",
}
m["lnm"] = {
"Langam",
6485678,
"paa",
"Latn",
}
m["lnn"] = {
"Lorediakarkar",
6680287,
"poz-vnn",
"Latn",
}
m["lno"] = {
"Lango (Sudan)",
223306,
"sdv-lma",
}
m["lns"] = {
"Lamnso'",
35788,
"nic-rng",
}
m["lnu"] = {
"Longuda",
35797,
"alv-bam",
"Latn",
}
m["lnw"] = {
"Lanima",
56825017,
"aus-pam",
"Latn",
}
m["loa"] = {
"ဋ္ဌဝ်ဋ္ဌဝ်ဒါ",
6669025,
"paa-nha",
"Latn",
}
m["lob"] = {
"Lobi",
35807,
}
m["loc"] = {
"Inonhan",
2400870,
"phi",
}
m["lod"] = {
"Berawan",
4891018,
"poz-swa",
"Latn",
}
m["loe"] = {
"သာလောန်",
12953867,
"poz",
}
m["lof"] = {
"Logol",
35779,
"alv-hei",
}
m["log"] = {
"လဝ်ဂဝ်",
2613477,
"csu-mma",
}
m["loh"] = {
"Narim",
56353,
"sdv",
}
m["loi"] = {
"Lomakka",
3913961,
"alv-kul",
}
m["loj"] = {
"ဠူ",
3260104,
"poz-aay",
"Latn",
}
m["lok"] = {
"Loko",
3914912,
"dmn-msw",
"Latn",
}
m["lol"] = {
"Mongo",
112893,
"bnt-mon",
"Latn",
}
m["lom"] = {
"Loma",
35885,
"dmn-msw",
"Latn, Loma"
}
m["lon"] = {
"Malawi Lomwe",
10975286,
}
m["loo"] = {
"Lombo",
11167192,
"bnt-ske",
}
m["lop"] = {
"Lopa",
3914875,
}
m["loq"] = {
"Lobala",
4849710,
"bnt-ngn",
}
m["lor"] = {
"Téén",
36467,
"alv-kul",
}
m["los"] = {
"Loniu",
3259202,
"poz-aay",
"Latn",
}
m["lot"] = {
"Lotuko",
56672,
"sdv-lma",
}
m["lou"] = {
"ပြၚ်သေတ် လူဝဳသဳယျာနာ ခရေဝ်အဝ်",
1185127,
"crp",
"Latn",
ancestors = "fr",
sort_key = s["roa-oil-sortkey"],
}
m["lov"] = {
"Lopi",
12952740,
"tbq-tal",
}
m["low"] = {
"Tampias Lobu",
12953674,
}
m["lox"] = {
"Loun",
6689636,
"poz-cet",
"Latn",
}
m["loz"] = {
"Lozi",
33628,
"bnt-sts",
"Latn",
}
m["lpa"] = {
"Lelepa",
3229273,
"poz-vnc",
"Latn",
}
m["lpe"] = {
"Lepki",
4259152,
"paa-pau",
}
m["lpn"] = {
"Long Phuri Naga",
6673049,
"sit-aao",
}
m["lpo"] = {
"Lipo",
56921,
"tbq-llo",
"Plrd",
}
m["lpx"] = {
"Lopit",
56684,
"sdv-lma",
}
m["lra"] = {
"Rara Bakati'",
3419746,
"day",
}
m["lrc"] = {
"ဠူရဳ လ္ပာ်သၟဝ်ကျာ",
19933293,
"ira-swi",
"fa-Arab",
ancestors = "pal",
}
m["lre"] = {
"လိုဝ်rentian",
1790301,
"iro-nor",
"Latn",
}
m["lrg"] = {
"Laragia",
2591193,
}
m["lri"] = {
"Marachi",
6754565,
"bnt-msl",
}
m["lrk"] = {
"Loarki",
6663513,
}
m["lrl"] = {
"ဠူရဳ",
33468,
"ira-swi",
"fa-Arab",
}
m["lrm"] = {
"Marama",
6325931,
"bnt-msl",
ancestors = "luy",
}
m["lrn"] = {
"Lorang",
6678781,
}
m["lro"] = {
"Laro",
35687,
"alv-hei",
}
m["lrr"] = {
"Southern Lorung",
12952742,
"sit-kie",
}
m["lrt"] = {
"Larantuka Malay",
6488691,
"poz-mly",
"Latn",
}
m["lrv"] = {
"Larëvat",
3217892,
"poz-vnc",
"Latn",
}
m["lrz"] = {
"Lemerig",
2028448,
"poz-vnn",
"Latn",
}
m["lsa"] = {
"လာပ်သဂေဒဳ",
3218296,
"ira-kms",
}
m["lsd"] = {
"လဳယှာနာ ဒေန်နဳ",
3436461,
"sem-nna",
"Hebr",
}
m["lse"] = {
"Lusengo",
6683546,
"bnt-zbi",
}
m["lsh"] = {
"Lish",
6558822,
"sit-khb",
}
m["lsi"] = {
"လာယှဳ",
6493203,
"tbq-brm",
}
m["lsl"] = {
"Latvian Sign Language",
6497414,
"sgn",
}
m["lsm"] = {
"Saamia",
3739441,
"bnt-msl",
}
m["lso"] = {
"Laos Sign Language",
6488022,
"sgn",
}
m["lsp"] = {
"Panamanian Sign Language",
7129968,
"sgn",
}
m["lsr"] = {
"Aruop",
3450566,
"qfa-tor",
}
m["lss"] = {
"Lasi",
12953669,
"inc-snd",
"Arab",
ancestors = "sd",
}
m["lst"] = {
"Trinidad and Tobago Sign Language",
7842495,
"sgn",
}
m["lsy"] = {
"Mauritian Sign Language",
6793754,
"sgn",
}
m["ltc"] = {
"ကြုက်လဒေါဝ်",
2016252,
"zhx",
"Hant, Phag, Tang",
translit = {Hant = "zh-translit"},
sort_key = {Hant = "Hani-sortkey"},
}
m["ltg"] = {
"လပ်ဂါလဳယာန်",
36212,
"bat-eas",
"Latn",
}
m["lti"] = {
"Leti",
3236912,
"poz-tim",
"Latn",
}
m["ltn"] = {
"Latundê",
63259736,
"sai-nmk",
"Latn",
}
m["lto"] = {
"Olutsotso",
63259915,
"bnt-msl",
ancestors = "luy",
}
m["lts"] = {
"Lutachoni",
63283459,
"bnt-msl",
}
m["ltu"] = {
"Latu",
6497181,
"poz-cma",
}
m["lua"] = {
"Luba-Kasai",
34173,
"bnt-lub",
"Latn",
}
m["luc"] = {
"Aringa",
56556,
"csu-mma",
}
m["lud"] = {
"ဠူဒဳယာန်",
33918,
"urj-fin",
"Latn",
}
m["lue"] = {
"Luvale",
33597,
"bnt-clu",
"Latn",
}
m["luf"] = {
"လိုဝ်a",
6497673,
}
m["luh"] = {
"မေန် လာယ်ဂျို",
1988433,
"zhx-nan",
"Hants",
generate_forms = "zh-generateforms",
sort_key = "Hani-sortkey",
}
m["lui"] = {
"ဠဝ်သဳသာန်ညဝ်",
56236,
"azc-cup",
"Latn",
entry_name = {remove_diacritics = c.acute .. c.circ},
}
m["luj"] = {
"Luna",
11003832,
"bnt-lbn",
}
m["luk"] = {
"Lunanakha",
56446,
"sit-tib",
"Tibt",
ancestors = "dz",
translit = "Tibt-translit",
override_translit = true,
display_text = s["Tibt-displaytext"],
entry_name = s["Tibt-entryname"],
sort_key = "Tibt-sortkey",
}
m["lul"] = {
"Olu'bo",
6589401,
"csu-mma",
}
m["lum"] = {
"Luimbi",
10963134,
"bnt-clu",
}
m["lun"] = {
"Lunda",
33607,
"bnt-lun",
"Latn",
}
m["luo"] = {
"ဠူအဝ်",
5414796,
"sdv-los",
"Latn",
}
m["lup"] = {
"Lumbu",
35793,
"bnt-sir",
}
m["luq"] = {
"Lucumí",
1768321,
"alv-yor",
"Latn",
ancestors = "yo",
sort_key = {
remove_diacritics = c.acute,
},
}
m["lur"] = {
"လိုဝ်ra",
2984540,
}
m["lus"] = {
"မဳသုဝ်",
36147,
"tbq-kuk",
"Latn",
}
m["lut"] = {
"ဠူသၠာ်သဳ",
33658,
"sal",
"Latn",
}
m["luu"] = {
"Lumba-Yakkha",
6703050,
"sit-kie",
ancestors = "ybh",
}
m["luv"] = {
"လူဝါတဳ",
33402,
"inc-snd",
"Khoj",
}
m["luy"] = {
"ဠူယျာ",
35893,
"bnt-msl",
"Latn",
}
m["luz"] = {
"ဠူရဳ လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
12952748,
"ira-swi",
"fa-Arab",
ancestors = "pal",
}
m["lva"] = {
"Maku'a",
35790,
"poz-tim",
}
m["lvi"] = {
"Lawi",
6502657,
"mkh-ban",
"Latn",
}
m["lvk"] = {
"Lavukaleve",
770547,
"paa",
"Latn",
}
m["lvl"] = {
"Lwel",
93936908,
"bnt-bdz",
"Latn",
}
m["lvu"] = {
"Levuka",
6535860,
}
m["lwa"] = {
"Lwalu",
6706953,
"bnt-lbn",
}
m["lwe"] = {
"Lewo Eleng",
6537465,
}
m["lwg"] = {
"Wanga",
nil,
"bnt-msl",
ancestors = "luy",
}
m["lwh"] = {
"White Lachi",
8842956,
"qfa-kra",
}
m["lwl"] = {
"လဝါန်လ္ပာ်ဖာဗၟံက်",
18644464,
"mkh-pal",
"Thai",
sort_key = "Thai-sortkey",
}
m["lwm"] = {
"Laomian",
19597674,
"tbq-bis",
}
m["lwo"] = {
"Luwo",
56362,
"sdv-lon",
"Latn",
}
m["lws"] = {
"Malawian Sign Language",
47522462,
"sgn",
}
m["lwt"] = {
"Lewotobi",
14916885,
}
m["lwu"] = {
"Lawu",
6505073,
"tbq-lwo",
}
m["lww"] = {
"Lewo",
3237321,
"poz-vnc",
"Latn",
}
m["lya"] = {
"Layakha",
56602,
"sit-tib",
"Tibt",
ancestors = "dz",
translit = "Tibt-translit",
override_translit = true,
display_text = s["Tibt-displaytext"],
entry_name = s["Tibt-entryname"],
sort_key = "Tibt-sortkey",
}
m["lyg"] = {
"Lyngngam",
12635902,
"aav-pkl",
}
m["lyn"] = {
"Luyana",
3268098,
}
m["lzh"] = {
"လိက်ပတ်ကြုက်",
37041,
"zhx",
"Hant",
wikimedia_codes = "zh-classical",
translit = "zh-translit",
sort_key = "Hani-sortkey",
}
m["lzl"] = {
"Litzlitz",
6653424,
"poz-vnc",
"Latn",
}
m["lzn"] = {
"Leinong Naga",
5924455,
"sit-kch",
}
m["lzz"] = {
"လာတ်",
1160372,
"ccs-zan",
"Geor, Latn",
translit = {Geor = "lzz-translit"},
override_translit = true,
entry_name = {remove_diacritics = c.grave .. c.acute .. c.circ},
}
return require("Module:languages").finalizeData(m, "language")
5y81shw8pi95aww0hpoq1did7tawmpw
ထာမ်ပလိက်:attention
10
1105
392692
152567
2026-04-14T08:51:45Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[ထာမ်ပလိက်:attn]] ဇရေင် [[ထာမ်ပလိက်:attention]] နကု မကလေင်ပညုင်
152567
wikitext
text/x-wiki
<includeonly>{{#invoke:attention|show}}</includeonly><!--
--><noinclude>{{documentation}}</noinclude>
hq0ehxqdxrmpfumst8gymc6zvvuouoj
หมัน
0
7693
392676
14531
2026-04-13T23:53:30Z
Apisite
133
392676
wikitext
text/x-wiki
{{also|หมั้น|หมื่น|หมุน}}
=={{=th=}}==
===ဗွဟ်ရမ္သာင်===
{{th-pron|หฺมัน}}
===နာမ်===
{{th-noun}}
# [[ခတန်]]
===နာမဝိသေသန===
{{head|th|နာမဝိသေသန}}
dbo52ihp86axt23w3631jvttmjb2gve
392716
392676
2026-04-14T09:48:44Z
咽頭べさ
33
392716
wikitext
text/x-wiki
{{also|หมั้น|หมื่น|หมุน}}
=={{=th=}}==
===ဗွဟ်ရမ္သာင်===
{{th-pron|หฺมัน}}
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|th|tai-pro|*ʰmanᴬ}}
====နာမဝိသေသန====
{{th-adj}}
# မဆက်ၜံၚ်မဇဟွံမာန်၊ မဆက်ၜံၚ်အဆက်ကောန်ဇာတ်ဟွံမာန်၊ မဆက်ၜံၚ်ကောန်ဇာတ်ဟွံမာန်။
====နာမ်====
{{th-noun}}
# ဒတန်။
1075caoesz6u11tegsx7z602dkyy8jl
392717
392716
2026-04-14T09:49:46Z
咽頭べさ
33
392717
wikitext
text/x-wiki
{{also|หมั้น|หมื่น|หมุน}}
=={{=th=}}==
===ဗွဟ်ရမ္သာင်===
{{th-pron|หฺมัน}}
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|th|tai-pro|*ʰmanᴬ}}
====နာမဝိသေသန====
{{th-adj|-}}
# မဆက်ၜံၚ်မဇဟွံမာန်၊ မဆက်ၜံၚ်အဆက်ကောန်ဇာတ်ဟွံမာန်၊ မဆက်ၜံၚ်ကောန်ဇာတ်ဟွံမာန်။
====နာမ်====
{{th-noun}}
# ဒတန်။
psoq30dcy5yvpd3ls8frgd5hhsf1eh4
မဝ်ဂျူ:bo-pron
828
9886
392683
293267
2026-04-14T08:29:20Z
咽頭べさ
33
392683
Scribunto
text/plain
local export = {}
local gsub = mw.ustring.gsub
local match = mw.ustring.match
function export.tidyRom(text)
text = gsub(text, "([fhvw])(.?)", function(a, b) if b == "-" or b == "" or b == " " or b == "," then return "<sup>"..a.."</sup>"..b end end)
return text
end
local iConv = {
["b"] = "p", ["p"] = "pʰ", ["bb"] = "b",
["d"] = "t", ["t"] = "tʰ", ["dd"] = "d",
["gy"] = "c", ["ky"] = "cʰ", ["ghy"] = "ɟ",
["g"] = "k", ["k"] = "kʰ", ["gg"] = "g",
["z"] = "t͡s", ["c"] = "t͡sʰ", ["zz"] = "d͡z",
["zh"] = "ʈ͡ʂ", ["ch"] = "ʈ͡ʂʰ", ["dh"] = "ɖ͡ʐ",
["j"] = "t͡ɕ", ["q"] = "t͡ɕʰ", ["jj"] = "d͡ʑ",
["m"] = "m", ["n"] = "n", ["ny"] = "ȵ", ["ng"] = "ŋ",
["mh"] = "m̥", ["ngh"] = "ŋ̊", --limited
["l"] = "l", ["lh"] = "ɬ",
["f"] = "f", ["s"] = "s", ["h"] = "h",
["sh"] = "ʂ", ["x"] = "ɕ", ["hy"] = "ç",
["r"] = "ʐ",
["w"] = "w", ["y"] = "j",
[""] = "ʔ",
}
local fConv = {
["i"] = "i", ["e"] = "e", ["a"] = "a", ["ac"] = "ə", ["o"] = "o", ["u"] = "u",
["ii"] = "iː", ["ee"] = "eː", ["aa"] = "aː", ["acc"] = "əː", ["oo"] = "oː", ["uu"] = "uː",
["ae"] = "ɛː", ["oe"] = "øː", ["ue"] = "yː", ["ie"] = "ɪː", ["uo"] = "ʊː",
["iu"] = "iu", ["eu"] = "eu", ["acu"] = "əu",
["ao"] = "ao", ["ua"] = "ua", ["ei"] = "ei", ["io"] = "io",
["im"] = "im", ["em"] = "em", ["am"] = "am", ["acm"] = "əm", ["om"] = "om", ["um"] = "um",
["in"] = "ĩ", ["en"] = "ẽ", ["an"] = "an", ["on"] = "on", ["un"] = "un",
["aen"] = "ɛ̃", ["oen"] = "ø̃", ["uen"] = "ỹ",
["ing"] = "iŋ", ["eng"] = "eŋ", ["ang"] = "aŋ", ["acng"] = "əŋ", ["ong"] = "oŋ", ["ung"] = "uŋ",
["ib"] = "ip̚", ["eb"] = "ep̚", ["ab"] = "ap̚", ["acb"] = "əp̚", ["ob"] = "op̚", ["ub"] = "up̚",
["ig"] = "i(k̚)ˀ", ["eg"] = "e(k̚)ˀ", ["acg"] = "ə(k̚)ˀ", ["ag"] = "a(k̚)ˀ", ["og"] = "o(k̚)ˀ", ["ug"] = "u(k̚)ˀ",
["ir"] = "iː(ɹ)", ["er"] = "eː(ɹ)", ["ar"] = "aː(ɹ)", ["or"] = "oː(ɹ)", ["ur"] = "uː(ɹ)",
}
local tConv = {
["f"] = "˥˥",
["h"] = "˥˨",
["v"] = "˩˨",
["w"] = "˩˧˨",
[""] = "ˑ",
}
function export.ipa(text)
text = mw.ustring.lower(text)
for word in mw.ustring.gmatch(text, "([a-z]+)") do
local originalWord = word
word = gsub(word, "^([^aeiou]*)([aeiou][aeioucmnbgr]*)([fhvw]?)$", function(initial, final, tone)
return (iConv[initial] or initial) .. (fConv[final] or final) .. tConv[tone] end)
text = gsub(text, originalWord, word, 1)
end
text = gsub(text, "-", ".")
return text
end
function ipaFormat(word, no_intro)
local part = mw.text.split(word, ",")
return (no_intro and "" or "[[Wiktionary:International Phonetic Alphabet|IPA]]<sup>([[Appendix:Tibetan pronunciation|key]])</sup>: ") ..
'<span class=\"IPA\">/' .. table.concat(part, "/, /") .. '/</span>'
end
function export.show(frame)
local args = frame:getParent().args
local p, ipa, textShow, textHide = {}, {}, "", ""
if args["otb"] ~= "-" then
local otb_ipa = {}
local lang = require("Module:languages").getByCode("bo")
local page_title = lang:transliterate(args["word"] or mw.loadData("Module:headword/data").pagename)
if page_title then
local single_letter = {
["kh"] = "ġ", ["ch"] = "ċ", ["th"] = "ṫ", ["ph"] = "ṗ",
["ng"] = "ŋ", ["ny"] = "ñ",
["ts"] = "ʒ", ["dz"] = "ž",
["zh"] = "ż", ["sh"] = "ṡ"
}
local voiceless_lateral = {
["lh"] = "ĺ", ["hr"] = "ŕ"
}
local function voice(text)
return match(text, "[kġcċtṫpṗʒǯṡshĺŕ]") and "voiceless" or "voiced"
end
local base_ipa = {
["g"] = "ɡ", ["ġ"] = "kʰ",
["c"] = "t͡ɕ", ["ċ"] = "t͡ɕʰ", ["j"] = "d͡ʑ", ["ñ"] = "ȵ",
["ṫ"] = "tʰ",
["ṗ"] = "pʰ",
["ʒ"] = "t͡s", ["ǯ"] = "t͡sʰ", ["ž"] = "d͡z",
["ż"] = "ʑ", ["'"] = "ɣ",
["y"] = "j",
["ṡ"] = "ɕ",
["ĺ"] = "l̥", ["ŕ"] = "r̥"
}
local syllable_structure = "^(b?)([dkgbmz'srl]?)(%.?)([kġgŋcċjñtṫdnpṗbmʒǯžwżz'yrlṡshĺŕʔ])([yr]?)(w?)([aeiouI])([gdbŋnms'rl]?)([sd]?)$"
local voicing = { ["s"] = "z" }
local devoicing = { ["b"] = "p", ["d"] = "t", ["g"] = "k" }
local function initial_process(prefix, superscript, base)
local prenasal = { ["kġgŋ"] = "ᵑ", ["cċjñtṫdnʒǯžwżz'yrlṡshĺŕʔ"] = "ⁿ", ["pṗbm"] = "ᵐ" }
if superscript == "'" then
for ensuing, nasal in pairs(prenasal) do
superscript = match(base, "[" .. ensuing .. "]") and nasal or superscript
end
end
return gsub(prefix .. superscript, ".", (voice(base) == "voiced" and voicing or devoicing)) .. (base_ipa[base] or base)
end
local function vowel_process(glide_a, glide_b, vowel, sep)
local glide_ipa = { ["y"] = "ʲ", ["w"] = "ʷ" }
local glide_sep_ipa = { ["y"] = "j", ["w"] = "ʷ" }
local vowel_ipa = { ["I"] = "ᵻ" }
return gsub(gsub(glide_a .. glide_b, ".", sep ~= "." and glide_ipa or glide_sep_ipa), "rʷ", "ʷr") .. gsub(vowel, ".", vowel_ipa)
end
local function coda_process(coda, suffix)
coda = gsub(coda, "'", "(ɣ)")
return (devoicing[coda] or coda) .. suffix
end
page_title = gsub(page_title, "tsh", "ǯ")
for original, replaced in pairs(single_letter) do
page_title = gsub(page_title, original, replaced)
end
page_title = gsub(page_title, "[lh][hr]", voiceless_lateral)
for syllable in mw.text.gsplit(page_title, " ") do
syllable = gsub(syllable, "^([aeiouI])", "ʔ%1")
if match(syllable, syllable_structure) then
syllable = gsub(syllable, syllable_structure, function(prefix, superscript, sep, base, glide_a, glide_b, vowel, coda, suffix)
if match(base, "[yrw]") and glide_a .. glide_b == "" and prefix .. superscript ~= "" then
glide_a, glide_b = match(base, "[yr]") or "", match(base, "w") or ""
base = prefix .. superscript
prefix, superscript = "", ""
end
return
initial_process(prefix, superscript, base) ..
vowel_process(glide_a, glide_b, vowel, sep) ..
coda_process(coda, suffix)
end)
table.insert(otb_ipa, syllable)
else
erroneous = true
break
end
end
textShow = textShow .. "\n* [[w:Old Tibetan|Old Tibetan]]: " .. ipaFormat("*" .. table.concat(otb_ipa, "."), true)
textHide = textHide .. (not erroneous and "* [[w:Old Tibetan|Old Tibetan]]:\n** " .. ipaFormat("*" .. table.concat(otb_ipa, ".")) .. " <span style=\"font-size:80%\">(reconstructed)</span>" or "")
end
end
if args[1] then
for index, item in ipairs(args) do
table.insert(p, (item ~= "") and item or nil)
end
for _, transcription in ipairs(p) do
table.insert(ipa, export.ipa(transcription))
end
textShow = textShow .. "\n* [[w:Standard Tibetan|Lhasa]]: " .. ipaFormat(table.concat(ipa, ","), true)
textHide = textHide .. "\n* [[w:Central Tibetan language|Ü-Tsang]]" ..
"\n** [[w:Tibetan pinyin|Tibetan pinyin]]: <span style=\"font-family:monospace;\" class=\"tr\">" .. export.tidyRom(table.concat(p, ", ")) .. "</span>" ..
"\n** (''[[w:Standard Tibetan|Lhasa]]'') " .. ipaFormat(table.concat(ipa, ","))
end
if args["batang"] or args["dege"] then
textHide = textHide .. "\n* [[w:Khams Tibetan|Khams]]"
if args["batang"] then
textShow = textShow .. "\n* [[w:Batang County|Batang]]: " .. ipaFormat(args["batang"], true)
textHide = textHide .. "\n** (''[[w:Batang County|Batang]]'') " .. ipaFormat(args["batang"])
end
if args["dege"] then
textShow = textShow .. "\n* [[w:Dêgê County|Dêgê]]: " .. ipaFormat(args["dege"], true)
textHide = textHide .. "\n** (''[[w:Dêgê County|Dêgê]]'') " .. ipaFormat(args["dege"])
end
if args["gyaitang"] then
textShow = textShow .. "\n* [[w:Jiantang|Gyaitang]]: " .. ipaFormat(args["gyaitang"], true)
textHide = textHide .. "\n** (''[[w:Jiantang|Gyaitang]]'') " .. ipaFormat(args["gyaitang"])
end
end
if args["zeku"] or args["labrang"] or args["arik"] or args["maqu"] or args["mdungnag"] then
textHide = textHide .. "\n* [[w:Amdo Tibetan|Amdo]]"
if args["zeku"] then
textShow = textShow .. "\n* [[w:Zêkog County|Zêkog]]: " .. ipaFormat(args["zeku"], true)
textHide = textHide .. "\n** (''[[w:Zêkog County|Zêkog]]'') " .. ipaFormat(args["zeku"])
end
if args["labrang"] then
textShow = textShow .. "\n* [[w:Xiahe County|Bla-Brang]]: " .. ipaFormat(args["labrang"], true)
textHide = textHide .. "\n** (''[[w:Xiahe County|Bla-Brang]]'') " .. ipaFormat(args["labrang"])
end
if args["arik"] then
textShow = textShow .. "\n* [[w:Qilian County|Arik]]: " .. ipaFormat(args["arik"], true)
textHide = textHide .. "\n** (''[[w:Qilian County|Arik]]'') " .. ipaFormat(args["arik"])
end
if args["maqu"] then
textShow = textShow .. "\n* [[w:Maqu County|Maqu]]: " .. ipaFormat(args["maqu"], true)
textHide = textHide .. "\n** (''[[w:Maqu County|Maqu]]'') " .. ipaFormat(args["maqu"])
end
if args["aba"] then
textShow = textShow .. "\n* [[w:Ngawa County|Ngawa]]: " .. ipaFormat(args["aba"], true)
textHide = textHide .. "\n** (''[[w:Ngawa County|Ngawa]]'') " .. ipaFormat(args["aba"])
end
if args["mdungnag"] then
textShow = textShow .. "\n* [[w:Sunan Yugur Autonomous County|Mdung-Nag]]: " .. ipaFormat(args["mdungnag"], true)
textHide = textHide .. "\n** (''[[w:Sunan Yugur Autonomous County|Mdung-Nag]]'') " .. ipaFormat(args["mdungnag"])
end
end
if args["spiti"] then
textShow = textShow .. "\n* [[w:Lahuli–Spiti language|Lahuli–Spiti]]: " .. ipaFormat(args["spiti"], true)
textHide = textHide .. "\n* [[w:Lahuli–Spiti language|Lahuli–Spiti]]"
textHide = textHide .. "\n** (''[[w:Lahaul and Spiti district|Spiti]]'') " .. ipaFormat(args["spiti"])
end
return '<div class="standard-box mw-collapsible mw-collapsed" style="max-width:400px; font-size:100%">' .. textShow ..
'\n<div class="mw-collapsible-content">\n----\n' .. textHide .. '</div></div>'
end
return export
jw9753ym4ebkayb8h80vhiu1urwjdum
အဆက်လက္ကရဴ:ယူနဳကုဒ်/တိဗိတ်
100
9895
392681
17925
2026-04-14T08:22:10Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[အဆက်လက္ကရဴ:ယူနဳကုဒ်/တဳဗဝ်]] ဇရေင် [[အဆက်လက္ကရဴ:ယူနဳကုဒ်/တိဗိတ်]] သီုကဵု ဟွံဂွံ ဂိုင်စွံလဝ် မကလေင်ပညုင်
17925
wikitext
text/x-wiki
{{#invoke:character list|show_header|block=တဳဗဝ်}}
{{#invoke:character list|show|block=တဳဗဝ်}}
[[en:Appendix:Unicode/Tibetan]]
op9t8bk53bu5zxsnv48038h0je7uvsk
392682
392681
2026-04-14T08:22:44Z
咽頭べさ
33
392682
wikitext
text/x-wiki
{{Unicode character list header}}
{{Unicode character list}}
ttzawwpka9qk1qjw50j3ep2eaqycaqw
ཉ
0
9993
392673
17757
2026-04-13T23:37:24Z
Apisite
133
/* တဳဗဝ် */
392673
wikitext
text/x-wiki
{{character info}}
==တဳဗဝ်==
===အက္ခရ်===
{{head|bo|အက္ခရ်}}
===နာမ်===
{{bo-noun}}
# [[က]]။
frnnd0jq9egsohlmv5nnn26443e6h57
392674
392673
2026-04-13T23:38:53Z
Apisite
133
/* တဳဗဝ် */
392674
wikitext
text/x-wiki
{{character info}}
==တဳဗဝ်==
===အက္ခရ်===
{{head|bo|အက္ခရ်}}
===နာမ်===
{{bo-noun}}
# [[က]]၊ ကအရံၚ်။
mn1b5pv92q7zbpqyzhqlzbrcsm4m4to
392680
392674
2026-04-14T08:13:54Z
咽頭べさ
33
392680
wikitext
text/x-wiki
{{character info}}
==မအရေဝ်ပံၚ်ကောံ==
===အက္ခရ်===
{{mul-letter|sc=Tibt}}
# ဗျဉ်တဳဗဝ်မအခဝ် ''ည''။
==ဗဝ်လ်တဳ==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|bft|/ɲə/|[ɲʌ]}}
===အက္ခရ်===
{{head|bft|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ကဵုစှ်မွဲနကဵုအက္ခရ်ဗဝ်လ်တဳ၊ မချူပ္ဍဲဆေၚ်စပ်ကဵုအက္ခရ်တဳဗဝ်။
==သောၚ်ခါ==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|dz|[ɲɑ˥]}}{{attn|dz|add /ɲ/ (and /˥/?) to phonemes}}
====အက္ခရ်====
{{head|dz|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ကဵုထပှ်ဝါနကဵုအက္ခရ်သောၚ်ခါ။
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|dz|sit-pro|*s-ŋja}}
===နာမ်===
{{head|dz|noun}}
# [[က]]။
==ခူတာတ်==
[[Image:Brown Trout 19 10 08.JPG|thumb|{{lang|xkz|ཉ་}}]]
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|xkz|sit-pro|*s-ŋja}}
===ဗွဟ်ရမ္သာၚ်===
* {{xkz-IPA}}
===နာမ်===
{{head|xkz|noun}}
# [[က]]။
==လာဒါခဳ==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|lbj|/ɲə/|[ɲə]}}
===အက္ခရ်===
{{head|lbj|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ဒ္စာံနကဵုအက္ခရ်လာဒါခဳ။
==သှေပါ==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|xsr|/ɲa/|[ɲa]}}
====အက္ခရ်====
{{head|xsr|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ကဵုစှ်ပန်နကဵုအက္ခရ်သှေပါ၊ မချူပ္ဍဲဆေၚ်စပ်ကဵုအက္ခရ်တဳဗဝ်။
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|xsr|sit-pro|*s-ŋja}}
===နာမ်===
{{head|xsr|noun}}
# [[က]]။
==သေတ်ကဳမဳသ်==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|sip|/ɲɐ/|[ɲɐ]}}
====အက္ခရ်====
{{head|sip|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ဒ္စာံနကဵုအက္ခရ်သေတ်ကဳမဳသ်။
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|sip|sit-pro|*s-ŋja}}
===နာမ်===
{{head|sip|noun}}
# [[က]]။
===နာမ် ၂===
{{head|sip|noun}}
# ကတေၚ်ဇၞော်၊ ကတေၚ်။
==တဳဗဝ်==
===ဗွဟ်ရမ္သာၚ်===
{{bo-IPA|nyaf}}
====အက္ခရ်====
{{head|bo|အက္ခရ်}}
# မဆေၚ်စပ်ကဵုအက္ခရ်မရနုက်ဒ္စာံနကဵုအက္ခရ်တဳဗဝ်။
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|bo|sit-pro|*s-ŋja}}
===ဗွဟ်ရမ္သာၚ်===
{{bo-IPA|nyav|batang=ȵa˨˧˩|dege=ȵa˩˧|zeku=ȵa|labrang=ȵa|arik=ȵæ}}
===နာမ်===
{{head|bo|noun}}
# [[က]]။
3uu4lsd2wbw0hbt7hksxnph0w3ue59t
မဝ်ဂျူ:de-noun
828
16685
392617
301510
2026-04-13T13:21:09Z
咽頭べさ
33
392617
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, cattype .. "ဂျာမာန်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်ဂမၠိုၚ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
lrhf313gddjk0w9jefoqnkk8kh47hmg
392618
392617
2026-04-13T13:23:29Z
咽頭べさ
33
392618
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, cattype .. "ဂျာမာန်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot("langname", decldescs)
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်ဂမၠိုၚ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
mnihw9l2zyjx960vue7ki4azj2wje55
392622
392618
2026-04-13T13:36:55Z
咽頭べさ
33
392622
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("မပံၚ်ဖနှဴလဝ်~")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
rzv5k67ak8xpkm6gkyangmmy8qe83tf
392623
392622
2026-04-13T13:41:09Z
咽頭べさ
33
392623
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
k64kjk6nttys744nvrdh9h75k7o5szl
392624
392623
2026-04-13T13:45:54Z
咽頭べさ
33
392624
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, alternant_multiword_spec.pos, "~")
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot("surname", decldescs)
elseif base.props.toponym then
m_table.insertIfNot("toponym", decldescs)
elseif base.props.langname then
m_table.insertIfNot("langname", decldescs)
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
fnuwt4b1qkkf2ww1s9fbwj5n8jbfivt
392625
392624
2026-04-13T13:46:40Z
咽頭べさ
33
ကလေင်ပလီု မူတၟိ[[Special:Diff/392624|392624]]နကု[[Special:Contributions/咽頭べさ|咽頭べさ]] ([[User talk:咽頭べさ|ဓရီုကျာ]])
392625
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
k64kjk6nttys744nvrdh9h75k7o5szl
392626
392625
2026-04-13T13:54:28Z
咽頭べさ
33
392626
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(cattype, "ဂျာမာန်" .. alternant_multiword_spec.categories .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
bvi9pp5tn43k0fjthc9jjn4o0u1kxma
392627
392626
2026-04-13T13:55:05Z
咽頭べさ
33
ကလေင်ပလီု မူတၟိ[[Special:Diff/392626|392626]]နကု[[Special:Contributions/咽頭べさ|咽頭べさ]] ([[User talk:咽頭べさ|ဓရီုကျာ]])
392627
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "ဂမၠိုၚ်")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
k64kjk6nttys744nvrdh9h75k7o5szl
392628
392627
2026-04-13T13:58:40Z
咽頭べさ
33
392628
Scribunto
text/plain
local export = {}
--[=[
Authorship: <benwing2>
]=]
--[=[
TERMINOLOGY:
-- "slot" = A particular combination of case/number.
Example slot names for nouns are "voc_s" (vocative singular) and
"gen_p" (genitive plural). Each slot is filled with zero or more forms.
-- "form" = The declined German form representing the value of a given slot.
-- "lemma" = The dictionary form of a given German term. Generally the nominative
masculine singular, but may occasionally be another form if the nominative
masculine singular is missing.
]=]
--[=[
FIXME:
1. Qualifiers in genders should appear as footnotes on the articles.
2. Support notation like <g:f> on feminine/diminutive/masculine, e.g. used for [[Gespons]] (neuter with the meaning
"wife", masculine with the meaning "husband").
3. Fix CSS gender-specific class in table.
4. Support adjectival nouns and adjective-noun combinations. (DONE)
5. Allow period and comma in forms e.g. for [[Eigent.-Whg.]], [[Eigt.-Whg.]] (using a backslash). (DONE)
6. Allow embedded links in genitive/plural/feminine/diminutive/masculine specs, e.g. 'f=![[weiblich]]er Geschäftspartner'.
7. Add 'prop' indicator to indicate proper nouns and suppress the indefinite article.
8. Add 'surname' indicator to indicate surnames, decline appropriately and include both masc and fem variants in the table. (DONE)
9. Add 'langname' indicator to indicate langnames and decline appropriately with its own table with two alternatives. (DONE)
]=]
local lang = require("Module:languages").getByCode("de")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local com = require("Module:de-common")
local pretend_from_headword = false -- may be set during debugging
local force_cat = false -- may be set during debugging
local u = m_str_utils.char
local rfind = m_str_utils.find
local rmatch = m_str_utils.match
local rsubn = m_str_utils.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = m_str_utils.sub
local SUB_ESCAPED_PERIOD = u(0xFFF0)
local SUB_ESCAPED_COMMA = u(0xFFF1)
local archaic_dative_note = "[now rare, [[Wiktionary:German entry guidelines#Dative_singular_-e_in_noun_declension|see notes]]]"
-- version of rsubn() that discards all but the first return value
local function rsub(term, foo, bar)
local retval = rsubn(term, foo, bar)
return retval
end
local function track(page)
require("Module:debug").track("de-noun/" .. page)
return true
end
local states = { "str", "wk", "mix" }
local definitenesses = { "ind", "def" }
local cases_with_abl_voc = { "nom", "gen", "dat", "acc", "abl", "voc" }
local basic_cases = { "nom", "gen", "dat", "acc" }
local numbers = { "s", "p" }
local gender_spec_to_full_gender = {
m = "masculine",
f = "feminine",
n = "neuter",
}
local case_set_with_abl_voc = m_table.listToSet(cases_with_abl_voc)
local function add_equiv(slot_list)
table.insert(slot_list, {"m_equiv", "-"}) -- masculine equivalent of a feminine or neuter noun
table.insert(slot_list, {"f_equiv", "-"}) -- feminine equivalent of a masculine or neuter noun
table.insert(slot_list, {"n_equiv", "-"}) -- neuter equivalent of a masculine or feminine noun
end
-- Construct noun slots.
local noun_slot_list = {}
add_equiv(noun_slot_list)
local noun_slot_set = {}
for _, number in ipairs(numbers) do
for _, case in ipairs(number == "s" and cases_with_abl_voc or basic_cases) do
local slot = case .. "_" .. number
local accel = case .. "|" .. number
table.insert(noun_slot_list, {slot, accel})
noun_slot_set[slot] = true
end
end
-- Construct noun surname slots.
local surname_slot_list = {
}
local surname_slot_set = {}
local surname_endings = {
{"m_s", "m|s"},
{"f_s", "f|s"},
{"p", "p"},
}
for _, case in ipairs(basic_cases) do
for _, ending_and_accel in ipairs(surname_endings) do
local ending, ending_accel = unpack(ending_and_accel)
local slot = case .. "_" .. ending
local accel = case .. "|" .. ending_accel
table.insert(surname_slot_list, {slot, accel})
surname_slot_set[slot] = true
end
end
-- Construct noun langname slots.
local langname_slot_list = {
}
local langname_slot_set = {}
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
for _, is_alt in ipairs { false, true } do
local slot = case .. "_" .. number .. (is_alt and "_alt" or "")
-- FIXME: We should add accelerators for the alternative forms, but this requires hacking the accelerator
-- code in [[Module:inflection utilities]] to specify the alternative lemma; e.g. genitive singular
-- ''Deutschen'' needs to have lemma [[Deutsche]] not [[Deutsch]].
local accel = is_alt and "-" or case .. "|" .. number
table.insert(langname_slot_list, {slot, accel})
langname_slot_set[slot] = true
end
end
end
-- Construct adjectival slots.
local adjectival_slot_list = {}
add_equiv(adjectival_slot_list)
local adjectival_slot_set = {}
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
for _, number in ipairs(numbers) do
local slot = state .. "_" .. case .. "_" .. number
local accel = state .. "|" .. case .. "|" .. number
table.insert(adjectival_slot_list, {slot, accel})
adjectival_slot_set[slot] = true
end
end
end
-- Construct expanded slot lists including linked variants.
local noun_slot_list_with_linked = m_table.shallowCopy(noun_slot_list)
table.insert(noun_slot_list_with_linked, {"nom_s_linked", "nom|s"})
table.insert(noun_slot_list_with_linked, {"nom_p_linked", "nom|p"})
local surname_slot_list_with_linked = m_table.shallowCopy(surname_slot_list)
table.insert(surname_slot_list_with_linked, {"nom_m_s_linked", "nom|m|s"})
local langname_slot_list_with_linked = m_table.shallowCopy(langname_slot_list)
table.insert(langname_slot_list_with_linked, {"nom_s_linked", "nom|s"})
local adjectival_slot_list_with_linked = m_table.shallowCopy(adjectival_slot_list)
table.insert(adjectival_slot_list_with_linked, {"str_nom_s_linked", "str|nom|s"})
table.insert(adjectival_slot_list_with_linked, {"str_nom_p_linked", "str|nom|p"})
-- Construct expanded slot lists including linked variants and articles.
local function add_slot_articles(slot_list, cases, numbers)
for _, case in ipairs(cases) do
for _, number in ipairs(numbers) do
for _, def in ipairs(definitenesses) do
local slotaccel = {"art_" .. def .. "_" .. case .. "_" .. number, "-"}
table.insert(slot_list, slotaccel)
end
end
end
end
local noun_slot_list_with_linked_and_articles = m_table.shallowCopy(noun_slot_list_with_linked)
add_slot_articles(noun_slot_list_with_linked_and_articles, cases_with_abl_voc, numbers)
local surname_slot_list_with_linked_and_articles = m_table.shallowCopy(surname_slot_list_with_linked)
add_slot_articles(surname_slot_list_with_linked_and_articles, basic_cases, {"m_s", "f_s", "p"})
local langname_slot_list_with_linked_and_articles = m_table.shallowCopy(langname_slot_list_with_linked)
add_slot_articles(langname_slot_list_with_linked_and_articles, basic_cases, {"s"})
local adjectival_slot_list_with_linked_and_articles = m_table.shallowCopy(adjectival_slot_list_with_linked)
add_slot_articles(adjectival_slot_list_with_linked_and_articles, basic_cases, numbers)
-- Return true if `prop` is a recognized indicator that can be specified on adjectives in [[Module:de-adjective]].
local function is_adjectival_decl_indicator(prop)
return prop == "ss" or prop == "sync_n" or prop == "sync_mn" or prop == "sync_mns"
end
local function skip_slot(number, slot)
return number == "sg" and rfind(slot, "_p$") or
number == "pl" and rfind(slot, "_s$")
end
local function combine_stem_ending(props, stem, ending)
if ending:find("^%^") then
-- Umlaut requested
ending = rsub(ending, "^%^", "")
stem = com.apply_umlaut(stem)
end
if props.ss and stem:find("ß$") and rfind(ending, "^" .. com.V) then
stem = rsub(stem, "ß$", "ss")
end
return stem .. ending
end
-- Add a form (a combination of `stem` and `ending`, where either may be a single string, a list of strings, or a
-- list of objects of the form {form=FORM, footnotes=FOOTNOTES}, where FOOTNOTES can be nil or a list of strings)
-- to the given slot `slot`. `gender` specifies the gender of the resulting form ("m", "f" or "n") or nil. (This is
-- used to ensure that the correct article is attached to the form when there are multiple forms with differing
-- genders. If `gender` is nil, articles of all relevant genders will be included. `gender` should only be nil
-- when the slot is plural or when the gender cannot be determined, e.g. in overrides.) `footnotes` specifies
-- any extra footnotes to add to the resulting form, and should be either nil or a list of strings.
-- `process_combined_stem_ending` is a function to process the resulting form before it is inserted. (This is used
-- currently to add an -n to the dative plural.)
local function add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
if not ending or skip_slot(base.number, slot) then
return
end
local function do_combine_stem_ending(stem, ending)
local retval = combine_stem_ending(base.props, stem, ending)
if process_combined_stem_ending then
retval = process_combined_stem_ending(retval)
end
-- For now, don't do this.
-- If gender specified, add a special character to the beginning of the value to indicate the
-- gender. This gets propagated to the end and used in [[Module:de-headword]].
-- if gender then
-- retval = gender_to_gender_char[gender] .. retval
-- end
return retval
end
footnotes = iut.combine_footnotes(base.footnotes, footnotes)
local ending_obj = iut.combine_form_and_footnotes(ending, footnotes)
-- If we're declining an adjectival noun or adjective-noun combination, and the slot is a noun slot, convert it to
-- the equivalent adjective slots (e.g. gen_s -> str_gen_s/wk_gen_s/mix_gen_s). But don't do that for "m_equiv",
-- "f_equiv", "n_equiv", which are the same in nouns and adjectives.
if base.props.overall_adj and noun_slot_set[slot] and not rfind(slot, "equiv$") then
for _, state in ipairs(states) do
iut.add_forms(base.forms, state .. "_" .. slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
else
iut.add_forms(base.forms, slot, stem or base.lemma, ending_obj, do_combine_stem_ending)
end
end
-- Process an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive,
-- plural, an override, the value of dim=/m=/f=/n=, etc. `endings` is a list of such specs, where each entry of the
-- list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or {FOOTNOTE, FOOTNOTE, ...}. If
-- `literal_endings` is given, the FORM values should be interpreted literally (i.e. as full forms) rather than as
-- ending specs. `default` is what to substitute if an ending spec is "+", and should be either in the same format as
-- `endings` or something that can be converted to that format, e.g. a string. `literal_default`, if given, indicates
-- that the FORM values in `default` should be interpreted literally, similar to `literal_endings`. `desc` is an
-- English description of what kind of spec is being processed, for error messages. `process` is called for each
-- generated form and is a function of two arguments, STEM and ENDING. If the spec is a full form, STEM will be that
-- form (in the form of an object {form=FORM, footnotes=FOOTNOTES}) and ENDING will be an empty string; otherwise, STEM
-- will be nil and ENDING will be the the ending to process in the form {form=FORM, footnotes=FOOTNOTES}. Note that
-- umlauts are not handled in process_spec(); if the spec passed in specifies an umlaut, e.g. "^chen", process()
-- will be called with a FORM beginning with "^", and must handle the umlaut itself. (Umlauts are properly handled
-- inside of add().)
local function process_spec(endings, literal_endings, default, literal_default, desc, process)
for _, ending in ipairs(endings) do
local function sub_form(form)
return {form = form, footnotes = ending.footnotes}
end
if ending.form == "--" then
-- do nothing
elseif ending.form == "+" then
if not default then
-- Could happen if e.g. gen is given as -- and then a gen_s override with + is specified, or with n= for neuter,
-- where no default is available.
error("Form '+' found for " .. desc .. " but no default is available")
end
process_spec(iut.convert_to_general_list_form(default, ending.footnotes), literal_default, nil, nil, desc, process)
else
local full_eform
if literal_endings or rfind(ending.form, "^" .. com.CAP) then
full_eform = true
elseif rfind(ending.form, "^!") then
full_eform = true
ending = sub_form(rsub(ending.form, "^!", ""))
end
if full_eform then
process(ending, "")
else
local expanded_endings
local umlaut = rmatch(ending.form, "^(%^?)%(e%)s$" )
if umlaut then
expanded_endings = {"es", "s"}
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(s%)$")
if umlaut then
expanded_endings = {"s", ""}
end
end
if not umlaut then
umlaut = rmatch(ending.form, "^(%^?)%(es%)$")
if umlaut then
expanded_endings = {"es", ""}
end
end
if expanded_endings then
local new_endings = {}
for _, expanded_ending in ipairs(expanded_endings) do
table.insert(new_endings, sub_form(umlaut .. expanded_ending))
end
process(nil, new_endings)
else
if ending.form == "-" then
ending = sub_form("")
end
process(nil, ending)
end
end
end
end
end
-- Add an ending spec such as "s", "(e)s", "^er", "^lein", "!Pizzen", etc. as might be found in the genitive, plural,
-- an override, the value of dim=/m=/f=/n=, etc., to the slot `slot` (e.g. "gen_s"). `endings` is a list of such specs,
-- where each entry of the list is of the form {form=FORM, footnotes=FOOTNOTES} where FOOTNOTES is either nil or
-- {FOOTNOTE, FOOTNOTE, ...}. For the meaning of `gender`, `footnotes` and `process_combined_stem_ending`, see add().
-- For the meaning of `default` and `literal_default`, see process_spec().
local function add_spec(base, slot, endings, gender, default, literal_default, footnotes, process_combined_stem_ending)
local function do_add(stem, ending)
add(base, slot, stem, ending, gender, footnotes, process_combined_stem_ending)
end
process_spec(endings, nil, default, literal_default, "slot '" .. slot .. "'", do_add)
end
local function process_slot_overrides(base)
for slot, overrides in pairs(base.overrides) do
if skip_slot(base.number, slot) then
error("Override specified for invalid slot '" .. slot .. "' due to '" .. base.number .. "' number restriction")
end
local origforms = base.forms[slot]
base.forms[slot] = nil
-- Gender is not given by the user.
add_spec(base, slot, overrides, nil, origforms, "literal default")
end
end
local function add_archaic_dative_singular(base, gender, def_gen)
for _, ending in ipairs(base.gens) do
local dat_ending
local ending_form = ending.form
if ending_form == "+" then
ending_form = def_gen
end
if ending_form == "es" or ending_form == "(e)s" then
dat_ending = "e"
elseif ending_form == "ses" then
dat_ending = "se"
elseif base.props.dat_with_e then
dat_ending = "e"
end
if dat_ending then
add(base, "dat_s", nil, dat_ending, gender, iut.combine_footnotes(ending.footnotes, {archaic_dative_note}))
end
end
end
local function get_n_ending(base, stem, is_sg)
if rfind(stem, "e$") then
-- typical feminine or weak masculine in -e
return "n"
elseif rfind(stem, "e[lr]$") and not rfind(stem, com.NV .. "[ei]e[lr]$") then
-- [[Kammer]], [[Feier]], [[Leier]], but not [[Spur]], [[Beer]], [[Manier]], [[Schmier]] or [[Vier]]
-- similarly, [[Achsel]], [[Gabel]], [[Tafel]], etc. but not [[Ziel]]
return "n"
elseif base.props.weak_n then
-- ''des Nachbarn'', ''des Herrn'', ''des Satyrn'', etc.
return "n"
elseif rfind(stem, "[^aeAE]in$") then
-- [[Chinesin]], [[Doktorin]], etc.; but not words in -ein or -ain such as [[Pein]]
return "nen"
else
return "en"
end
end
local function get_default_gen(base, gender)
if gender == "f" then
return ""
elseif base.props.weak then
return get_n_ending(base, base.lemma, "is singular")
elseif rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or occasional masculine like [[Firnis]], [[Penis]]
return "ses"
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Euphemismus]], [[Exitus]], [[Exodus]], etc.
return ""
elseif rfind(base.lemma, "[sßxz]$") then
return "es"
else
return "s"
end
end
local function get_default_pl(base, gender)
if rfind(base.lemma, "nis$") then
-- neuter like [[Erlebnis]], [[Geheimnis]] or feminine like [[Kenntnis]], [[Wildnis]],
-- or occasional masculine like [[Firnis]], [[Penis]]
return "se"
elseif gender == "f" or base.props.weak then
return get_n_ending(base, base.lemma)
elseif rfind(base.lemma, "e$") then
track("default-pl-e-not-f-or-weak")
-- FIXME: This should return "s"
return get_n_ending(base, base.lemma)
elseif gender == "n" and rfind(base.lemma, "lein$") then
-- Diminutives in -lein (those in -chen will automatically get a null ending from -en below)
return ""
elseif gender == "n" and rfind(base.lemma, "um$") then
-- [[Museum]] -> [[Museen]], [[Vakuum]] -> [[Vakuen]]; not masculine [[Baum]] (plural [[Bäume]])
-- or [[Reichtum]] (plural [[Reichtümer]])
return "!" .. rsub(base.lemma, "um$", "en")
elseif rfind(base.lemma, "mus$") then
-- Algorithmus -> Algorithmen, Aphorismus -> Aphorismen
return "!" .. rsub(base.lemma, "us$", "en")
elseif rfind(base.lemma, com.NV .. "us$") then
-- [[Abakus]] -> [[Abakusse]], [[Zirkus]] -> [[Zirkusse]], [[Autobus]] -> [[Autobusse]];
-- not [[Applaus]] (plural [[Applause]])
return "se"
elseif rfind(base.lemma, "e[lmnr]$") and not rfind(base.lemma, com.NV .. "[ei]e[lnmr]$") then
-- check for weak ending -el, -em, -en, -er, e.g. [[Adler]], [[Meier]], [[Riedel]]; but exclude [[Heer]],
-- [[Bier]], [[Ziel]], which take -e by default
return ""
else
return "e"
end
end
local function decline_singular(base, gender, def_gen)
add(base, "nom_s", nil, "", gender)
add_spec(base, "gen_s", base.gens, gender, def_gen)
if base.props.weak then
local ending = get_n_ending(base, base.lemma, "is singular")
add(base, "dat_s", nil, ending, gender)
add(base, "acc_s", nil, gender == "m" and ending or "", gender)
else
add(base, "dat_s", nil, "", gender)
add_archaic_dative_singular(base, gender, def_gen)
add(base, "acc_s", nil, "", gender)
end
end
local function decline_plural(base, def_pl)
local function process_nom_pl_for_decl_type(stem_ending)
if base.props.saw_mn and base.number ~= "pl" then
if base.props.weak then
m_table.insertIfNot(base.decl_type, "weak")
elseif stem_ending == base.lemma .. "n" or stem_ending == base.lemma .. "en" then
m_table.insertIfNot(base.decl_type, "mixed")
else
m_table.insertIfNot(base.decl_type, "strong")
end
end
return stem_ending
end
local function process_dat_pl_to_add_n(stem_ending)
if base.props.nodatpln then
return stem_ending
elseif rfind(stem_ending, "e[lr]?$") or rfind(stem_ending, "erl$") then
return stem_ending .. "n"
else
return stem_ending
end
end
add_spec(base, "nom_p", base.pls, nil, def_pl, nil, nil, process_nom_pl_for_decl_type)
add_spec(base, "gen_p", base.pls, nil, def_pl)
add_spec(base, "dat_p", base.pls, nil, def_pl, nil, nil, process_dat_pl_to_add_n)
add_spec(base, "acc_p", base.pls, nil, def_pl)
end
local function decline_noun(base)
if base.number == "pl" then
decline_plural(base, "")
if rfind(base.lemma, "innen$") then
--- Ends in -innen, likely feminine. Chop off, and convert e.g. Chinesinnen -> Chinesen.
local masc = rsub(base.lemma, "innen$", "")
if rfind(masc, "es$") then
masc = masc .. "en"
end
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", masc, "")
else
-- Likely masculine. Try to convert Chinesen -> Chinesinnen, and -er -> -erinnen.
local femstem = rsub(base.lemma, "en$", "")
add(base, "f_equiv", femstem, "innen")
end
else
base.decl_type = {}
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
decline_singular(base, gender, get_default_gen(base, gender))
decline_plural(base, get_default_pl(base, gender))
if gender == "m" then
add(base, "f_equiv", rsub(base.lemma, "e$", ""), "in") -- feminine
elseif gender == "f" then
-- Try (sort of) to get the masculine. Remove final -in, and if the result ends in -es, convert to -ese
-- (e.g. Chinesin -> Chinese).
local masc = rsub(base.lemma, "in$", "")
if rfind(masc, "es$") then
masc = masc .. "e"
end
add(base, "m_equiv", masc, "")
end -- do nothing for neuter
end
end
end
local function decline_surname(base)
-- We don't specify gender here. There are always two genders, m and f, which will be handled correctly in
-- [[Module:de-headword]].
add(base, "nom_m_s", nil, "")
add(base, "nom_f_s", nil, "")
local gen_m_s
if rfind(base.lemma, "[sxzß]$") or rfind(base.lemma, "ce$") then
-- [[Marx]], [[Engels]], [[Weiß]], [[Schulz]]
-- also names with silent -s or -x like [[Delacroix]]
gen_m_s = "'"
else
gen_m_s = "s"
end
add_spec(base, "gen_m_s", base.gens, nil, gen_m_s)
add(base, "gen_m_s", nil, "", nil, {"[with an article]"})
add(base, "gen_f_s", nil, "")
add(base, "dat_m_s", nil, "")
add(base, "dat_f_s", nil, "")
add(base, "acc_m_s", nil, "")
add(base, "acc_f_s", nil, "")
local pl_ending
if rfind(base.lemma, "[sxß]$") then
-- [[Marx]], [[Engels]], [[Weiß]]
pl_ending = {"", "ens"}
elseif rfind(base.lemma, "z$") then
-- [[Schulz]], [[Schmitz]]
pl_ending = {"", "es", "ens"}
elseif rfind(base.lemma, "ce$") then
pl_ending = {"", "ns"}
elseif rfind(base.lemma, "e[nlr]?$") then
-- [[Müller]], [[Goethe]], [[Dürer]], [[Schlegel]], [[Münchhausen]]
pl_ending = {"s", ""}
else
-- [[Schmidt]], [[Bergmann]], [[Brentano]]
pl_ending = {"s"}
end
add_spec(base, "nom_p", base.pls, nil, pl_ending)
add_spec(base, "gen_p", base.pls, nil, pl_ending)
add_spec(base, "dat_p", base.pls, nil, pl_ending)
add_spec(base, "acc_p", base.pls, nil, pl_ending)
end
local function decline_toponym(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
local gen_s
local null_footnote
if rfind(base.lemma, "[sxzß]$") then
gen_s = "'"
null_footnote = "[with an article]"
else
gen_s = "s"
null_footnote = "[optionally with an article]"
end
add_spec(base, "gen_s", base.gens, nil, gen_s)
add(base, "gen_s", nil, "", nil, {null_footnote})
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
if base.number == "both" then
-- only with explicitly given plural
add_spec(base, "nom_p", base.pls)
add_spec(base, "gen_p", base.pls)
add_spec(base, "dat_p", base.pls)
add_spec(base, "acc_p", base.pls)
end
end
local function decline_langname(base)
-- We don't specify gender here, which is always neuter.
add(base, "nom_s", nil, "")
add(base, "gen_s", nil, "")
-- If explicit genitive singular given, add it (in addition to the null genitive singular), otherwise default to -s.
add_spec(base, "gen_s", base.gens, nil, "s")
add(base, "dat_s", nil, "")
add(base, "acc_s", nil, "")
add(base, "nom_s_alt", nil, "e")
add(base, "gen_s_alt", nil, "en")
add(base, "dat_s_alt", nil, "en")
add(base, "acc_s_alt", nil, "e")
end
local function decline_adjective(base)
-- Construct an equivalent call to {{de-adecl}} based on the adjective indicators we fetched.
local adj_spec_parts = {}
local function ins(val)
table.insert(adj_spec_parts, val)
end
local function ins_dot()
if #adj_spec_parts > 0 then
ins(".")
end
end
local function insert_footnotes(footnotes)
if footnotes then
for _, footnote in ipairs(footnotes) do
ins(footnote)
end
end
end
if base.adj_stem then
ins("stem")
for _, stem in ipairs(base.adj_stem) do
ins(":")
ins(stem.form)
insert_footnotes(stem.footnotes)
end
end
if base.adj_suppress then
ins_dot()
ins("suppress:")
ins(base.adj_suppress)
end
if base.footnotes then
ins_dot()
insert_footnotes(base.footnotes)
end
for prop, _ in pairs(base.props) do
if is_adjectival_decl_indicator(prop) then
ins_dot()
ins(prop)
end
end
local adj_alternant_multiword_spec = require("Module:de-adjective").do_generate_forms(
{base.lemma .. "<" .. table.concat(adj_spec_parts) .. ">"}
)
local function copy(from_slot, to_slot)
base.forms[to_slot] = adj_alternant_multiword_spec.forms[from_slot]
end
local function copy_gender_forms(gender)
local number = gender == "p" and "p" or "s"
for _, state in ipairs(states) do
for _, case in ipairs(basic_cases) do
copy(state .. "_" .. case .. "_" .. gender, state .. "_" .. case .. "_" .. number)
end
end
end
if base.number == "pl" then
copy_gender_forms("p")
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "e")
add(base, "f_equiv", base.lemma, "e")
add(base, "n_equiv", base.lemma, "e")
else
-- Normally there should be only one gender.
for _, genderspec in ipairs(base.genders) do
local gender = genderspec.form
copy_gender_forms(gender)
-- No need to specify gender for *_equiv; will be handled correctly in [[Module:de-headword]].
add(base, "m_equiv", base.lemma, "er") -- masculine
add(base, "f_equiv", base.lemma, "e") -- feminine
add(base, "n_equiv", base.lemma, "es") -- neuter
end
if base.number ~= "sg" then
copy_gender_forms("p")
end
end
end
-- Return the slots that may contain a lemma, in the order they should be checked. `props` is a property table,
-- coming either from `base` or `alternant_multiword_spec`.
local function get_lemma_slots(props)
if props.surname then
return {"nom_m_s"}
elseif props.overall_adj then
return {"str_nom_s", "str_nom_p"}
else
return {"nom_s", "nom_p"}
end
end
-- Return the lemmas for this term. The return value is a list of {form = FORM, footnotes = FOOTNOTES}.
-- If `linked_variant` is given, return the linked variants (with embedded links if specified that way by the user),
-- otherwies return variants with any embedded links removed. If `remove_footnotes` is given, remove any
-- footnotes attached to the lemmas.
function export.get_lemmas(alternant_multiword_spec, linked_variant, remove_footnotes)
local slots_to_fetch = get_lemma_slots(alternant_multiword_spec.props)
local linked_suf = linked_variant and "_linked" or ""
for _, slot in ipairs(slots_to_fetch) do
if alternant_multiword_spec.forms[slot .. linked_suf] then
local lemmas = alternant_multiword_spec.forms[slot .. linked_suf]
if remove_footnotes then
local lemmas_no_footnotes = {}
for _, lemma in ipairs(lemmas) do
table.insert(lemmas_no_footnotes, {form = lemma.form})
end
return lemmas_no_footnotes
else
return lemmas
end
end
end
return {}
end
local function handle_derived_slots_and_overrides(base)
process_slot_overrides(base)
-- Compute linked versions of potential lemma slots, for use in {{de-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs(get_lemma_slots(base.props)) do
iut.insert_forms(base.forms, slot .. "_linked", iut.map_forms(base.forms[slot], function(form)
if form == base.orig_lemma_no_links and rfind(base.orig_lemma, "%[%[") then
return base.orig_lemma
else
return form
end
end))
end
end
-- Like put.split_alternating_runs_and_strip_spaces(), but ensure that backslash-escaped commas and periods are not
-- treated as separators.
local function split_alternating_runs_with_escapes(segments, splitchar)
for i, segment in ipairs(segments) do
segments[i] = rsub(segment, "\\,", SUB_ESCAPED_COMMA)
segments[i] = rsub(segment, "\\%.", SUB_ESCAPED_PERIOD)
end
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, splitchar)
for _, separated_group in ipairs(separated_groups) do
for i, segment in ipairs(separated_group) do
separated_group[i] = rsub(segment, SUB_ESCAPED_COMMA, ",")
separated_group[i] = rsub(segment, SUB_ESCAPED_PERIOD, ".")
end
end
return separated_groups
end
--[=[
Parse an indicator spec (text consisting of angle brackets and zero or more dot-separated indicators within them).
Return value is an object of the form
{
overrides = {
SLOT = {OVERRIDE, OVERRIDE, ...},
...
}, -- where OVERRIDE is {form = FORM, footnotes = FOOTNOTES}; same as `forms` table; FORM can be a full form (only if
beginning with a capital letter or !), otherwise an ending; "-" for an ending means a null ending, while
"--" suppresses the slot entirely, i.e. it is defective
gens = {GEN_SG_SPEC, GEN_SG_SPEC, ...}, same form as OVERRIDE above
pls = {PL_SPEC, PL_SPEC, ...}, same form as OVERRIDE above
forms = {}, -- forms for a single spec alternant; see `forms` below
props = {
PROP = true,
PROP = true,
...
}, -- misc Boolean properties: "weak" (weak noun); "adj" (adjectival noun; set using "+");
"ss" (lemma in -ß changes to -ss- before endings beginning with a vowel; pre-1996 spelling);
"nodatpln" (suppress automatic addition of 'n' in the dative plural after '-e', '-er', '-el')
number = "NUMBER", -- "sg", "pl", "both"; may be missing
adj = true, -- may be missing
-- The following additional fields are added by other functions:
orig_lemma = "ORIGINAL-LEMMA", -- as given by the user or taken from pagename
orig_lemma_no_links = "ORIGINAL-LEMMA-NO-LINKS", -- links removed
lemma = "LEMMA", -- `orig_lemma_no_links`,
forms = {
SLOT = {
{
form = "FORM",
footnotes = {"FOOTNOTE", "FOOTNOTE", ...} -- may be missing
},
...
},
...
},
}
]=]
local function parse_indicator_spec(angle_bracket_spec, lemma, pagename, proper_noun)
if lemma == "" then
lemma = pagename
end
local base = {forms = {}, overrides = {}, props = {prop = proper_noun}}
base.orig_lemma = lemma
base.orig_lemma_no_links = m_links.remove_links(lemma)
base.lemma = base.orig_lemma_no_links
local inside = rmatch(angle_bracket_spec, "^<(.*)>$")
assert(inside)
local function parse_err(msg)
error(msg .. ": <" .. inside .. ">")
end
--[=[
Parse a single override spec and return three values: the slot the override applies to, the original indicator
spec used to specify the slot, and the override specs. The input is a list where the footnotes have been separated
out. For example, given the spec 'dat:-[referring to a card suit, as a term of endearment, and generally in speech]:en[in most cases in writing]',
the input will be a list {"dat:-", "[referring to a card suit, as a term of endearment, and generally in speech]", ":en",
"[in most cases in writing]", ""}
]=]
local function parse_override(segments)
local part = segments[1]
local offset = 4
local case = usub(part, 1, 3)
if not case_set_with_abl_voc[case] then
parse_err("Internal error: unrecognized case in override: '" .. table.concat(segments) .. "'")
end
local indicator = case
local rest = usub(part, offset)
local slot
if rfind(rest, "^pl") then
rest = rsub(rest, "^pl", "")
slot = case .. "_p"
indicator = indicator .. "pl"
else
slot = case .. "_s"
end
if rfind(rest, "^:") then
rest = rsub(rest, "^:", "")
else
parse_err("Slot indicator '" .. indicator .. "' must be followed by a colon: '" .. table.concat(segments) .. "'")
end
if not noun_slot_set[slot] then
parse_err("Unrecognized slot indicator '" .. indicator .. "': '" .. table.concat(segments) .. "'")
end
segments[1] = rest
return slot, indicator, com.fetch_specs(segments, ":", "override", nil, parse_err)
end
if inside ~= "" then
local segments = put.parse_balanced_segment_run(inside, "[", "]")
local dot_separated_groups = split_alternating_runs_with_escapes(segments, "%.")
for i, dot_separated_group in ipairs(dot_separated_groups) do
local part = dot_separated_group[1]
if i == 1 then
local comma_separated_groups = split_alternating_runs_with_escapes(dot_separated_group, ",")
base.genders = com.fetch_specs(comma_separated_groups[1], ":", "gender", nil, parse_err)
local saw_sg = false
local saw_pl = false
local saw_gendered_pl = false
local saw_non_gendered_pl = false
local saw_adj = false
local special_variant = nil
for _, genderspec in ipairs(base.genders) do
local g = genderspec.form
if g == "m" or g == "n" then
-- Set this on `base.props` as it's used in various other places.
base.props.saw_mn = true
saw_sg = true
elseif g == "f" then
saw_sg = true
elseif g == "p" then
saw_pl = true
saw_non_gendered_pl = true
elseif rfind(g, "^[mfn]p$") then
saw_pl = true
saw_gendered_pl = true
elseif g == "+" or g == "p+" or g == "+p" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with adjectival declension")
end
saw_adj = true
if g ~= "+" then
saw_pl = true
end
elseif g == "surname" or g == "toponym" or g == "langname" then
if #base.genders > 1 then
parse_err("Can't specify multiple genders with " .. g .. " declension")
end
special_variant = g
else
parse_err("Unrecognized gender spec '" .. g .. "'")
end
end
if saw_sg and saw_pl then
parse_err("Can't specify both singular and plural gender specs")
end
if saw_gendered_pl and saw_non_gendered_pl then
parse_err("Can't specify both 'p' and gendered plural specs")
end
local gen_index = (base.props.saw_mn or special_variant) and 2 or 1
local pl_index =
(saw_adj or saw_pl) and 1 or
(base.props.saw_mn or special_variant == "surname" or special_variant == "toponym") and 3 or
2
if #comma_separated_groups > pl_index then
if saw_adj then
parse_err("Can't specify plurals or genitives with adjectival declension")
elseif saw_pl then
parse_err("Can't specify plurals or genitives with plural-only nouns")
elseif base.props.saw_mn then
parse_err("Can specify at most three comma-separated specs when the gender is masculine or "
.. "neuter (gender, genitive, plural)")
elseif special_variant == "surname" or special_variant == "toponym" then
parse_err("Can specify at most three comma-separated specs with '" .. special_variant .. "' "
.. "nouns ('" .. special_variant .. "', genitive, plural)")
elseif special_variant == "langname" then
parse_err("Can specify at most two comma-separated specs with 'langname' "
.. " ('langname', genitive)")
else
parse_err("Can specify at most two comma-separated specs when the gender is feminine "
.. "(gender, plural)")
end
end
if #comma_separated_groups >= gen_index and gen_index > 1 then
base.gens = com.fetch_specs(comma_separated_groups[gen_index], ":", "genitive", "allow blank", parse_err)
end
if #comma_separated_groups >= pl_index and pl_index > gen_index then
base.pls = com.fetch_specs(comma_separated_groups[pl_index], ":", "plural", "allow blank", parse_err)
end
if special_variant then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for '" .. special_variant .. "'")
else
base.props[special_variant] = true
if special_variant == "surname" then
-- FIXME, does it make sense to put the footnotes on the feminine gender (they appear after the gender)?
base.genders = {{form = "m"}, {form = "f", footnotes = base.genders[1].footnotes}}
else
base.genders = {{form = "n", footnotes = base.genders[1].footnotes}}
end
end
elseif saw_adj then
if #base.genders > 1 then
parse_err("Internal error: More than one gender spec for adjectival declension")
else
base.props.adj = true
if saw_pl then
base.number = "pl"
base.genders = {{form = "p", footnotes = base.genders[1].footnotes}}
else
-- Stash the footnotes into `adj_footnotes`; we will put them onto the autodetected gender
-- in determine_adjectival_genders(), which will set base.genders appropriately.
base.adj_footnotes = base.genders[1].footnotes
base.genders = {}
end
end
elseif saw_pl then
-- Convert 'mp' to 'm-p', 'fp' to 'f-p', etc. as that's what [[Module:gender and number]] expects.
for _, genderspec in ipairs(base.genders) do
local gender = rmatch(genderspec.form, "^([mfn])p$")
if gender then
genderspec.form = gender .. "-p"
end
end
base.number = "pl"
end
elseif base.props.adj and part:find("^stem:") then
dot_separated_group[1] = rsub(part, "^stem:", "")
base.adj_stem = com.fetch_specs(dot_separated_group, ":", "adjectival stem", nil, parse_err)
elseif base.props.adj and part:find("^suppress:") then
if #dot_separated_group > 1 then
parse_err("Can't specify footnotes with suppress: '" .. table.concat(dot_separated_group) .. "'")
end
-- No need to parse or validate more. Will happen in [[Module:de-adjective]].
base.adj_suppress = rsub(part, "suppress:", "")
elseif part == "" then
if #dot_separated_group == 1 then
parse_err("Blank indicator")
end
base.footnotes = com.fetch_footnotes(dot_separated_group, parse_err)
elseif part:find(":") then
-- override
-- FIXME: Handle adjectival overrides
local case_prefix = usub(part, 1, 3)
if case_set_with_abl_voc[case_prefix] then
local slot, slot_indicator, override = parse_override(dot_separated_group)
if base.overrides[slot] then
parse_err("Can't specify override twice for slot '" .. slot_indicator .. "'")
else
base.overrides[slot] = override
end
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
elseif #dot_separated_group > 1 then
local errmsg
if base.props.adj then
errmsg = "Footnotes only allowed with slot overrides, 'stem:' or by themselves"
else
errmsg = "Footnotes only allowed with genitive, plural, slot overrides or by themselves"
end
parse_err(errmsg .. ": '" .. table.concat(dot_separated_group) .. "'")
elseif part == "sg" or part == "both" then
if base.number then
if base.number ~= part then
parse_err("Can't specify '" .. part .. "' along with '" .. base.number .. "'")
else
parse_err("Can't specify '" .. part .. "' twice")
end
end
base.number = part
elseif not base.props.adj and (part == "weak" or part == "weak_n" or part == "ss" or part == "nodatpln" or part == "article" or part == "dat_with_e") then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
if part == "weak_n" then
-- weak_n implies weak
base.props.weak = true
end
elseif base.props.adj and (part == "article" or is_adjectival_decl_indicator(part)) then
if base.props[part] then
parse_err("Can't specify '" .. part .. "' twice")
end
base.props[part] = true
else
parse_err("Unrecognized indicator '" .. part .. "'")
end
end
end
return base
end
-- For an adjectival lemma, synthesize the predicative (lemma) form. It doesn't have to be perfect in that the
-- predicative form itself isn't used, so we don't have to try to convert -abler -> -abel or anything like that.
local function synthesize_adj_lemma(base)
local stem, ending = rmatch(base.lemma, "^(.*)(e[rs]?)$")
if not stem then
error("Unrecognized adjectival lemma, should end in '-er', '-e' or '-es': '" .. base.lemma .. "'")
end
base.lemma = stem
-- Will be ignored if number == "pl"
if ending == "er" then
base.autodetected_gender = "m"
elseif ending == "e" then
base.autodetected_gender = "f"
else
base.autodetected_gender = "n"
end
end
local function detect_indicator_spec(alternant_multiword_spec, base)
if base.props.article then
alternant_multiword_spec.props.article = true
end
for _, prop in ipairs {"surname", "toponym", "langname"} do
if alternant_multiword_spec.props[prop] == nil then
alternant_multiword_spec.props[prop] = base.props[prop]
elseif alternant_multiword_spec.props[prop] ~= base.props[prop] then
-- We do this because we have a special table with its own slots for each of these special variants.
-- FIXME: Consider supporting adjectives with these variants. That requires that we copy the adjectival
-- declensions to the appropriate per-variant slots.
error("If some alternants set '" .. prop .. "', all must do so")
end
end
if base.props.adj then
alternant_multiword_spec.props.overall_adj = true
synthesize_adj_lemma(base)
else
-- Set default values.
base.number =
base.number or
base.props.surname and "both" or
base.pls and "both" or
(alternant_multiword_spec.props.is_proper or base.props.toponym or base.props.langname) and "sg" or
"both"
if not base.props.surname then
if base.number == "pl" then
if base.gens then
error("Internal error: With plural-only noun, no genitive singular specs should be allowed")
end
if base.pls then
error("Internal error: With plural-only noun, no plural specs should be allowed")
end
end
if base.pls and base.number == "sg" then
error("Can't specify explicit plural specs along with explicit '.sg'")
end
end
base.gens = base.gens or {{form = "+"}}
base.pls = base.pls or {{form = "+"}}
end
end
local function detect_all_indicator_specs(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
detect_indicator_spec(alternant_multiword_spec, base)
end)
-- Now propagate some properties downwards.
iut.map_word_specs(alternant_multiword_spec, function(base)
base.props.overall_adj = alternant_multiword_spec.props.overall_adj
end)
end
local propagate_multiword_properties
local function propagate_alternant_properties(alternant_spec, property, mixed_value, nouns_only)
local seen_property
for _, multiword_spec in ipairs(alternant_spec.alternants) do
propagate_multiword_properties(multiword_spec, property, mixed_value, nouns_only)
if seen_property == nil then
seen_property = multiword_spec[property]
elseif multiword_spec[property] and seen_property ~= multiword_spec[property] then
seen_property = mixed_value
end
end
alternant_spec[property] = seen_property
end
propagate_multiword_properties = function(multiword_spec, property, mixed_value, nouns_only)
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs[i].alternants then
propagate_alternant_properties(word_specs[i], property, mixed_value)
is_nounal = not not word_specs[i][property]
elseif nouns_only then
is_nounal = not word_specs[i].props.adj
else
is_nounal = not not word_specs[i][property]
end
if is_nounal then
if not word_specs[i][property] then
error("Internal error: noun-type word spec without " .. property .. " set")
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs[j][property] = word_specs[j][property] or word_specs[i][property]
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs[i][property]
elseif seen_property ~= word_specs[i][property] then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs[i][property] = word_specs[i][property] or word_specs[last_seen_nounal_pos][property]
end
end
multiword_spec[property] = seen_property
end
local function propagate_properties_downward(alternant_multiword_spec, property, default_propval)
local propval1 = alternant_multiword_spec[property] or default_propval
alternant_multiword_spec[property] = propval1
for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
local propval2 = alternant_or_word_spec[property] or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
local propval3 = multiword_spec[property] or propval2
for _, word_spec in ipairs(multiword_spec.word_specs) do
local propval4 = word_spec[property] or propval3
if propval4 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
word_spec[property] = propval4
end
end
else
if propval2 == "mixed" then
error("Attempt to assign mixed " .. property .. " to word")
end
alternant_or_word_spec[property] = propval2
end
end
end
--[=[
Propagate `property` ("genders" or "number") from nouns to adjacent adjectives. We proceed as follows:
1. We assume the properties in question are already set on all nouns. This should happen in parse_indicator_spec().
2. We first propagate properties upwards and sideways. We recurse downwards from the top. When we encounter a
multiword spec, we proceed left to right looking for a noun. When we find a noun, we fetch its property
(recursing if the noun is an alternant), and propagate it to any adjectives to its left, up to the next noun
to the left. When we have processed the last noun, we also propagate its property value to any adjectives to the
right. Finally, we set the property value for the multiword spec itself by combining all the non-nil properties of
the individual elements. If all non-nil properties have the same value, the result is that value, otherwise it is
`mixed_value` (which is "mixed" gender, but "both" for number).
3. When we encounter an alternant spec in this process, we recursively process each alternant (which is a multiword
spec) using the previous step, and combine any non-nil properties we encounter the same way as for multiword specs.
4. The effect of steps 2 and 3 is to set the property of each alternant and multiword spec based on its children or its
neighbors.
]=]
local function propagate_properties(alternant_multiword_spec, property, default_propval, mixed_value)
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, "nouns only")
propagate_multiword_properties(alternant_multiword_spec, property, mixed_value, false)
propagate_properties_downward(alternant_multiword_spec, property, default_propval)
end
-- Set the gender of adjectives and adjectival nouns to the gender autodetected during synthesize_adj_lemma(),
-- unless the form is plural. We don't just set the gender directly in synthesize_adj_lemma() because we don't know
-- until later (i.e. when propagate_properties() is called) whether an adjectival form in -e is feminine or plural.
-- We set the footnotes (i.e. qualifiers) of the gender to the footnotes (if any) specified directly after '+'.
local function determine_adjectival_genders(alternant_multiword_spec)
iut.map_word_specs(alternant_multiword_spec, function(base)
if base.props.adj and #base.genders == 0 then
base.genders = {{form = base.number == "pl" and "p" or base.autodetected_gender, footnotes = base.adj_footnotes}}
end
end)
end
-- Find the first noun in a multiword expression and set alternant_multiword_spec.first_noun
-- to the index of that noun. Also find the first adjective and set alternant_multiword_spec.first_adj
-- similarly. If there is a first noun, we use its properties to determine the overall expression's
-- properties; otherwise we use the first adjective's properties, otherwise the first word's properties.
-- If the "word" located this way is not an alternant spec, we just use its properties directly, otherwise
-- we use the properties of the first noun (or failing that the first adjective, or failing that the
-- first word) in each alternative alternant in the alternant spec. For this reason, we need to set the
-- the .first_noun of and .first_adj of each multiword expression embedded in the first noun alternant spec,
-- and the .first_adj of each multiword expression in each adjective alternant spec leading up to the
-- first noun alternant spec.
local function determine_noun_status(alternant_multiword_spec)
for i, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do
if alternant_or_word_spec.alternants then
local alternant_type
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
for j, word_spec in ipairs(multiword_spec.word_specs) do
if not word_spec.props.adj then
multiword_spec.first_noun = j
alternant_type = "နာမ်"
break
elseif not multiword_spec.first_adj then
multiword_spec.first_adj = j
if not alternant_type then
alternant_type = "adj"
end
end
end
end
if alternant_type == "noun" then
alternant_multiword_spec.first_noun = i
return
elseif alternant_type == "adj" and not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
else
if not alternant_or_word_spec.props.adj then
alternant_multiword_spec.first_noun = i
return
elseif not alternant_multiword_spec.first_adj then
alternant_multiword_spec.first_adj = i
end
end
end
end
local function decline_noun_or_adjective(base)
if base.props.surname then
decline_surname(base)
elseif base.props.toponym then
decline_toponym(base)
elseif base.props.langname then
decline_langname(base)
elseif base.props.adj then
decline_adjective(base)
else
decline_noun(base)
end
handle_derived_slots_and_overrides(base)
end
-- Set the overall articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_non_surname_articles(alternant_multiword_spec)
if alternant_multiword_spec.number ~= "pl" then
iut.map_word_specs(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
for _, case in ipairs(cases_with_abl_voc) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_s",
{form = com.articles[genderspec.form][def .. "_" .. case]})
end
end
end
end)
end
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_p",
{form = com.articles.p[def .. "_" .. case]})
end
end
end
-- Set the overall surname articles. We can't do this using the normal inflection code as it will produce e.g.
-- '[[der]] [[und]] [[der]]' for conjoined nouns.
local function compute_surname_articles(alternant_multiword_spec)
for _, gender in ipairs {"m", "f"} do
for _, case in ipairs(basic_cases) do
for _, def in ipairs(definitenesses) do
iut.insert_form(alternant_multiword_spec.forms, "art_" .. def .. "_" .. case .. "_" .. gender .. "_s",
{form = "([[" .. com.articles[gender][def .. "_" .. case] .. "]])"})
end
end
end
for _, case in ipairs(basic_cases) do
iut.insert_form(alternant_multiword_spec.forms, "art_def_" .. case .. "_p",
{form = "([[" .. com.articles.p["def_" .. case] .. "]])"})
end
end
local function compute_articles(alternant_multiword_spec)
if alternant_multiword_spec.props.surname then
compute_surname_articles(alternant_multiword_spec)
else
compute_non_surname_articles(alternant_multiword_spec)
end
end
-- Call a function `fun` over the first noun in the `alternant_multiword_spec`, or over the first noun in each
-- alternant if there is more than one alternant. If there are no nouns, use the first adjective (in the case of an
-- adjectival noun).
local function map_first_noun(alternant_multiword_spec, fun)
local key_entry = alternant_multiword_spec.first_noun or alternant_multiword_spec.first_adj or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs[key_entry]
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do
key_entry = multiword_spec.first_noun or multiword_spec.first_adj or 1
if #multiword_spec.word_specs >= key_entry then
fun(multiword_spec.word_specs[key_entry])
end
end
else
fun(alternant_or_word_spec)
end
end
end
-- Compute the categories to add the noun to, as well as the annotation to display in the
-- declension title bar. We combine the code to do these functions as both categories and
-- title bar contain similar information.
local function compute_categories_and_annotation(alternant_multiword_spec)
alternant_multiword_spec.categories = {}
alternant_multiword_spec.decl_type = {}
local function insert(cattype)
cattype = rsub(cattype, "~", alternant_multiword_spec.pos)
m_table.insertIfNot(alternant_multiword_spec.categories, "ဂျာမာန်" .. cattype .. "")
end
if not alternant_multiword_spec.props.is_proper and alternant_multiword_spec.number == "sg" then
insert("~မတော်ဟွံဂွံဂမၠိုၚ်")
elseif alternant_multiword_spec.number == "pl" then
-- insert("pluralia tantum")
end
local annotation
local annparts = {}
local genderdescs = {}
local decldescs = {}
if alternant_multiword_spec.number == "sg" then
table.insert(annparts, "sg-only")
elseif alternant_multiword_spec.number == "pl" and alternant_multiword_spec.genders[1].spec ~= "p" then
-- If the gender is just 'p', we use "pl-only" below as a substitute for the gender and hook any qualifiers
-- onto it. Note that when 'p' is the gender, there can be only one gender.
table.insert(annparts, "pl-only")
end
for i, genderspec in ipairs(alternant_multiword_spec.genders) do
local genderdesc_parts = {}
local gender = genderspec.spec
if gender == "p" then
table.insert(genderdesc_parts, "pl-only")
else
gender = rsub(gender, "%-p$", "")
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender])
end
if genderspec.qualifiers then
table.insert(genderdesc_parts, " ''(")
table.insert(genderdesc_parts, table.concat(genderspec.qualifiers, ", "))
table.insert(genderdesc_parts, ")''")
end
table.insert(genderdescs, table.concat(genderdesc_parts))
end
local function insert_decl_type(decl_type)
m_table.insertIfNot(decldescs, decl_type)
m_table.insertIfNot(alternant_multiword_spec.decl_type, decl_type)
end
local function do_word_spec(base)
if base.props.surname then
m_table.insertIfNot(decldescs, "surname")
elseif base.props.toponym then
m_table.insertIfNot(decldescs, "toponym")
elseif base.props.langname then
m_table.insertIfNot(decldescs, "langname")
elseif base.decl_type and #base.decl_type > 0 then
-- strong/weak/mixed declension type; should only be present on masculine or neuter nouns with a plural
for _, decl_type in ipairs(base.decl_type) do
if decl_type == "weak" then
insert("weak ~")
elseif decl_type == "mixed" then
insert("~မပံၚ်ဖနှဴလဝ်ဂမၠိုၚ်")
end
insert_decl_type(decl_type)
end
elseif base.props.saw_mn then
-- For singular-only masculine or neuter nouns, we can still classify as strong or weak.
-- We don't try to classify plural-only nouns. Even for nouns in -n or -en, we have no idea if they are
-- strong (-en is part of the stem), mixed or weak.
if base.props.weak then
insert("weak ~")
insert_decl_type("weak")
else
insert_decl_type("strong")
end
end
end
-- Use the surname/toponym/langname/weak/strong properties of the noun(s).
map_first_noun(alternant_multiword_spec, do_word_spec)
if #genderdescs > 0 then
table.insert(annparts, table.concat(genderdescs, " // "))
end
if #decldescs > 0 then
table.insert(annparts, table.concat(decldescs, " // "))
end
if not alternant_multiword_spec.first_noun and alternant_multiword_spec.first_adj then
insert("adjectival ~")
table.insert(annparts, "adjectival")
end
if alternant_multiword_spec.props.langname then
-- insert("specially-declined language names")
end
alternant_multiword_spec.annotation = table.concat(annparts, ", ")
end
local function compute_headword_genders(alternant_multiword_spec)
alternant_multiword_spec.genders = {}
-- Compute the genders based on the nouns. We don't want to use the adjectives in adjective-noun combinations
-- because that will cause issues in plural-only expressions like [[Kanarische Inseln]], where ''Inseln'' may be
-- 'f-p' but ''Kanarische'' will be just 'p', and we'd end up with both genders.
map_first_noun(alternant_multiword_spec, function(base)
for _, genderspec in ipairs(base.genders) do
-- Create the new spec to insert.
local spec = {spec = genderspec.form, qualifiers = genderspec.footnotes}
-- See if the gender of the spec is already present; if so, combine qualifiers.
local saw_existing = false
for _, existing_spec in ipairs(alternant_multiword_spec.genders) do
if existing_spec.spec == spec.spec then
existing_spec.qualifiers = iut.combine_footnotes(existing_spec.qualifiers, spec.qualifiers)
saw_existing = true
break
end
end
-- If not, add gender.
if not saw_existing then
table.insert(alternant_multiword_spec.genders, spec)
end
end
end)
-- Now convert the footnotes in the gender specs to qualifiers. This involves removing brackets and expanding any
-- footnote abbreviations.
for _, genderspec in ipairs(alternant_multiword_spec.genders) do
if genderspec.qualifiers then
local processed_qualifiers = {}
for _, qualifier in ipairs(genderspec.qualifiers) do
m_table.insertIfNot(processed_qualifiers,
iut.expand_footnote_or_references(qualifier, "return raw", "no parse refs"))
end
genderspec.qualifiers = processed_qualifiers
end
end
end
-- Process the specs in `arg_specs` given for dim=, m=, f=, n= or sg= and store the results in `slot` in
-- `alternant_multiword_spec.forms`. `arg_specs` is a list of specs, each of which is a comma-separated or
-- colon-separated string of specs, where each spec may be a suffix like "in", or a suffix with umlaut like
-- "^chen", or a full form beginning with a capital letter or exclamation point. Suffixes are added onto the lemma
-- with -e removed if present. `default` is the default value to use if "+" is given as a spec, and `literal_default`,
-- if given, indicates that `default` is always a literal (full) form; otherwise, it `default` begins with a
-- lowercase letter, it is taken as a suffix. (This is used in cases like the feminine of [[ordenlicher Professor]],
-- which is generated as "ordentiche Professorin"; we don't want this interpreted as a suffix.) `desc` is an English
-- description of the form whose specs are being processed, for display in error messages.
local function process_dim_m_f_n(alternant_multiword_spec, arg_specs, default, literal_default, slot, desc)
-- We don't want footnotes attached to a lemma to end up in the output. These footnotes typically get there if the
-- syntax `.[footnote]` is used, which attaches a footnote to every form.
local lemmas = export.get_lemmas(alternant_multiword_spec, nil, "remove footnotes")
lemmas = iut.map_forms(lemmas, function(form)
return rsub(form, "e$", "")
end)
for _, spec in ipairs(arg_specs) do
local function parse_err(msg)
error(msg .. ": " .. spec)
end
local segments = put.parse_balanced_segment_run(spec, "[", "]")
-- Allow comma (preferred) or colon as separator.
local ending_specs = com.fetch_specs(segments, "[,:]", desc, nil, parse_err)
-- FIXME, this should propagate the 'ss' property upwards
local props = {}
local function do_combine_stem_ending(stem, ending)
return combine_stem_ending(props, stem, ending)
end
local function process(stem, ending)
iut.add_forms(alternant_multiword_spec.forms, slot, stem or lemmas, ending, do_combine_stem_ending)
end
process_spec(ending_specs, nil, default, literal_default, desc, process)
end
end
local function show_forms(alternant_multiword_spec)
local lemmas = export.get_lemmas(alternant_multiword_spec)
local props = {
lang = lang,
lemmas = lemmas,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked_and_articles
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked_and_articles
or noun_slot_list_with_linked_and_articles,
}
iut.show_forms(alternant_multiword_spec.forms, props)
end
local noun_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="3" style="{BG2};width:46%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[indefinite article|indef.]]
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_both_no_indef = [=[
<div class="NavFrame" style="width:93%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:15%" |
! colspan="2" style="{BG2};width:39%" | singular
! colspan="2" style="{BG2};width:39%" | plural
|-
! style="{BG3}" |
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_abl_voc = [=[
|-
! style="{BG3}" | ablative
| style="{BG4}" | {art_ind_abl_s}
| style="{BG4}" | {art_def_abl_s}
| {abl_s}
|-
! style="{BG3}" | vocative
| style="{BG4}" | {art_ind_voc_s}
| style="{BG4}" | {art_def_voc_s}
| {voc_s}]=]
local noun_template_sg = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="3" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[indefinite article|indef.]]
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_sg_no_indef = [=[
<div class="NavFrame" style="width:50%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | singular
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_s}
| {nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_s}
| {gen_s}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_s}
| {dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_s}
| {acc_s}{abl_voc_clause}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_pl = [=[
<div class="NavFrame" style="width:61%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! style="{BG2};width:24.6%" |
! colspan="2" style="{BG2};" | plural
|-
! style="{BG3}" |
! style="{BG3};width:11.5%" | [[definite article|def.]]
! style="{BG3};width:52.5%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_surname = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-{decl_type}"
! rowspan="2" style="{BG2};width:11%" |
! colspan="6" style="{BG2}" | singular
! colspan="2" rowspan="2" style="{BG2}" | plural
|-
! colspan="3" style="{BG2}" | masculine
! colspan="3" style="{BG2}" | feminine
|-
! style="{BG3}" |
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[indefinite article|indef.]]
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
! style="{BG3};width:4%" | [[definite article|def.]]
! style="{BG3};width:23%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | {art_ind_nom_m_s}
| style="{BG4}" | {art_def_nom_m_s}
| {nom_m_s}
| style="{BG4}" | {art_ind_nom_f_s}
| style="{BG4}" | {art_def_nom_f_s}
| {nom_f_s}
| style="{BG4}" | {art_def_nom_p}
| {nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4}" | {art_ind_gen_m_s}
| style="{BG4}" | {art_def_gen_m_s}
| {gen_m_s}
| style="{BG4}" | {art_ind_gen_f_s}
| style="{BG4}" | {art_def_gen_f_s}
| {gen_f_s}
| style="{BG4}" | {art_def_gen_p}
| {gen_p}
|-
! style="{BG3}" | dative
| style="{BG4}" | {art_ind_dat_m_s}
| style="{BG4}" | {art_def_dat_m_s}
| {dat_m_s}
| style="{BG4}" | {art_ind_dat_f_s}
| style="{BG4}" | {art_def_dat_f_s}
| {dat_f_s}
| style="{BG4}" | {art_def_dat_p}
| {dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4}" | {art_ind_acc_m_s}
| style="{BG4}" | {art_def_acc_m_s}
| {acc_m_s}
| style="{BG4}" | {art_ind_acc_f_s}
| style="{BG4}" | {art_def_acc_f_s}
| {acc_f_s}
| style="{BG4}" | {art_def_acc_p}
| {acc_p}
|{\cl}{notes_clause}</div></div>]=]
local noun_template_langname = [=[
<div class="NavFrame" style="width:100%">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table inflection-table-de inflection-table-de-langname"
! style="{BG2};width:15%" |
! colspan="5" style="{BG2};width:85%" | singular ''([[Wiktionary:German entry guidelines#Declension of language names|explanation of the use and meaning of the forms]])''
|-
! style="{BG3}" |
! style="{BG3};width:14%" | (usually without article)
! style="{BG3};width:32%" | noun
! style="{BG3};width:7%" | [[definite article|def.]]
! style="{BG3};width:32%" | noun
|-
! style="{BG3}" | nominative
| style="{BG4}" | ({art_def_nom_s})
| {nom_s}
| style="{BG4}" | {art_def_nom_s}
| {nom_s_alt}
|-
! style="{BG3}" | genitive
| style="{BG4}" | ({art_def_gen_s})
| {gen_s}
| style="{BG4}" | {art_def_gen_s}
| {gen_s_alt}
|-
! style="{BG3}" | dative
| style="{BG4}" | ({art_def_dat_s})
| {dat_s}
| style="{BG4}" | {art_def_dat_s}
| {dat_s_alt}
|-
! style="{BG3}" | accusative
| style="{BG4}" | ({art_def_acc_s})
| {acc_s}
| style="{BG4}" | {art_def_acc_s}
| {acc_s_alt}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_both = [=[
<div class="NavFrame">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{\op}| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
! colspan="2" style="{BG3}" | plural
|-
! style="{BG2}" | {gender}
! colspan="4" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
| colspan="2" | {str_nom_p}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
| colspan="2" | {str_gen_p}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
| colspan="2" | {str_dat_p}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
| colspan="2" | {str_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
| style="{BG4};width:5em" | {art_def_nom_p}
| {wk_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
| style="{BG4};width:5em" | {art_def_gen_p}
| {wk_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
| style="{BG4};width:5em" | {art_def_dat_p}
| {wk_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
| style="{BG4};width:5em" | {art_def_acc_p}
| {wk_acc_p}
|-
! style="{BG2}" |
! colspan="4" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
| style="{BG4};width:5em" | {art_ind_nom_p}
| {mix_nom_p}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
| style="{BG4};width:5em" | {art_ind_gen_p}
| {mix_gen_p}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
| style="{BG4};width:5em" | {art_ind_dat_p}
| {mix_dat_p}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
| style="{BG4};width:5em" | {art_ind_acc_p}
| {mix_acc_p}
|{\cl}{notes_clause}</div></div>]=]
local adjectival_template_sg = [=[
<div class="NavFrame" style="width:500px">
<div class="NavHead">{title}{annotation}</div>
<div class="NavContent">
{| style="border: 1px solid var(--wikt-palette-darkgrey,#505050); border-collapse:collapse; {BG1}; text-align:center; width:100%" class="inflection-table"
! style="{BG3};width:15%" |
! colspan="2" style="{BG3}" | singular
|-
! style="{BG2}" | {gender}
! colspan="2" style="{BG2}" | strong declension
|-
! style="{BG3}" | nominative
| colspan="2" | {str_nom_s}
|-
! style="{BG3}" | genitive
| colspan="2" | {str_gen_s}
|-
! style="{BG3}" | dative
| colspan="2" | {str_dat_s}
|-
! style="{BG3}" | accusative
| colspan="2" | {str_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | weak declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_def_nom_s}
| {wk_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_def_gen_s}
| {wk_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_def_dat_s}
| {wk_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_def_acc_s}
| {wk_acc_s}
|-
! style="{BG2}" |
! colspan="2" style="{BG2}" | mixed declension
|-
! style="{BG3}" | nominative
| style="{BG4};width:5em" | {art_ind_nom_s}
| {mix_nom_s}
|-
! style="{BG3}" | genitive
| style="{BG4};width:5em" | {art_ind_gen_s}
| {mix_gen_s}
|-
! style="{BG3}" | dative
| style="{BG4};width:5em" | {art_ind_dat_s}
| {mix_dat_s}
|-
! style="{BG3}" | accusative
| style="{BG4};width:5em" | {art_ind_acc_s}
| {mix_acc_s}
|{\cl}{notes_clause}</div></div>]=]
local notes_template = [===[
<div style="width:100%;text-align:left;background:var(--wikt-palette-lightblue,#d9ebff);color:inherit">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
local function make_table(alternant_multiword_spec)
local forms = alternant_multiword_spec.forms
-- dark mode support
forms.BG1 = "background:var(--wikt-palette-white,#ffffff);color:inherit"
forms.BG2 = "background:var(--wikt-palette-grey,#9e9e9e);color:inherit"
forms.BG3 = "background:var(--wikt-palette-lightgrey,#cccccc);color:inherit"
forms.BG4 = "background:var(--wikt-palette-lightergrey,#eeeeee);color:inherit"
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = 'Declension of <i lang="de" class="Latn">' .. forms.lemma .. '</i>'
end
local annotation = alternant_multiword_spec.annotation
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " [<span style=\"font-size: smaller;\">" .. annotation .. "</span>]"
end
local table_spec
if alternant_multiword_spec.props.surname then
table_spec = noun_template_surname
elseif alternant_multiword_spec.props.langname then
table_spec = noun_template_langname
elseif alternant_multiword_spec.props.overall_adj then
table_spec =
alternant_multiword_spec.number == "sg" and adjectival_template_sg or
alternant_multiword_spec.number == "pl" and rsub(rsub(adjectival_template_sg, "singular", "plural"), "_s}", "_p}") or
adjectival_template_both
if alternant_multiword_spec.number == "pl" then
forms.gender = ""
else
local genderdesc_parts = {}
for _, gender in ipairs(alternant_multiword_spec.genders) do
table.insert(genderdesc_parts, gender_spec_to_full_gender[gender.spec])
end
forms.gender = "''" .. table.concat(genderdesc_parts, " or ") .. " gender ''"
end
else
local no_indef = alternant_multiword_spec.props.toponym or alternant_multiword_spec.props.article
table_spec =
alternant_multiword_spec.number == "sg" and (no_indef and noun_template_sg_no_indef or noun_template_sg) or
alternant_multiword_spec.number == "pl" and noun_template_pl or
(no_indef and noun_template_both_no_indef or noun_template_both)
if forms.abl_s ~= "—" or forms.voc_s ~= "—" then
forms.abl_voc_clause = m_string_utilities.format(noun_template_abl_voc, forms)
else
forms.abl_voc_clause = ""
end
end
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format(notes_template, forms) or ""
return m_string_utilities.format(table_spec, forms)
end
-- Externally callable function to parse and decline a noun given user-specified arguments. Return value is
-- ALTERNANT_MULTIWORD_SPEC, an object where the declined forms are in `ALTERNANT_MULTIWORD_SPEC.forms` for each slot.
-- If there are no values for a slot, the slot key will be missing. The value for a given slot is a list of objects
-- {form=FORM, footnotes=FOOTNOTES}.
function export.do_generate_forms(parent_args, pos, from_headword, is_proper, def)
local params = {
[1] = {required = true, default = "Haus<n,es,^er>"},
pagename = {},
}
if from_headword or pretend_from_headword then
params["head"] = {list = true}
params["f"] = {list = true}
params["m"] = {list = true}
params["n"] = {list = true}
params["dim"] = {list = true}
params["sg"] = {list = true}
params["id"] = {}
params["sort"] = {}
params["splithyph"] = {type = "boolean"}
params["nolinkhead"] = {type = "boolean"}
end
local args = require("Module:parameters").process(parent_args, params)
local arg1 = args[1]
local need_surrounding_angle_brackets = true
-- Check whether we need to add <...> around the argument. If the
-- argument has no < in it, we definitely do. Otherwise, we need to
-- parse the balanced [...] and <...> and add <...> only if there isn't
-- a top-level <...>. We check for [...] because there might be angle
-- brackets inside of them (HTML tags in qualifiers or <<name:...>> and
-- such in references).
if arg1:find("<") then
local segments = put.parse_multi_delimiter_balanced_segment_run(arg1, {{"<", ">"}, {"[", "]"}})
for i = 2, #segments, 2 do
if segments[i]:find("^<.*>$") then
need_surrounding_angle_brackets = false
break
end
end
end
if need_surrounding_angle_brackets then
arg1 = "<" .. arg1 .. ">"
end
local pagename = args.pagename or mw.title.getCurrentTitle().text
local function do_parse_indicator_spec(angle_bracket_spec, lemma)
return parse_indicator_spec(angle_bracket_spec, lemma, pagename)
end
local parse_props = {
parse_indicator_spec = do_parse_indicator_spec,
allow_default_indicator = true,
allow_blank_lemma = true,
}
local alternant_multiword_spec = iut.parse_inflected_text(arg1, parse_props)
alternant_multiword_spec.args = args
alternant_multiword_spec.props = {}
alternant_multiword_spec.props.is_proper = is_proper
detect_all_indicator_specs(alternant_multiword_spec)
local default_number =
(alternant_multiword_spec.props.is_proper or alternant_multiword_spec.props.toponym) and "sg" or "both"
propagate_properties(alternant_multiword_spec, "number", default_number, "both")
-- FIXME, maybe should check that noun genders match adjective genders
determine_adjectival_genders(alternant_multiword_spec)
determine_noun_status(alternant_multiword_spec)
local inflect_props = {
skip_slot = function(slot)
return skip_slot(alternant_multiword_spec.number, slot)
end,
slot_list = alternant_multiword_spec.props.surname and surname_slot_list_with_linked
or alternant_multiword_spec.props.langname and langname_slot_list_with_linked
or alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked
or noun_slot_list_with_linked,
inflect_word_spec = decline_noun_or_adjective,
}
iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props)
compute_articles(alternant_multiword_spec)
compute_headword_genders(alternant_multiword_spec)
if not pos then
-- Compute part of speech for categories. Fetch the first lemma, or failing that (which would only happen
-- if the user overrides the nom_sg and nom_p to be missing) the pagename. If it begins with a hyphen,
-- it's a suffix, else a noun (proper nouns get categorized like nouns).
local lemmas = export.get_lemmas(alternant_multiword_spec)
local first_lemma = #lemmas > 0 and lemmas[1].form or pagename
pos = rfind(first_lemma, "^%-") and "အဆက်လက္ကရဴ" or "နာမ်"
end
alternant_multiword_spec.pos = pos
compute_categories_and_annotation(alternant_multiword_spec)
if from_headword or pretend_from_headword then
process_dim_m_f_n(alternant_multiword_spec, args.dim, "^chen", nil, "dim", "diminutive")
process_dim_m_f_n(alternant_multiword_spec, args.f, alternant_multiword_spec.forms.f_equiv,
"literal default", "f", "feminine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.m, alternant_multiword_spec.forms.m_equiv,
"literal default", "m", "masculine equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.n, alternant_multiword_spec.forms.n_equiv,
"literal default", "n", "neuter equivalent")
process_dim_m_f_n(alternant_multiword_spec, args.sg, nil, nil, "sg", "singular")
end
return alternant_multiword_spec
end
-- Entry point for {{de-ndecl}}. Template-callable function to parse and decline a noun given
-- user-specified arguments and generate a displayable table of the declined forms.
function export.show(frame)
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
show_forms(alternant_multiword_spec)
-- FIXME!
alternant_multiword_spec.forms.decl_type = "foo"
return make_table(alternant_multiword_spec) .. require("Module:utilities").format_categories(
alternant_multiword_spec.categories, lang, nil, nil, force_cat)
end
-- Concatenate all forms of all slots into a single string of the form "SLOT=FORM,FORM,...|SLOT=FORM,FORM,...|...".
-- Embedded pipe symbols (as might occur in embedded links) are converted to <!>. If INCLUDE_PROPS is given, also
-- include additional properties (currently, g= for headword genders). This is for use by bots.
local function concat_forms(alternant_multiword_spec, include_props)
local ins_text = {}
for _, slotaccel in ipairs(
alternant_multiword_spec.props.surname and surname_slot_list_with_linked or
alternant_multiword_spec.props.langname and langname_slot_list_with_linked or
alternant_multiword_spec.props.overall_adj and adjectival_slot_list_with_linked or
noun_slot_list_with_linked
) do
local slot, accel = unpack(slotaccel)
local formtext = iut.concat_forms_in_slot(alternant_multiword_spec.forms[slot])
if formtext then
table.insert(ins_text, slot .. "=" .. formtext)
end
end
if include_props then
table.insert(ins_text, "g=" .. table.concat(alternant_multiword_spec.genders, ","))
end
return table.concat(ins_text, "|")
end
-- Template-callable function to parse and decline a noun given user-specified arguments and return
-- the forms as a string of the same form as documented in concat_forms() above.
function export.generate_forms(frame)
local include_props = frame.args["include_props"]
local parent_args = frame:getParent().args
local alternant_multiword_spec = export.do_generate_forms(parent_args)
return concat_forms(alternant_multiword_spec, include_props)
end
return export
jbcthoht61iibzebp4uiso0a9uai1x8
monish
0
24057
392607
267599
2026-04-13T12:01:14Z
咽頭べさ
33
392607
wikitext
text/x-wiki
=={{=en=}}==
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{inh|en|ang|monesten}}
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|en|/ˈmɒnɪʃ/}}
* {{audio|en|LL-Q1860 (eng)-Vealhurl-monish.wav|a=Southern England}}
===ကြိယာ===
{{en-verb}}
# သကဵုဒၠောံဗ္တောန်၊ သကဵုမကဵုသတိ။
ibjhluh2nuac22u4vxoae99oqujqnuf
ကဏ္ဍ:နာမ်ဗဝ်လ်တဳဂမၠိုၚ်
14
29712
392679
41438
2026-04-14T08:13:10Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[ကဏ္ဍ:နာမ် ဗဝ်လ်တဳ]] ဇရေင် [[ကဏ္ဍ:နာမ်ဗဝ်လ်တဳဂမၠိုၚ်]] သီုကဵု ဟွံဂွံ ဂိုင်စွံလဝ် မကလေင်ပညုင်
41438
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာဗဝ်လ်တဳ]]
ey5tip3574op3r3bcfeu8lvjd1i6o6b
ကဏ္ဍ:ဝေါဟာအဓိကဗဝ်လ်တဳဂမၠိုၚ်
14
29714
392678
172500
2026-04-14T08:12:48Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[ကဏ္ဍ:ဝေါဟာဗဝ်လ်တဳနွံပ္ဍဲအဘိဓာန်ဂမၠိုၚ်]] ဇရေင် [[ကဏ္ဍ:ဝေါဟာအဓိကဗဝ်လ်တဳဂမၠိုၚ်]] သီုကဵု ဟွံဂွံ ဂိုင်စွံလဝ် မကလေင်ပညုင်
41440
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာဗဝ်လ်တဳ]]
ey5tip3574op3r3bcfeu8lvjd1i6o6b
မဝ်ဂျူ:bo-common
828
79752
392686
104696
2026-04-14T08:34:03Z
咽頭べさ
33
392686
Scribunto
text/plain
local m_str_utils = require("Module:string utilities")
local codepoint = m_str_utils.codepoint
local gsub = m_str_utils.gsub
local len = m_str_utils.len
local match = m_str_utils.match
local sub = m_str_utils.sub
local u = m_str_utils.char
local upper = m_str_utils.upper
local export = {}
function export.preconvert(text)
return (gsub(text, "([ཀ-ཇཉ-ཬྈ-ྌ༘༙༵༷༾༿ཱ-ྃ྆྇])༹", function(m1) return u(codepoint(m1) + 0xF0000) end))
end
function export.invalidChecks(text)
return {
len(gsub(text, "[^ཀ-ཇཉ-ཬྈ-ྌ---]", "")) > 6, -- 5 & 6 letter syllables are very rare
}
end
function export.mainStackChecks(text)
return {
match(text, "[ཀ-ཇཉ-ཬྈ-ྌ---][ྍ-ྗྙ-ྼ--]+[༘༙༵༷༾༿ཱ-ྃ྆྇-]*"),
match(text, "[ཀ-ཇཉ-ཟཡ-ཬྈ-ྌ---][༘༙༵༷༾༿ཱ-ྃ྆྇-]+"),
match(text, "^འ[༘༙༵༷༾༿ཱ-ྃ྆྇-]+"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])[ཀ-ཇཉ-ཬྈ-ྌ---]྄"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ[༘༙༵༷༾༿ཱ-ྃ྆྇-]+$"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ"),
(len(text) == 3 or len(text) == 4) and match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ[ངམར]$"),
len(gsub(text, "྄", "")) == 1 and text,
len(gsub(text, "྄", "")) == 2 and match(text, "^([ཀ-ཇཉ-ཬྈ-ྌ---])[^྄]"),
len(gsub(text, "྄", "")) == 4 and match(text, "^[ཀ-ཇཉ-ཬྈ-ྌ---]྄?([ཀ-ཇཉ-ཬྈ-ྌ---])[^྄]"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])[^དས྄]$"),
match(text, "^[ཀཁང-ཇཉ-ཐན-ཕཙ-ཟཡ-ཬྈ-ྌ---]"),
match(text, "^([གདབམའ])[ཀ-ཇཉ-ཬྈ-ྌ---]྄"),
match(text, "^(ག)[^ཅཉཏདནཙཞཟཡཤས]"),
match(text, "^(ད)[^ཀགངཔབམ]"),
match(text, "^(བ)[^ཀགཅཏདཙཞཟཤས]"),
match(text, "^(མ)[^ཁགངཆཇཉཐདནཚཛ]"),
match(text, "^(འ)[^ཁགཆཇཐདཕབཚཛ]"),
match(text, "([^གངབམ])ས྄?$"),
match(text, "([^ནརལ])ད྄?$")
}
end
function export.postconvert(text)
return (gsub(text, "([-])", function(m1) return u(codepoint(m1) - 0xF0000) .. "༹" end))
end
export.ambiguousSyllables = {
["མངས"] = "མ", ["མགས"] = "མ", ["དབས"] = "བ", ["དངས"] = "ད", ["དགས"] = "ག", ["དམས"] = "མ", ["བགས"] = "བ", ["འབས"] = "བ", ["འགས"] = "ག", ["གནད"] = "ན", ["མནད"] = "ན"
}
function export.new(frame)
local title = mw.loadData("Module:headword/data").pagename
local args = frame:getParent().args
local pron = args["p"] or false
local pos = args[1] or ""
local def = args[2] or "{{rfdef|bo}}"
local pos2 = args[3] or (args[4] and "" or false)
local def2 = args[4] or "{{rfdef|bo}}"
local pos3 = args[5] or (args[6] and "" or false)
local def3 = args[6] or "{{rfdef|bo}}"
local etym = args["e"] or false
local head = args["head"] or false
local cat = args["cat"] or false
local reg = args["reg"] or false
local otb = args["otb"] or false
local result = ""
local function genTitle(text)
local pos_title = {
[""] = "Noun", ["n"] = "Noun", ["pn"] = "Proper noun", ["propn"] = "Proper noun", ["pron"] = "Pronoun",
["v"] = "Verb", ["vf"] = "Verb", ["a"] = "Adjective", ["adj"] = "Adjective", ["adv"] = "Adverb",
["prep"] = "Preposition", ["postp"] = "Postposition", ["conj"] = "Conjunction",
["part"] = "Particle", ["suf"] = "Suffix",
["prov"] = "Proverb", ["id"] = "Idiom", ["ph"] = "Phrase", ["intj"] = "Interjection", ["interj"] = "Interjection",
["cl"] = "Classifier", ["cls"] = "Classifier", ["num"] = "Numeral", ["abb"] = "Abbreviation", ["deter"] = "Determiner"
};
return pos_title[text] or upper(sub(text, 1, 1)) .. sub(text, 2, -1)
end
local function genHead(text)
local pos_head = {
[""] = "noun", ["n"] = "noun", ["pn"] = "proper noun", ["propn"] = "proper noun", ["v"] = "verb", ["vf"] = "verb form", ["a"] = "adj",
["postp"] = "post", ["conj"] = "con", ["part"] = "particle", ["pron"] = "pronoun",
["prov"] = "proverb", ["id"] = "idiom", ["ph"] = "phrase", ["intj"] = "interj",
["abb"] = "abbr", ["cl"] = "classifier", ["deter"] = "det"
};
return pos_head[text] or text
end
local function other(class, title, args)
local code = ""
if args[class] then
code = code .. "\n\n===" .. title .. "===\n* {{l|bo|" .. args[class] .. "}}"
if args[class .. "2"] then
code = code .. "\n* {{l|bo|" .. args[class .. "2"] .. "}}"
if args[class .. "3"] then
code = code .. "\n* {{l|bo|" .. args[class .. "3"] .. "}}"
if args[class .. "4"] then
code = code .. "\n* {{l|bo|" .. args[class .. "4"] .. "}}"
end
end
end
end
return code
end
result = result .. "==Tibetan=="
if args["wp"] then result = result .. "\n{{wikipedia|lang=bo" ..
(args["wp"] == "y" and "" or "|" .. args["wp"]) .. "}}" end
result = result .. other("alt", "Alternative forms", args)
if etym then result = result .. "\n\n===Etymology===\n" .. etym end
result = result .. "\n\n===Pronunciation===\n{{bo-pron" .. (pron and "|" .. pron or "") .. (otb and "|otb=-" or "") .. "}}"
result = result .. "\n\n===" .. genTitle(pos) .. "===\n{{bo-" .. genHead(pos) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def
if reg then result = result .. "\n{{bo-registers|" .. reg .. "}}" end
result = result .. other("syn", "=Synonyms=", args)
result = result .. other("ant", "=Antonyms=", args)
result = result .. other("der", "=Derived terms=", args)
result = result .. other("also", "=See also=", args)
if pos2 then
result = result .. "\n\n===" .. genTitle(pos2) .. "===\n{{bo-" .. genHead(pos2) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def2
end
if pos3 then
result = result .. "\n\n===" .. genTitle(pos3) .. "===\n{{bo-" .. genHead(pos3) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def3
end
if cat then result = result .. "\n\n{{C|bo|" .. cat .. "}}" end
return result
end
function export.verb(frame)
local title = mw.loadData("Module:headword/data").pagename
title = require("Module:Tibt-translit").tr(title, "bo", "Tibt")
local s = { match(title, (gsub(title, ".", "(.)"))) }
local i = #s - 1
local j = i - 1
if match(s[i], "[aeiourl']") or (s[j] == "n" and s[i] == "g") then
return "བ"
end
return "པ"
end
function export.removePa(frame)
local title = mw.loadData("Module:headword/data").pagename
return (gsub(title, "་[པབ]$", ""))
end
return export
6e4fxmsueah8keuknd833idlulq1xo2
392688
392686
2026-04-14T08:45:08Z
咽頭べさ
33
392688
Scribunto
text/plain
local m_str_utils = require("Module:string utilities")
local codepoint = m_str_utils.codepoint
local gsub = m_str_utils.gsub
local len = m_str_utils.len
local match = m_str_utils.match
local sub = m_str_utils.sub
local u = m_str_utils.char
local upper = m_str_utils.upper
local export = {}
function export.preconvert(text)
return (gsub(text, "([ཀ-ཇཉ-ཬྈ-ྌ༘༙༵༷༾༿ཱ-ྃ྆྇])༹", function(m1) return u(codepoint(m1) + 0xF0000) end))
end
function export.invalidChecks(text)
return {
len(gsub(text, "[^ཀ-ཇཉ-ཬྈ-ྌ---]", "")) > 6, -- 5 & 6 letter syllables are very rare
}
end
function export.mainStackChecks(text)
return {
match(text, "[ཀ-ཇཉ-ཬྈ-ྌ---][ྍ-ྗྙ-ྼ--]+[༘༙༵༷༾༿ཱ-ྃ྆྇-]*"),
match(text, "[ཀ-ཇཉ-ཟཡ-ཬྈ-ྌ---][༘༙༵༷༾༿ཱ-ྃ྆྇-]+"),
match(text, "^འ[༘༙༵༷༾༿ཱ-ྃ྆྇-]+"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])[ཀ-ཇཉ-ཬྈ-ྌ---]྄"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ[༘༙༵༷༾༿ཱ-ྃ྆྇-]+$"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ"),
(len(text) == 3 or len(text) == 4) and match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])འ[ངམར]$"),
len(gsub(text, "྄", "")) == 1 and text,
len(gsub(text, "྄", "")) == 2 and match(text, "^([ཀ-ཇཉ-ཬྈ-ྌ---])[^྄]"),
len(gsub(text, "྄", "")) == 4 and match(text, "^[ཀ-ཇཉ-ཬྈ-ྌ---]྄?([ཀ-ཇཉ-ཬྈ-ྌ---])[^྄]"),
match(text, "([ཀ-ཇཉ-ཬྈ-ྌ---])[^དས྄]$"),
match(text, "^[ཀཁང-ཇཉ-ཐན-ཕཙ-ཟཡ-ཬྈ-ྌ---]"),
match(text, "^([གདབམའ])[ཀ-ཇཉ-ཬྈ-ྌ---]྄"),
match(text, "^(ག)[^ཅཉཏདནཙཞཟཡཤས]"),
match(text, "^(ད)[^ཀགངཔབམ]"),
match(text, "^(བ)[^ཀགཅཏདཙཞཟཤས]"),
match(text, "^(མ)[^ཁགངཆཇཉཐདནཚཛ]"),
match(text, "^(འ)[^ཁགཆཇཐདཕབཚཛ]"),
match(text, "([^གངབམ])ས྄?$"),
match(text, "([^ནརལ])ད྄?$")
}
end
function export.postconvert(text)
return (gsub(text, "([-])", function(m1) return u(codepoint(m1) - 0xF0000) .. "༹" end))
end
export.ambiguousSyllables = {
["མངས"] = "མ", ["མགས"] = "མ", ["དབས"] = "བ", ["དངས"] = "ད", ["དགས"] = "ག", ["དམས"] = "མ", ["བགས"] = "བ", ["འབས"] = "བ", ["འགས"] = "ག", ["གནད"] = "ན", ["མནད"] = "ན"
}
function export.new(frame)
local title = mw.loadData("Module:headword/data").pagename
local args = frame:getParent().args
local pron = args["p"] or false
local pos = args[1] or ""
local def = args[2] or "{{rfdef|bo}}"
local pos2 = args[3] or (args[4] and "" or false)
local def2 = args[4] or "{{rfdef|bo}}"
local pos3 = args[5] or (args[6] and "" or false)
local def3 = args[6] or "{{rfdef|bo}}"
local etym = args["e"] or false
local head = args["head"] or false
local cat = args["cat"] or false
local reg = args["reg"] or false
local otb = args["otb"] or false
local result = ""
local function genTitle(text)
local pos_title = {
[""] = "နာမ်", ["n"] = "နာမ်", ["pn"] = "နာမ်မကိတ်ညဳ", ["propn"] = "နာမ်မကိတ်ညဳ", ["pron"] = "သဗ္ဗနာမ်",
["v"] = "ကြိယာ", ["vf"] = "ကြိယာ", ["a"] = "နာမဝိသေသန", ["adj"] = "နာမဝိသေသန", ["adv"] = "ကြိယာဝိသေသန",
["prep"] = "ဝိဘတ်", ["postp"] = "ဝိဘတ်", ["conj"] = "သမ္ဗန္ဓ",
["part"] = "ကၞာတ်အမှိက်", ["suf"] = "အဆက်လက္ကရဴ",
["prov"] = "ပေါရာဏာံပေါရာဒါံ", ["id"] = "Idiom", ["ph"] = "ဝါကျ", ["intj"] = "အာမေဍိက်", ["interj"] = "အာမေဍိက်",
["cl"] = "နာမ်ပါ်ကၞာတ်", ["cls"] = "နာမ်ပါ်ကၞာတ်", ["num"] = "ဂၞန်သၚ်္ချာ", ["abb"] = "Abbreviation", ["deter"] = "ဖျေံလဝ်သန္နိဋ္ဌာန်"
};
return pos_title[text] or upper(sub(text, 1, 1)) .. sub(text, 2, -1)
end
local function genHead(text)
local pos_head = {
[""] = "noun", ["n"] = "noun", ["pn"] = "proper noun", ["propn"] = "proper noun", ["v"] = "verb", ["vf"] = "verb form", ["a"] = "adj",
["postp"] = "post", ["conj"] = "con", ["part"] = "particle", ["pron"] = "pronoun",
["prov"] = "proverb", ["id"] = "idiom", ["ph"] = "phrase", ["intj"] = "interj",
["abb"] = "abbr", ["cl"] = "classifier", ["deter"] = "det"
};
return pos_head[text] or text
end
local function other(class, title, args)
local code = ""
if args[class] then
code = code .. "\n\n===" .. title .. "===\n* {{l|bo|" .. args[class] .. "}}"
if args[class .. "2"] then
code = code .. "\n* {{l|bo|" .. args[class .. "2"] .. "}}"
if args[class .. "3"] then
code = code .. "\n* {{l|bo|" .. args[class .. "3"] .. "}}"
if args[class .. "4"] then
code = code .. "\n* {{l|bo|" .. args[class .. "4"] .. "}}"
end
end
end
end
return code
end
result = result .. "==တိဗိတ်=="
if args["wp"] then result = result .. "\n{{wikipedia|lang=bo" ..
(args["wp"] == "y" and "" or "|" .. args["wp"]) .. "}}" end
result = result .. other("alt", "ပွံၚ်နဲတၞဟ်", args)
if etym then result = result .. "\n\n===နိရုတ်===\n" .. etym end
result = result .. "\n\n===ဗွဟ်ရမ္သာၚ်===\n{{bo-pron" .. (pron and "|" .. pron or "") .. (otb and "|otb=-" or "") .. "}}"
result = result .. "\n\n===" .. genTitle(pos) .. "===\n{{bo-" .. genHead(pos) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def
if reg then result = result .. "\n{{bo-registers|" .. reg .. "}}" end
result = result .. other("syn", "=Synonyms=", args)
result = result .. other("ant", "=Antonyms=", args)
result = result .. other("der", "=Derived terms=", args)
result = result .. other("also", "=See also=", args)
if pos2 then
result = result .. "\n\n===" .. genTitle(pos2) .. "===\n{{bo-" .. genHead(pos2) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def2
end
if pos3 then
result = result .. "\n\n===" .. genTitle(pos3) .. "===\n{{bo-" .. genHead(pos3) .. (head and ("|head=" .. head) or "") .. "}}\n\n# " .. def3
end
if cat then result = result .. "\n\n{{C|bo|" .. cat .. "}}" end
return result
end
function export.verb(frame)
local title = mw.loadData("Module:headword/data").pagename
title = require("Module:Tibt-translit").tr(title, "bo", "Tibt")
local s = { match(title, (gsub(title, ".", "(.)"))) }
local i = #s - 1
local j = i - 1
if match(s[i], "[aeiourl']") or (s[j] == "n" and s[i] == "g") then
return "བ"
end
return "པ"
end
function export.removePa(frame)
local title = mw.loadData("Module:headword/data").pagename
return (gsub(title, "་[པབ]$", ""))
end
return export
cfqmzb1par35pv0p5r7bwm87qqr36c6
မဝ်ဂျူ:labels/data/lang/en
828
108363
392612
392523
2026-04-13T12:44:01Z
咽頭べさ
33
392612
Scribunto
text/plain
local labels = {}
------------------------------------ North America ------------------------------------
labels["North America"] = {
aliases = {"North American"},
display = "[[Canada|ခေန်နာဒါ]]၊ [[American English|အမေရိကာန်]]",
regional_categories = {"ခေန်နာဒါ", "အမေရိကာန်"},
}
labels["caricature Black"] = {
display = "caricatures of Black speech",
def = "any of various caricatures of Black speech by non-Black writers",
aliases = {"caricature black", "a caricature of Black speech", "caricatures of Black speech"},
plain_categories = "Caricatures of Black English",
form_of_display = "a caricature of Black"
-- for use in T:pronunciation spelling of. use in T:altform and T:altspell is not intended and looks bad.
}
------------- Canada -------------
labels["Canada"] = {
aliases = {"CA", "Canadian", "CanE", "Canadian English"},
Wikipedia = "en:Canadian English",
display = "ခေန်နာဒါ",
regional_categories = "ခေန်နာဒါ",
parent = "rawposcat:North American English,Commonwealth",
}
labels["Acadia"] = {
region = "colonial [[Acadia]]",
aliases = {"Acadian"},
Wikipedia = true,
regional_categories = "Acadian",
parent = "Canada",
}
labels["Alberta"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Atlantic Canada"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = "Atlantic Canadian",
parent = "Canada",
}
labels["British Columbia"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Canadian Prairies"] = {
the = true,
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Labrador"] = {
Wikipedia = true,
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Manitoba"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Multicultural Toronto English"] = {
def = "the {{w|multiethnolect|multi-ethnic dialect}} of {{catlink|Canadian English}} used in the {{w|Greater Toronto Area}}, particularly among young non-white working-class speakers",
aliases = {"MTE"},
display = "MTE",
Wikipedia = true,
plain_categories = true,
parent = "Ontario",
}
labels["New Brunswick"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Newfoundland"] = {
Wikipedia = "Newfoundland English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Northwest Territories"] = {
region = "the [[Northwest Territories]] of [[Canada]]",
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Northwestern Ontario"] = {
aliases = {"northwestern Ontario", "Northwest Ontario", "northwest Ontario"},
Wikipedia = true,
regional_categories = true,
parent = "Ontario",
}
labels["Nova Scotia"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Nunavut"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Ontario"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Prince Edward Island"] = {
Wikipedia = true,
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Quebec"] = {
aliases = {"Québec"},
Wikipedia = "Quebec English",
regional_categories = true,
parent = "Canada",
}
labels["Saskatchewan"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Yukon"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
------------- US -------------
labels["US"] = {
region = "the [[United States]]",
aliases = {"U.S.", "United States", "United States of America", "USA", "US English", "U.S. English", "America", "American", "American English"},
Wikipedia = "en:American English",
display = "အမေရိကာန်",
regional_categories = "အမေရိကာန်",
parent = "rawposcat:North American English",
}
labels["African-American Vernacular"] = {
def = "the variety of [[English]] spoken, especially in urban communities, by most working-class and some middle-class [[African-American]]s",
addl = "It is a [[sociolect]] with significantly different grammatical characteristics from {{w|Standard English}}, especially in {{w|tense-aspect}} and [[negation]] constructions. Many African-American communities maintain [[diglossia]] between African-American Vernacular English (AAVE) and Standard English.",
aliases = {"AAVE", "African American Vernacular", "African American Vernacular English", "African-American Vernacular English", "BVE"},
Wikipedia = "African-American Vernacular English",
regional_categories = true,
parent = "African-American",
}
labels["African-American"] = {
prep = "by",
region = "[[African-American]]s in the [[United States]]",
aliases = {"AA", "African-American English", "African American", "African American English", "AAE"},
Wikipedia = "African-American English",
regional_categories = true,
parent = "US",
}
labels["Alabama"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Alaska"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northwestern US",
}
labels["Appalachia"] = {
aliases = {"Appalachian"},
Wikipedia = "en:Appalachian English",
display = "အေတ်ပလာချဳယျာ",
regional_categories = "အေတ်ပလာချဳယျာ",
parent = "US",
}
labels["Arizona"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southwestern US",
}
labels["Arkansas"] = {
Wikipedia = true,
regional_categories = "Arkansan",
parent = "South Midland US",
}
labels["Baltimore"] = {
Wikipedia = "Baltimore accent",
regional_categories = true,
parent = "Maryland",
}
labels["Boston"] = {
Wikipedia = "Boston accent",
regional_categories = true,
parent = "Massachusetts",
}
labels["Cajun"] = {
prep = "by",
region = "[[Cajun]]s in {{w|Acadiana|Southern Louisiana}}",
Wikipedia = "Cajun English",
regional_categories = true,
parent = "Louisiana",
}
labels["California"] = {
Wikipedia = "California English",
regional_categories = true,
parent = "Western US",
}
labels["Chicago"] = {
Wikipedia = {"Inland Northern American English", true},
regional_categories = true,
parent = "Illinois",
}
labels["Cincinnati"] = {
Wikipedia = "Midland American English#Cincinnati",
regional_categories = true,
parent = "Ohio,Kentucky",
}
labels["Colorado"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southwestern US",
}
labels["Connecticut"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["District of Columbia"] = {
region = "Washington, D.C.",
aliases = {"DC", "Washington, DC"},
Wikipedia = true,
regional_categories = "DC",
parent = "Mid-Atlantic US",
}
labels["Eastern New England"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["Florida"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Georgia (US)"] = {
region = "the state of [[Georgia]] in the [[United States]]",
display = "Georgia",
Wikipedia = "Georgia (U.S. state)",
regional_categories = true,
parent = "Southern US",
}
labels["Hawaii"] = {
Wikipedia = true,
regional_categories = "Hawaiian",
parent = "Western US",
}
labels["Illinois"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US,Northern US",
}
labels["Indiana"] = {
Wikipedia = "en:Indiana",
display = "အိန်ဒဳယျာနာ",
regional_categories = "အိန်ဒဳယျာနာ",
parent = "Midland US,Northern US",
}
labels["Kentucky"] = {
Wikipedia = true,
regional_categories = true,
parent = "South Midland US",
}
labels["Louisiana"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Maine"] = {
Wikipedia = "Maine accent",
regional_categories = true,
parent = "New England",
}
labels["Maryland"] = {
Wikipedia = true,
regional_categories = true,
parent = "Mid-Atlantic US",
}
labels["Massachusetts"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["Memphis"] = {
regional_categories = true,
parent = "Southern US",
}
labels["Michigan"] = {
Wikipedia = true,
regional_categories = true,
parent = "Upper Midwestern US",
}
labels["Mid-Atlantic US"] = {
region = "the [[Mid-Atlantic]] United States",
Wikipedia = "Mid-Atlantic American English",
regional_categories = true,
parent = "US",
}
labels["Midland US"] = {
region = "the American [[Midland]]",
Wikipedia = "Midland American English",
regional_categories = true,
parent = "Midwestern US",
}
labels["Midwestern US"] = {
region = "the [[Midwest]] of the [[United States]]",
aliases = {"Midwest US"},
Wikipedia = "Midwestern American English",
regional_categories = true,
parent = "US",
}
labels["Mississippi"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Missouri"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US",
}
labels["New England"] = {
Wikipedia = "en:New England English",
display = "အိန်ဂလာန်တၟိ",
regional_categories = "အိန်ဂလာန်တၟိ",
parent = "Northeastern US",
}
labels["New Jersey"] = {
Wikipedia = "en:New Jersey English",
display = "ဂျာသဳတၟိ",
regional_categories = "ဂျာသဳတၟိ",
parent = "Northeastern US",
}
labels["New Mexico"] = {
Wikipedia = "Western American English#New Mexico",
regional_categories = true,
parent = "Southwestern US",
}
labels["New Orleans"] = {
Wikipedia = "en:New Orleans English",
display = "နယူအေဝ်လေန်",
regional_categories = "နယူအေဝ်လေန်",
parent = "Louisiana",
}
labels["New York City"] = {
aliases = {"NYC"},
Wikipedia = "en:New York City English",
display = "ဍုၚ်နယူယံက်",
regional_categories = "ဍုၚ်နယူယံက်",
parent = "New York",
}
labels["New York"] = {
region = "the [[United States]] state of [[New York]]",
aliases = {"NY"},
Wikipedia = "en:New York English (disambiguation)",
display = "နယူယံက်",
regional_categories = "နယူယံက်",
parent = "Northeastern US",
}
labels["North Carolina"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
-- can be split off if enough entries in it arise; group with Midland US for now
labels["North Midland US"] = {
aliases = {"Northern Midland US"},
Wikipedia = "Midland American English",
regional_categories = "Midland US",
}
labels["Northeastern US"] = {
region = "the {{w|Northeastern United States}}",
aliases = {"Northeast US"},
Wikipedia = {"Northern American English#Northeastern American English"},
regional_categories = true,
parent = "Northern US",
}
-- can be split off if enough entries in it arise; group with California for now
labels["Northern California"] = {
Wikipedia = "California English",
regional_categories = "California",
}
labels["Northwestern US"] = {
region = "the {{w|Northwestern United States}}",
aliases = {"Northwest US", "Pacific Northwest"},
Wikipedia = {"Pacific Northwest English", "Northwestern United States"},
regional_categories = true,
parent = "Western US",
}
labels["Ohio"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US,Northern US",
}
labels["Oklahoma"] = {
Wikipedia = true,
regional_categories = true,
parent = "South Midland US",
}
labels["Pennsylvania Dutch English"] = {
prep = "by",
region = "{{w|Pennsylvania Dutch}} people in south-central [[Pennsylvania]]",
Wikipedia = true,
plain_categories = true,
parent = "Pennsylvania",
}
labels["Pennsylvania"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northeastern US",
}
-- can be split off if enough entries in it arise; group with Pennsylvania for now
labels["Philadelphia"] = {
Wikipedia = "Philadelphia English",
regional_categories = true,
parent = "Pennsylvania,Mid-Atlantic US",
}
-- can be split off if enough entries in it arise; group with Western Pennsylvania for now
labels["Pittsburgh"] = {
Wikipedia = "Western Pennsylvania English",
regional_categories = "Western Pennsylvania",
parent = "Pennsylvania",
}
labels["Pittsburghese"] = {
Wikipedia = "Western Pennsylvania English",
regional_categories = "Western Pennsylvania",
parent = "Pennsylvania",
}
labels["Rhode Island"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["South Carolina"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
-- can be split off if enough entries in it arise; group with Midland US for now
labels["South Midland US"] = {
aliases = {"Southern Midland US"},
Wikipedia = "Midland American English",
regional_categories = "Midland US",
}
-- can be split off if enough entries in it arise; group with California for now
labels["Southern California"] = {
Wikipedia = "California English",
regional_categories = "California",
}
labels["Southern US"] = {
region = "the {{w|Southern United States}}",
aliases = {"Southern American English", "southern US", "US South"},
Wikipedia = "en:Southern American English",
display = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "US",
}
labels["Southwestern US"] = {
region = "the {{w|Southwestern United States}}",
aliases = {"southwestern US", "Southwest US", "southwest US"},
Wikipedia = {"Western American English", "Southwestern United States"},
regional_categories = true,
parent = "Western US",
}
labels["St. Louis"] = {
Wikipedia = "St. Louis dialect",
regional_categories = true,
parent = "Missouri,Illinois",
}
labels["St. Vincent"] = {
Wikipedia = "Saint Vincent (Saint Vincent and the Grenadines)",
regional_categories = "Saint Vincentian",
parent = "Caribbean",
}
labels["Texas"] = {
Wikipedia = "Texan English",
regional_categories = true,
parent = "Southern US,Southwestern US",
}
labels["Upper Midwestern US"] = {
region = "the {{w|Upper Midwest}} of the [[United States]]",
aliases = {"Upper Midwest US"},
Wikipedia = {"North-Central American English", "Upper Midwest"},
regional_categories = true,
parent = "Midwestern US,Northern US",
}
labels["Vermont"] = {
Wikipedia = {"New England English", "Vermont"},
regional_categories = true,
parent = "New England",
}
labels["Virginia"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Western Pennsylvania"] = {
aliases = {"Western Pennsylvania English"},
Wikipedia = "Western Pennsylvania English",
regional_categories = true,
parent = "Pennsylvania",
}
labels["Western US"] = {
region = "the {{w|Western United States}}",
aliases = {"western US"},
Wikipedia = {"en:Western American English", "en:Western United States"},
display = "အမေရိကာန်လ္ပာ်ဖာပလိုတ်",
regional_categories = "အမေရိကာန်လ္ပာ်ဖာပလိုတ်",
parent = "US",
}
labels["Wisconsin"] = {
Wikipedia = true,
regional_categories = true,
parent = "Upper Midwestern US",
}
------------------------------------ Australia and New Zealand ------------------------------------
labels["Australian Aboriginal"] = {
prep = "by",
region = "[[Aboriginal]] people in [[Australia]]",
aliases = {"Australian aboriginal", "Australian Aboriginal English", "Australian aboriginal English", "Aboriginal Australian", "aboriginal Australian", "Aboriginal Australian English", "aboriginal Australian English"},
Wikipedia = "Australian Aboriginal English",
regional_categories = true,
parent = "Australia",
}
labels["Australia"] = {
aliases = {"Australian", "AU", "AuE", "Aus", "AusE", "General Australian"},
Wikipedia = "Australian English",
accent_Wikipedia = "Australian English phonology",
accent_display = "အမေရိကာန်နာနာသာ်",
regional_categories = "အဝ်သတြေလျာ",
parent = "Oceania,Commonwealth",
}
labels["Canberra"] = {
region = "the [[Australian Capital Territory]] ([[Canberra]])",
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["New South Wales"] = {
aliases = {"NSW"},
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["New Zealand"] = {
aliases = {"NZ", "NZE"},
Wikipedia = "en:New Zealand English",
accent_Wikipedia = "New Zealand English phonology",
display = "နယူဇြဳလာန်",
regional_categories = "နယူဇြဳလာန်",
parent = "Oceania,Commonwealth",
}
labels["Northern Territory"] = {
aliases = {"NT"},
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["Northern US"] = {
region = "the {{w|Northern United States}}",
aliases = {"Northern American English", "northern US", "US North"},
Wikipedia = "en:Northern American English",
display = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "US",
}
labels["Queensland"] = {
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["South Australia"] = {
Wikipedia = "South Australian English",
regional_categories = "South Australian",
parent = "Australia",
}
labels["Tasmania"] = {
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = "Tasmanian",
parent = "Australia",
}
labels["Victoria"] = {
Wikipedia = {"Variation in Australian English#Regional variation", "Victoria (state)"},
regional_categories = true,
parent = "Australia",
}
labels["Western Australia"] = {
Wikipedia = "Western Australian English",
regional_categories = "Western Australian",
parent = "Australia",
}
------------------------------------ Ireland ------------------------------------
labels["Cork"] = {
Wikipedia = {"South-West Irish English", "Cork (city)"},
regional_categories = "Munster",
}
labels["Dublin"] = {
Wikipedia = {"Dublin English", "Dublin", "DE"},
regional_categories = true,
parent = "Ireland",
}
labels["Ireland"] = {
aliases = {"Irish", "IE"},
Wikipedia = "Hiberno-English",
regional_categories = "Irish",
parent = "Europe",
}
labels["Munster"] = {
Wikipedia = {"South-West Irish English", "Munster"},
regional_categories = true,
parent = "Ireland",
}
------------------------------------ United Kingdom ------------------------------------
labels["British"] = {
region = "Great Britain",
addl = "Not to be confused with [[:Category:British English forms|British spellings]], a spelling system used in some English-speaking countries of the world.",
aliases = {"Britain", "Great Britain"},
Wikipedia = "en:British English",
display = "ဗြေတ်တိန်",
regional_categories = "ဗြေတ်တိန်",
parent = "Europe,Commonwealth",
country = "the United Kingdom",
}
labels["UK"] = {
aliases = {"United Kingdom"},
Wikipedia = "en:British English",
display = "ဗြေတ်တိန်",
regional_categories = "ဗြေတ်တိန်",
}
labels["Antrim"] = {
Wikipedia = "County Antrim",
regional_categories = "Northern Irish",
}
labels["Bedfordshire"] = {
Wikipedia = "Bedfordshire dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Berkshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Birmingham"] = {
Wikipedia = "Brummie dialect",
regional_categories = true,
parent = "West Midlands",
}
labels["Bristol"] = {
region = "[[Bristol]], [[England]]",
aliases = {"Bristolian"},
Wikipedia = "Bristolian dialect",
regional_categories = "Bristolian",
parent = "West Country",
}
labels["Caithness"] = {
Wikipedia = true,
regional_categories = true,
parent = "Scotland",
}
labels["Cambridge University"] = {
prep = "at",
region = "{{w|Cambridge University}} in [[Cambridge]]",
aliases = {"University of Cambridge", "Cantab"},
Wikipedia = "University of Cambridge",
regional_categories = true,
parent = "East Anglia",
othercat = "en:Universities",
}
labels["Channel Islands"] = {
the = true,
Wikipedia = "Channel Island English",
regional_categories = true,
parent = "Europe,Commonwealth",
}
labels["Cockney"] = {
prep = "by",
region = "working-class [[Londoner]]s, especially in the [[East End]]",
Wikipedia = "Cockney#Speech",
regional_categories = true,
parent = "London",
}
labels["Cornwall"] = {
aliases = {"Cornish"},
Wikipedia = "Cornish dialect",
regional_categories = "Cornish",
parent = "West Country",
}
labels["Cumbria"] = {
aliases = {"Cumbrian"},
Wikipedia = "Cumbrian dialect",
regional_categories = "Cumbrian",
parent = "Northern England",
}
labels["Derbyshire"] = {
region = "[[Derbyshire]], which is geographically in the East Midlands but whose dialect is sometimes classified as West Midlands",
Wikipedia = "Derbyshire dialect",
regional_categories = true,
parent = "East Midlands,West Midlands",
}
labels["Devon"] = {
aliases = {"Devonshire"},
Wikipedia = {"West Country English", true},
regional_categories = "Devonian",
parent = "West Country",
}
labels["Dorset"] = {
Wikipedia = "Dorset dialect",
regional_categories = true,
parent = "West Country",
}
labels["Dundee"] = {
Wikipedia = true,
regional_categories = true,
parent = "Scotland",
}
labels["Durham University"] = {
prep = "at",
region = "{{w|Durham University}} in [[Durham]]",
Wikipedia = true,
regional_categories = true,
parent = "Durham",
othercat = "en:Universities",
}
labels["Durham"] = {
Wikipedia = "County Durham",
regional_categories = true,
parent = "Northumbria",
}
labels["East Anglia"] = {
Wikipedia = "East Anglian English",
regional_categories = "East Anglian",
parent = "England",
}
labels["East Midlands"] = {
region = "the [[East Midlands]] of [[England]]",
Wikipedia = "East Midlands English",
regional_categories = true,
parent = "Midlands",
}
labels["England"] = {
aliases = {"English"},
Wikipedia = "en:English language in England",
display = "အိန်ဂလာန်",
regional_categories = "အၚ်္ဂလိက်",
parent = "British",
}
labels["England and Wales"] = {
aliases = {"E&W"},
Wikipedia = true,
regional_categories = {"English", "Welsh"},
}
labels["Essex"] = {
Wikipedia = "Essex dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Exmoor"] = {
Wikipedia = true,
regional_categories = {"Devonian", "Somerset"},
}
labels["Geordie"] = {
region = "Tyneside",
aliases = {"Geordie English", "Tyneside"},
Wikipedia = ":en:Geordie",
display = "ကျဝ်ဒဳ",
plain_categories = "ကျဝ်ဒဳ",
parent = "Northumbria",
}
labels["Gloucestershire"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
labels["Guernsey"] = {
prep = "on",
Wikipedia = "Channel Island English#Guernsey English",
regional_categories = true,
parent = "Channel Islands",
}
labels["Hartlepool"] = {
Wikipedia = "Smoggie",
regional_categories = "Teesside",
}
labels["Herefordshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "West Country",
}
labels["Isle of Man"] = {
prep = "on",
the = true,
aliases = {"Manx"},
Wikipedia = "Manx English",
regional_categories = "Manx",
parent = "British",
}
labels["Isle of Wight"] = {
prep = "on",
the = true,
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Jersey"] = {
prep = "on",
Wikipedia = "Channel Island English#Jersey English",
regional_categories = true,
parent = "Channel Islands",
}
labels["Kent"] = {
aliases = {"Kentish"},
Wikipedia = "Kentish dialect",
regional_categories = "Kentish",
parent = "Southern England",
}
labels["Lancashire"] = {
Wikipedia = "Lancashire dialect",
regional_categories = true,
parent = "Northern England",
}
labels["Lewis"] = {
prep = "on",
region = "the [[Isle of Lewis]]",
aliases = {"Isle of Lewis"},
Wikipedia = "Isle of Lewis",
regional_categories = true,
parent = "Scotland",
}
labels["Lincolnshire"] = {
Wikipedia = "Lincolnshire dialect",
regional_categories = true,
parent = "East Midlands",
}
labels["Liverpool"] = {
region = "the {{w|Liverpool City Region}}, comprising the [[metropolitan county]] of [[Merseyside]] and the [[Cheshire]] [[unitary authority]] of [[Halton]]",
aliases = {"Scouse"},
Wikipedia = "Scouse",
regional_categories = "Liverpudlian",
parent = "Northern England",
}
labels["London"] = {
Wikipedia = "Estuary English",
regional_categories = true,
parent = "Southern England",
}
labels["Manchester"] = {
aliases = {"Mancunian"},
Wikipedia = "Manchester dialect",
regional_categories = "Mancunian",
parent = "Northern England",
}
labels["Mid-Ulster"] = {
region = "central [[Ulster]]",
aliases = {"Mid-Ulster English"},
Wikipedia = "Mid-Ulster English",
regional_categories = true,
parent = "Ulster,Northern Ireland",
}
labels["Midlands"] = {
region = "the [[Midlands]] of [[England]]",
aliases = {"English Midlands", "South Midlands"},
Wikipedia = "Midlands English",
regional_categories = true,
parent = "England",
}
labels["Multicultural London English"] = {
prep = "by",
region = "young, working-class people in multicultural parts of [[London]]",
aliases = {"MLE"},
display = "MLE",
Wikipedia = true,
plain_categories = true,
parent = "London",
}
labels["Norfolk"] = {
Wikipedia = "Norfolk dialect",
regional_categories = true,
parent = "East Anglia",
}
labels["North Wales"] = {
Wikipedia = {"Welsh English", true},
regional_categories = true,
parent = "Wales",
}
labels["Northern England"] = {
aliases = {"northern England", "North England", "north England"},
Wikipedia = "en:English language in Northern England",
display = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "England",
}
labels["Northern Ireland"] = {
aliases = {"Northern Irish", "NI"},
Wikipedia = "Ulster English",
regional_categories = "Northern Irish",
parent = "Ulster",
}
labels["Northern Isles"] = {
display = "[[w:Orkney|Orkney]], [[w:Shetland|Shetland]]",
regional_categories = {"Orkney", "Shetland"},
}
labels["Northumberland"] = {
Wikipedia = {"Northumberland"},
regional_categories = true,
parent = "Northumbria",
}
labels["Northumbria"] = {
aliases = {"Northumbrian", "Northeast England", "North-East England", "North East England"},
Wikipedia = {"Northumbrian dialect", "Northumbria (modern)"},
regional_categories = "Northumbrian",
parent = "Northern England",
}
labels["Nottinghamshire"] = {
Wikipedia = "Nottinghamshire dialect",
regional_categories = true,
parent = "East Midlands",
}
labels["Orkney"] = {
prep = "on",
aliases = {"Orcadian"},
Wikipedia = {true, "Highland English"},
regional_categories = true,
parent = "Scotland",
}
labels["Oxbridge"] = {
Wikipedia = true,
regional_categories = {"Cambridge University", "Oxford University"},
}
labels["Oxford City"] = {
region = "the city of [[Oxford]] in [[England]]",
Wikipedia = true,
regional_categories = "Oxford",
parent = "Oxfordshire",
}
labels["Oxford University"] = {
prep = "at",
aliases = {"University of Oxford", "Oxon"},
Wikipedia = "University of Oxford",
regional_categories = true,
parent = "Oxford City",
othercat = "en:Universities",
}
labels["Oxfordshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Pitmatic"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northumbria",
}
labels["Potteries"] = {
region = "Stoke-on-Trent",
Wikipedia = "Potteries dialect",
regional_categories = true,
parent = "West Midlands",
}
labels["Scotland"] = {
aliases = {"Scottish", "Scottish English", "ScE"},
Wikipedia = "Scottish English",
regional_categories = "Scottish",
parent = "British",
}
labels["Shetland"] = {
region = "the [[Shetland Islands]]",
aliases = {"Shetland Islands", "Shetlands"},
Wikipedia = {true, "Highland English"},
regional_categories = true,
parent = "Scotland",
}
labels["Shropshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "West Midlands",
}
labels["Somerset"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
-- eventually maybe break this out into its own category
labels["South Midlands"] = {
Wikipedia = {"Midlands English", "South Midlands"},
regional_categories = "Midlands",
}
labels["South Wales"] = {
Wikipedia = {"Welsh English", true},
regional_categories = true,
parent = "Wales",
}
labels["Southern England"] = {
aliases = {"southern England", "South England", "south England", "Southern English"},
Wikipedia = "en:English in southern England",
display = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories ="အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "England",
}
labels["Suffolk"] = {
Wikipedia = "Suffolk dialect",
regional_categories = true,
parent = "East Anglia",
}
labels["Sussex"] = {
Wikipedia = "Sussex dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Teesside"] = {
Wikipedia = "Smoggie",
regional_categories = true,
parent = "Northumbria",
}
-- Tyneside: see Geordie
labels["Ulster"] = {
Wikipedia = "Ulster English",
regional_categories = true,
parent = "Ireland",
}
labels["Wales"] = {
aliases = {"Welsh"},
Wikipedia = "Welsh English",
regional_categories = "Welsh",
parent = "British",
}
labels["Wearside"] = {
Wikipedia = {"Mackem", true},
regional_categories = true,
parent = "Northumbria",
}
labels["West Country"] = {
the = true,
aliases = {"West England", "west England"},
Wikipedia = "West Country English",
regional_categories = true,
parent = "England",
}
-- can be split off if enough entries in it arise; group with Cumbria for now
labels["West Cumbria"] = {
Wikipedia = "Cumbrian dialect",
regional_categories = "Cumbrian",
}
labels["West Midlands"] = {
region = "the [[West Midlands]] of [[England]]",
Wikipedia = "West Midlands English",
regional_categories = true,
parent = "Midlands",
}
labels["Wiltshire"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
labels["Yorkshire"] = {
Wikipedia = "Yorkshire dialect",
regional_categories = true,
parent = "Northern England",
}
-------------------------------- South Asia --------------------------------
labels["South Asia"] = {
aliases = {"Indic", "South Asian", "Desi", "Deshi"},
Wikipedia = "en:South Asian English",
accent_display = "အိန်ဒဳစ်",
regional_categories = "အာသျှဒိုဟ်သမၠုၚ်ကျာ",
parent = "Asia",
}
labels["Afghanistan"] = {
Wikipedia = true,
regional_categories = "Afghan",
parent = "South Asia",
}
labels["Bangladesh"] = {
Wikipedia = "Bangladeshi English",
regional_categories = "Bangladeshi",
parent = "South Asia,Commonwealth",
}
labels["Nepal"] = {
Wikipedia = "Nepalese English",
regional_categories = "Nepali",
parent = "South Asia,Commonwealth",
}
labels["Sri Lanka"] = {
aliases = {"Sri Lankan"},
Wikipedia = "Sri Lankan English",
regional_categories = "Sri Lankan",
parent = "South Asia,Commonwealth",
}
labels["Pakistan"] = {
aliases = {"Pakistani"},
Wikipedia = "Pakistani English",
regional_categories = "Pakistani",
parent = "South Asia,Commonwealth",
}
labels["British Pakistani"] = {
prep = "by",
region = "{{w|British Pakistanis}}, i.e. [[British]] citizens of [[Pakistani]] origin",
Wikipedia = "British Pakistanis",
regional_categories = true,
parent = "South Asia,British",
}
labels["British India"] = {
fulldef = "Anglo-Indian terms or senses in English as used formerly by Britishers in {{w|British India}}",
Wikipedia = "Indian English", -- The WP articles are strictly divided by geography, not historical period
regional_categories = true,
parent = "South Asia,British",
othercat = "English terms with historical senses",
}
labels["India"] = {
aliases = {"Indian", "Indian English", "InE"},
Wikipedia = "Indian English",
accent_Wikipedia = "Indian English#Phonology",
regional_categories = "Indian",
parent = "South Asia,Commonwealth",
}
labels["North India"] = {
Wikipedia = true,
regional_categories = "North Indian",
parent = "India",
}
labels["South India"] = {
aliases = {"South Indian"},
Wikipedia = true,
regional_categories = "South Indian",
parent = "India",
}
labels["West Bengal"] = {
Wikipedia = true,
accent_Wikipedia = "Regional differences and dialects in Indian English#Bengali English",
regional_categories = true,
parent = "India",
}
labels["Hinglish"] = {
def = "[[Hinglish]], an English-based [[creole]] incorporating many [[Hindi]] words; used informally in [[India]]",
Wikipedia = true,
plain_categories = true,
parent = "North India",
}
labels["Tamil Nadu"] = {
aliases = {"TN", "Tamilnadu"},
accent_Wikipedia = "Regional differences and dialects in Indian English#Southern Indian English",
parent="South India"
}
labels["Kerala"] = {
accent_Wikipedia = "Regional differences and dialects in Indian English#Malayali",
aliases = { "Malayalam", "Mallu" },
parent = "South India"
}
------------------------------------ World ------------------------------------
labels["Africa"] = {
aliases = {"African"},
Wikipedia = "African English",
regional_categories = "African",
parent = true,
}
labels["Antarctica"] = {
Wikipedia = "Antarctic English",
regional_categories = "Antarctic",
parent = true,
}
labels["Asia"] = {
Wikipedia = "Asian English",
regional_categories = "Asian",
parent = true,
}
labels["Bahamas"] = {
the = true,
Wikipedia = "Bahamian English",
regional_categories = "Bahaman",
parent = "Caribbean",
}
labels["Barbados"] = {
Wikipedia = "English in Barbados",
regional_categories = "Barbadian",
parent = "Caribbean",
}
labels["Belize"] = {
Wikipedia = "Belizean English",
regional_categories = "Belizean",
parent = "Caribbean,Central America",
}
labels["Benglish"] = {
def = "[[Benglish]], an English-based [[creole]] incorporating many [[Bengali]] words; used informally in [[Bangladesh]] and [[West Bengal]]",
aliases = {"Banglish"},
Wikipedia = true,
plain_categories = true,
parent = "Bangladesh,West Bengal",
}
labels["Bermuda"] = {
Wikipedia = "Bermudian English",
regional_categories = "Bermudian",
parent = "Caribbean,rawposcat:North American English,British",
}
labels["Botswana"] = {
Wikipedia = "Botswana English",
regional_categories = "Botswanan",
parent = "Africa",
}
labels["Brunei"] = {
Wikipedia = "Brunei English",
regional_categories = "Bruneian",
parent = "Southeast Asia",
}
labels["Cameroon"] = {
aliases = {"CM", "Cameroonian", "Cameroonian English", "en-CM"},
Wikipedia = "Cameroonian English",
regional_categories = "Cameroonian",
parent = "Africa",
}
labels["Caribbean"] = {
the = true,
aliases = {"West Indies"},
Wikipedia = "Caribbean English",
regional_categories = true,
parent = true,
}
labels["Cebu"] = {
Wikipedia = true,
regional_categories = true,
parent = "Philippines",
}
labels["Central America"] = {
Wikipedia = true,
regional_categories = "Central American",
parent = "rawposcat:North American English",
}
labels["Ceylon"] = {
Wikipedia = true,
regional_categories = "Sri Lankan",
}
labels["China"] = {
Wikipedia = "en:China",
display = "ဍုၚ်ကြုက်",
regional_categories = "ဂကူကြုက်",
parent = "East Asia",
}
labels["Chinese Filipino"] = {
verb = "used",
prep = "by",
region = "Chinese Filipinos",
aliases = {"Chinese-Filipino"}, -- Sociolect subset to Philippine English
-- may also see "Hokaglish" in Wikipedia, although Hokaglish is the codeswitching form with a Hokkien or Tagalog base, just like Philippine English to "Conyo" (English-based) and "Taglish" (Tagalog-based), whereas this is the English variant itself subset to Philippine English.
Wikipedia = "Chinese Filipino#Language",
regional_categories = true,
parent = "Philippines",
}
labels["Chinglish"] = {
def = "[[English]] that has been influenced by [[Chinese]]",
Wikipedia = true,
plain_categories = true,
parent = "China",
}
labels["Commonwealth"] = {
region = "the [[Commonwealth of Nations]]",
Wikipedia = "en:English in the Commonwealth of Nations",
display = "ဓနသဟာယ",
regional_categories = "ဓနသဟာယ",
parent = true,
}
labels["Cuba"] = {
Wikipedia = true,
regional_categories = "Cuban",
parent = "Caribbean",
}
labels["East Africa"] = {
Wikipedia = true,
regional_categories = "East African",
parent = "Africa",
}
labels["East Asia"] = {
Wikipedia = true,
regional_categories = "East Asian",
parent = "Asia",
}
labels["Egypt"] = {
Wikipedia = "en:Egypt",
display = "အဳဂျေပ်",
regional_categories = "ဍုၚ်အဳဂျေပ်",
parent = "Africa,Middle East",
}
labels["Europe"] = {
aliases = {"European"},
Wikipedia = "English language in Europe",
regional_categories = "European",
parent = true,
}
labels["Fiji"] = {
Wikipedia = "Fijian English",
regional_categories = "Fijian",
parent = "Oceania,Commonwealth",
}
labels["Ghana"] = {
Wikipedia = "Ghanaian English",
regional_categories = "Ghanaian",
parent = "West Africa",
}
labels["Guyana"] = {
Wikipedia = {"Guyanese English", "Guyana"},
regional_categories = "Guyanese",
parent = "Caribbean,South America",
}
labels["Hong Kong"] = {
aliases = {"HK"},
Wikipedia = "Hong Kong English",
regional_categories = true,
parent = "China",
}
labels["Hungary"] = {
Wikipedia = true,
regional_categories = "Hungarian",
parent = "Europe",
}
labels["Indonesia"] = {
Wikipedia = "Indonesian English",
regional_categories = "Indonesian",
parent = "Southeast Asia",
}
labels["Israel"] = {
Wikipedia = "Israeli English",
regional_categories = "Israeli",
parent = "Middle East",
}
labels["Japan"] = {
Wikipedia = "en:Japan",
display = "ဍုၚ်ဂျပါန်",
regional_categories = "ဂကူဂျပါန်",
parent = "East Asia",
}
labels["Jamaica"] = {
aliases = {"Jamaican English", "Jamaican"},
Wikipedia = "Jamaican English",
regional_categories = "Jamaican",
parent = "Caribbean,Commonwealth",
}
labels["Kenya"] = {
Wikipedia = "Kenyan English",
regional_categories = "Kenyan",
parent = "East Africa",
}
labels["Liberia"] = {
Wikipedia = "Liberian English",
regional_categories = "Liberian",
parent = "West Africa",
}
labels["Libya"] = {
Wikipedia = true,
regional_categories = "Libyan",
parent = "Africa",
}
labels["Macau"] = {
Wikipedia = true,
regional_categories = "Macanese",
parent = "China",
}
labels["Mainland China"] = {
aliases = {"Mainland", "mainland", "mainland China"},
Wikipedia = true,
regional_categories = true,
parent = "China",
}
labels["Malaysia"] = {
aliases = {"Malaysian"},
Wikipedia = "Malaysian English",
regional_categories = "Malaysian",
parent = "Southeast Asia,Commonwealth",
}
labels["Malta"] = {
Wikipedia = "Maltese English",
regional_categories = "Maltese",
parent = "Europe",
}
labels["Manglish"] = {
def = "[[Manglish]], an English-based [[creole]] incorporating [[Malay]], [[Chinese]], and [[Tamil]] words; used informally in [[Malaysia]]",
Wikipedia = true,
plain_categories = true,
parent = "Malaysia",
}
labels["Mexico"] = {
Wikipedia = {"Mexican English", "Mexico"},
regional_categories = "Mexican",
parent = "rawposcat:North American English",
}
labels["Middle East"] = {
the = true,
Wikipedia = true,
regional_categories = "Middle Eastern",
parent = true,
}
labels["Myanmar"] = {
aliases = {"Burma"},
Wikipedia = "en:Myanmar English",
display = "ဍုၚ်ဗၟာ",
regional_categories = "ဍုၚ်ဗၟာ",
parent = "Southeast Asia",
}
labels["Namibia"] = {
Wikipedia = "Namibian English",
regional_categories = "Namibian",
parent = "Africa",
}
labels["Natal"] = {
Wikipedia = "KwaZulu-Natal",
regional_categories = true,
parent = "South Africa",
}
labels["Nigeria"] = {
aliases = {"Nigerian"},
Wikipedia = "Nigerian English",
regional_categories = "Nigerian",
parent = "West Africa",
}
labels["Oceania"] = {
Wikipedia = "Oceanian English",
regional_categories = "Oceanian",
parent = true,
}
labels["Palestine"] = {
Wikipedia = true,
regional_categories = "Palestinian",
parent = "Middle East",
}
labels["Papua New Guinea"] = {
Wikipedia = "Papua New Guinean English",
regional_categories = "Papua New Guinean",
parent = "Oceania,Commonwealth",
}
labels["Philippines"] = {
the = true,
aliases = {"Philippine", "Philippine English"},
Wikipedia = "en:Philippine English",
display = "ဖိလေတ်ပေန်",
regional_categories = "ဖိလေတ်ပေန်",
parent = "Southeast Asia",
}
labels["Baguio"] = {
Wikipedia = true,
regional_categories = true,
parent = "Philippines",
}
labels["Réunion"] = {
Wikipedia = true,
regional_categories = true,
parent = "Africa",
}
labels["Rhodesia"] = {
region = "the historical state of [[Rhodesia]]",
Wikipedia = "Zimbabwean English",
regional_categories = "Rhodesian",
parent = "Africa",
}
labels["Rwanda"] = {
Wikipedia = true,
regional_categories = "Rwandan",
parent = "Africa",
}
labels["Singapore"] = {
aliases = {"SG", "Singaporean"},
Wikipedia = "Singapore English",
regional_categories = true,
parent = "Southeast Asia,Commonwealth",
}
labels["Singlish"] = {
def = "[[Singlish]], an English-based [[creole]] incorporating many words of [[Chinese]], [[Malay]] and [[Indian]] origin; used informally in [[Singapore]]",
Wikipedia = true,
plain_categories = true,
parent = "Singapore",
}
labels["Solomon Islands"] = {
the = true,
Wikipedia = "Solomon Islands English",
regional_categories = true,
parent = "Oceania",
}
labels["South Africa"] = {
aliases = {"South African", "South African English", "ZA"},
Wikipedia = "South African English",
accent_Wikipedia = "South African English phonology",
accent_display = "General South African",
regional_categories = "South African",
parent = "Africa,Commonwealth",
}
labels["South America"] = {
aliases = {"South American"},
Wikipedia = "en:South American English",
display = "အမေရိကာန်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်ဒိုဟ်သမၠုၚ်ကျာ",
parent = true,
}
labels["South Korea"] = {
Wikipedia = "en:Korean English",
display = "ကိုဝ်ရဳယျာဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "ကိုဝ်ရဳယျာဒိုဟ်သမၠုၚ်ကျာ",
parent = "East Asia",
}
labels["Southeast Asia"] = {
aliases = {"Southeast Asian", "South-East Asia", "South-East Asian", "South-east Asia", "South-east Asian", "SEA"},
Wikipedia = "Southeast Asian English",
regional_categories = "Southeast Asian",
parent = "Asia",
}
labels["Taiwan"] = {
aliases = {"Taiwanese"},
Wikipedia = "en:Taiwan",
display = "ထာၚ်ဝါန်",
regional_categories = "ဍုၚ်ထာၚ်ဝါန်",
parent = "East Asia",
}
labels["Tanzania"] = {
aliases = {"Tanzanian"},
Wikipedia = true,
regional_categories = "Tanzanian",
parent = "East Africa",
}
labels["Thailand"] = {
Wikipedia = "en:Tinglish",
display = "ဍုၚ်သေံ",
regional_categories = "သေံ",
parent = "Southeast Asia",
}
labels["Trinidad and Tobago"] = {
aliases = {"Trinidad", "Tobago", "Trinidadian"},
Wikipedia = "Trinidadian and Tobagonian English",
regional_categories = true,
parent = "Caribbean",
}
labels["Uganda"] = {
Wikipedia = "Ugandan English",
regional_categories = "Ugandan",
parent = "Africa",
}
labels["Vanuatu"] = {
Wikipedia = "Vanuatuan English",
regional_categories = true,
parent = "Oceania",
}
labels["Vietnam"] = {
Wikipedia = "Vietglish",
regional_categories = "Vietnamese",
parent = "Southeast Asia",
}
labels["West Africa"] = {
aliases = {"West African"},
Wikipedia = true,
regional_categories = "West African",
parent = "Africa",
}
labels["Zimbabwe"] = {
Wikipedia = "Zimbabwean English",
regional_categories = true,
parent = "Africa",
}
------------------------------------ non-regional ------------------------------------
labels["DoggoLingo"] = {
def = "[[DoggoLingo]]",
display = "[[DoggoLingo]]",
noreg = true,
plain_categories = true,
othercat = "English internet slang",
parent = "internet slang",
}
labels["Early Modern"] = {
prep = "from",
region = "the late 15th to the mid-17th centuries",
noreg = true,
nolink = true,
aliases = {"Early Modern English", "EME"},
Wikipedia = "Early Modern English",
regional_categories = true,
parent = true,
}
labels["Late Modern"] = {
prep = "from",
region = "the mid-17th to the end of the 19th centuries",
noreg = true,
nolink = true,
aliases = {"Late Modern English", "LME"},
Wikipedia = "Late Modern English",
regional_categories = true,
parent = true,
}
-- ideally this would sit at [[Module:category tree/pragmatic properties]] so it can be used for all languages, but those cats needs to begin with the language name...
labels["non-native speakers' English"] = {
display = "[[non-native speaker]]s' English",
noreg = true,
aliases = {"NNES", "NNSE"},
regional_categories = "Non-native speakers'",
Wikipedia = "English as a second or foreign language",
accent_Wikipedia = "Non-native pronunciations of English",
othercat = "English nonstandard terms,English terms by usage,English terms by orthographic property",
}
labels["Polari"] = {
def = "a form of cant slang used in [[Britain]] by some actors, circus and fairground showmen, professional wrestlers, merchant navy sailors, criminals, prostitutes, and the gay subculture",
noreg = true,
country = "the United Kingdom",
Wikipedia = true,
plain_categories = true,
othercat = "British slang,English cant,English gay slang",
parent = true,
}
-- Thieves' Cant is English-only, for other languages, use "criminal slang"
labels["thieves' cant"] = {
fulldef = "A secret language formerly used by thieves, beggars and hustlers of various kinds in [[Great Britain]] and to a lesser extent in other English-speaking countries",
noreg = true,
aliases = {"Thieves' Cant", "Thieves' cant", "thieves cant", "thieves'", "thieves"},
Wikipedia = true,
-- FIXME: Currently pos_categories aren't recognized.
-- pos_categories = "Thieves' Cant",
plain_categories = "English Thieves' Cant",
parent = true,
othercat = "English cant",
}
------------------------------------ English-specific qualifier labels ------------------------------------
labels["attributive"] = {
display = "[[Appendix:English nouns#Attributive|attributive]]",
}
labels["attributively"] = {
display = "[[Appendix:English nouns#Attributive|attributively]]",
}
------------------------------------ supporting [[Template:standard spelling of]] et al. ------------------------------------
labels["American spelling"] = {
aliases = {"American form", "US spelling", "US form",
-- As in "color" vs. "colour"
"or form", "-or form",
"or spelling", "-or spelling",
-- As in "meter" vs. "metre"
"er form", "-er form",
"er spelling", "-er spelling"
},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "အမေရိကာန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်",
}
labels["Australian spelling"] = {
aliases = {"Australian form"},
Wikipedia = "en:Australian English#Spelling and style",
form_of_display = "အမေရိကာန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်",
}
labels["British spelling"] = {
aliases = {"British form", "UK spelling", "UK form"},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "ဗြေတ်တိန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["Commonwealth spelling"] = {
aliases = {"Commonwealth form",
-- As in "color" vs. "colour"
"our form", "-our form", "our spelling", "-our spelling",
-- As in "meter" vs. "metre"
"re form", "-re form", "re spelling", "-re spelling"
},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "ဓနသဟာယ",
plain_categories = {"ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်", "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ခေန်နာဒါ", "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်"},
}
labels["Canadian spelling"] = {
aliases = {"Canadian form"},
Wikipedia = "en:Canadian spelling",
form_of_display = "ခေန်နာဒါ",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ခေန်နာဒါ",
}
labels["Oxford British spelling"] = {
aliases = {"Oxford", "Oxford form", "Oxford spelling", "en-GB-oxendict",},
display = "[[British English|အၚ်္ဂလိက်ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]",
plain_categories = "ခ္ဍံက်လိက်အံက်ဖှဝ်ဒ်",
}
labels["non-Oxford British spelling"] = {
aliases = {"Non-Oxford British spelling", "non-Oxford British form", "Non-Oxford British form", "non-Oxford form", "Non-Oxford form", "non-Oxford", "Non-Oxford", "not Oxford", "Not Oxford"},
display = "[[British English|အၚ်္ဂလိက်ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]-ဟွံသေၚ်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["ise spelling"] = {
aliases = {
"ise", "-ise", "ise form", "-ise form", "-ise spelling", "isation", "-isation", "isation form", "-isation form", "isation spelling", "-isation spelling",
"ise-form" -- backwards compatability
},
display = "non-[[w:Oxford spelling|Oxford]] [[w:American and British English spelling differences|British spelling]]",
form_of_display = "[[w:en:American and British English spelling differences|ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]-ဟွံသေၚ်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["ize spelling"] = {
aliases = {
"ize", "-ize", "ize form", "-ize form", "-ize spelling", "ization", "-ization", "ization form", "-ization form", "ization spelling", "-ization spelling",
"ize-form" -- backwards compatability
},
display = "[[w:American and British English spelling differences|American]] and [[w:Oxford spelling|Oxford]] [[British English|British spelling]]",
form_of_display = "[[w:en:American and British English spelling differences|အမေရိကာန်]] ကဵု [[British English|ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]",
plain_categories = {"ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်", "ခ္ဍံက်လိက်အံက်ဖှဝ်ဒ်"},
}
------------------------------------ supporting [[Template:inflection of]] ------------------------------------
-- This is added to an inflection line when something like {{infl of|en|make||th-form}} is used. Specifically, the form-of
-- tag 'th-form' is a shortcut for '3-th|s|spres|ind' (see [[Module:form of/lang-data/en]]); the tag '3-th' displays as
-- "third-person" (see [[Module:form of/lang-data/en]]) and attaches the following label (see [[Module:form of/cats]]).
labels["archaic third singular"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "archaic third-person singular forms",
}
-- This is added to an inflection line when something like {{infl of|en|make||st-form}} is used. See above.
labels["archaic second singular present"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "second-person singular forms",
}
-- This is added to an inflection line when something like {{infl of|en|make||st-past-form}} is used. See above.
labels["archaic second singular past"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "second-person singular past tense forms",
}
------------------------------------ accent qualifiers ------------------------------------
-- Generate the inverse of a sound change. In general, we should do this for sound changes that are either
-- extremely common (e.g. 'cot-caught') or dominant ('horse-hoarse', 'wine-whine') or are at least locally
-- dominant (e.g. 'cheer-chair'). The idea is that when presenting the pronunciation of an area with a locally
-- dominant pronunciation, we may want to also present the alternative pronunciation lacking the change, as long
-- as it is found at least somewhere in the area. Hence, for New Zealand, which typically has the cheer-chair
-- merger, we might might to present the non-merger pronunciation as well; but for a change like card-cord that
-- is recessive everywhere, it's unlikely we'll need to specifically highlight the inverse pronunciation (which
-- would be the standard, already covered elsewhere), and we can save memory and time by omitting the label.
local function generate_non(key, display)
if not labels[key] then
error(("Internal error: No label definition for key '%s'"):format(key))
end
local labval = mw.clone(labels[key])
labels["non-" .. key] = labval
if labval.aliases then
for i, alias in ipairs(labval.aliases) do
labval.aliases[i] = "non-" .. alias
end
end
if not display then
display = labval.display or key
if display:find("ing$") or display:find("[st]ion$") then
-- e.g. "Canadian raising", "t-glottalization"
display = "without " .. display
else
-- e.g. "cot-caught merger"
display = "without the " .. display
end
end
labval.display = display
end
labels["Anglicised"] = {
aliases = {"Anglicized"},
Wikipedia = "Anglicisation#Anglicisation of non-English-language vocabulary and names",
}
labels["Canadian raising"] = {
aliases = {"North American raising"},
Wikipedia = true,
}
generate_non("Canadian raising")
labels["Canadian Shift"] = {
aliases = {"Canadian Vowel Shift", "Canadian shift", "Canadian vowel shift"},
Wikipedia = true,
display = "Canadian Vowel Shift",
}
generate_non("Canadian Shift")
labels["card-cord"] = {
Wikipedia = "Card-cord merger",
display = "''card''–''cord'' merger",
}
labels["cheer-chair"] = {
aliases = {"near-square"},
Wikipedia = "near-square merger",
display = "''cheer''–''chair'' merger",
}
generate_non("cheer-chair")
labels["cot-caught"] = {
aliases = {"caught-cot"},
Wikipedia = "en:Cot–caught merger",
display = "''ခါတ်''–''ပံၚ်စပ်အာ''ပရေၚ်ဒုၚ်ရပ်ကေတ်မာန်",
}
generate_non("cot-caught")
labels["cure-fir"] = {
aliases = {"cure-nurse"},
Wikipedia = "Cure-nurse merger",
display = "''cure''–''fir'' merger",
}
generate_non("cure-fir")
labels["doll-dole"] = {
Wikipedia = "Doll-dole merger",
display = "''doll''–''dole'' merger",
}
labels["dough-door"] = {
Wikipedia = "Dough-door merger",
display = "''dough''–''door'' merger",
}
generate_non("dough-door")
labels["Estuary English"] = {
Wikipedia = true,
}
labels["fair-fur"] = {
aliases = {"square-nurse"},
Wikipedia = "Square-nurse merger",
display = "''fair''–''fur'' merger",
}
generate_non("fair-fur")
labels["father-bother"] = {
Wikipedia = "Father–bother merger",
display = "''father''-''bother'' merger",
}
generate_non("father-bother")
labels["fern-fir-fur"] = {
aliases = {"nurse merger"},
Wikipedia = "Fern-fir-fur merger",
display = "''fern''–''fir''–''fur'' merger",
}
generate_non("fern-fir-fur")
labels["t-flapping"] = {
Wikipedia = true,
}
generate_non("t-flapping")
labels["foot-goose"] = {
Wikipedia = "Foot-goose merger",
display = "''foot''-''goose'' merger",
}
-- Most labels of the form 'foo-bar' are mergers. Since this is rather a split, include the word "split"
-- for clarity.
labels["foot-strut split"] = {
Wikipedia = "Phonological history of English close back vowels#FOOT–STRUT split",
display = "''foot''-''strut'' split",
}
generate_non("foot-strut split")
labels["g-dropping"] = {
aliases = {"g dropping"},
Wikipedia = "G-dropping",
display = "''g''-dropping",
}
generate_non("g-dropping")
labels["General American"] = {
aliases = {"GenAm", "GA"},
Wikipedia = "en:General American English",
display = "အမေရိကာန်နာနာသာ်",
}
labels["glottalized"] = {
aliases = {"glottalization", "glottalised", "glottalisation"},
Wikipedia = "Phonological history of English consonant clusters#Glottalization",
}
labels["goose split"] = {
-- Phonemic split in some Southeastern England English variants.
Wikipedia = "English-language vowel changes before historic /l/#Goose_split",
display = "''goose'' split",
}
labels["gulf-golf"] = {
Wikipedia = "English-language vowel changes before historic /l/#Gulf-golf merger",
display = "''gulf''-''golf'' merger",
}
labels["h-dropping"] = {
Wikipedia = "H-dropping",
display = "''h''-dropping",
}
generate_non("h-dropping")
labels["happy-tensing"] = {
aliases = {"happy tensing"},
Wikipedia = "Happy tensing",
display = "''happy''-tensing",
}
generate_non("happy-tensing")
labels["horse-hoarse"] = {
Wikipedia = "horse–hoarse merger",
display = "''horse''–''hoarse'' merger",
}
generate_non("horse-hoarse")
labels["hurry-furry"] = {
Wikipedia = "hurry-furry merger",
display = "''hurry''–''furry'' merger",
}
generate_non("hurry-furry")
labels["Inland Northern US"] = {
aliases = {"Great Lakes", "Inland Northern", "Inland North", "Inland Northern American", "Inland Northern American English", "Inland Northern English", "Northern Cities Vowel Shift", "US Inland North", "northern cities vowel shift"},
Wikipedia = "Inland Northern American English",
display = "Inland Northern American",
}
labels["intrusive r"] = {
Wikipedia = "Intrusive r",
display = "intrusive R",
}
generate_non("intrusive r", "without intrusive R")
labels["laxing"] = {
Wikipedia = "Trisyllabic laxing"
}
generate_non("laxing")
labels["linking w"] = {
Wiktionary = "Appendix:English_pronunciation#Linking_semivowels",
display="linking W"
}
labels["linking y"] = {
Wiktionary = "Appendix:English_pronunciation#Linking_semivowels",
display="linking Y"
}
labels["l-vocalization"] = {
aliases = {"l-vocalisation"},
Wikipedia = "L-vocalization#Modern English",
display = "''l''-vocalization",
}
generate_non("l-vocalization")
labels["Latinate"] = {
Wikipedia = "Latin#Phonology",
}
labels["lot-cloth split"] = {
Wikipedia = true,
display = "''lot''–''cloth'' split",
}
generate_non("lot-cloth split")
labels["Mary-marry-merry"] = {
aliases = {"Mmmm"},
Wikipedia = "Mary–marry–merry merger",
display = "''Mary''–''marry''–''merry'' merger",
}
generate_non("Mary-marry-merry")
table.insert(labels["non-Mary-marry-merry"].aliases, "nMmmm")
labels["merry-Murray"] = {
aliases = {"Merry-Murray"},
Wikipedia = "Merry–Murray merger",
display = "''merry''–''Murray'' merger",
}
labels["mirror-nearer"] = {
aliases = {"Sirius-serious"},
Wikipedia = "Mirror-nearer merger",
display = "''mirror''–''nearer'' merger",
}
generate_non("mirror-nearer")
labels["nt-flapping"] = {
Wikipedia = "Flapping#Distribution",
display = "''nt''-flapping",
}
generate_non("nt-flapping")
labels["pane-pain"] = {
Wikipedia = "Pane–pain merger",
display = "''pane''–''pain'' merger"
}
generate_non("pane-pain")
labels["paw-poor"] = {
Wikipedia = "Rhoticity in English#/ɔː/–/ʊər/ merger",
display = "''paw''–''poor'' merger",
}
labels["pin-pen"] = {
aliases = {"pen-pin"},
Wikipedia = "pin–pen merger",
display = "''pin''–''pen'' merger",
}
labels["pour-poor"] = {
aliases = {"poor-pour", "cure-force"},
Wikipedia = "Cure–force merger",
display = "''pour''–''poor'' merger",
}
generate_non("pour-poor")
labels["r-dissimilation"] = {
Wikipedia = "Dissimilation",
display = "''r''-dissimilation",
}
labels["rhotic"] = {
Wikipedia = "Rhoticity in English",
}
labels["non-rhotic"] = {
aliases = {"nonrhotic"},
Wikipedia = "Rhoticity in English",
}
labels["Received Pronunciation"] = {
aliases = {"RP"},
Wikipedia = "en:Received Pronunciation",
display = "ဗီုပ္တိတ်ရမျာၚ်မဒုၚ်တဲလဝ်",
}
labels["salary-celery"] = {
Wikipedia = "Salary–celery merger",
display = "''salary''–''celery'' merger",
}
labels["show-sure"] = {
Wikipedia = "Show-sure merger",
display = "''show''–''sure'' merger",
}
labels["Standard Southern British English"] = {
aliases = {"SSB", "SSBE", "Standard Southern British"},
Wikipedia = "Standard Southern British",
display = "Standard Southern British",
}
labels["stressed"] = {
Wikipedia = "Stress and vowel reduction in English#Weak and strong forms of function words",
display = "stressed form",
}
labels["tar-tire"] = {
Wikipedia = "/aɪər/–/ɑr/ merger",
display = "tar-tire merger",
}
labels["tar-tire-tower"] = {
Wikipedia = "English-language vowel changes before historic /r/#/aɪə/–/aʊə/–/ɑː/ merger",
display = "tar-tire-tower merger",
}
labels["t-glottalization"] = {
aliases = {"t-glottaling", "t-glottalisation"},
Wikipedia = "T-glottalization",
display = "''t''-glottalization",
}
generate_non("t-glottalization")
labels["th-fronting"] = {
Wikipedia = true,
display = "''th''-fronting",
}
labels["th-stopping"] = {
Wikipedia = true,
display = "''th''-stopping",
}
labels['toe-tow'] = {
Wikipedia = "Phonological history of English diphthongs#Toe–tow merger",
display = "''toe''–''tow'' merger"
}
generate_non("toe-tow")
labels["trap-bath split"] = {
Wikipedia = "trap–bath split",
display = "''trap''–''bath'' split",
}
generate_non("trap-bath split")
labels["triphthong smoothing"] = {
Wikipedia = "Triphthong smoothing",
display = "triphthong smoothing",
}
generate_non("triphthong smoothing")
labels["unstressed"] = {
Wikipedia = "Stress and vowel reduction in English#Weak and strong forms of function words",
display = "unstressed form",
}
labels["weak vowel"] = {
aliases = {"weak vowel merger"},
Wikipedia = "Weak vowel merger",
display = "weak vowel merger",
}
generate_non("weak vowel", "weak vowel distinction")
labels["wine-whine"] = {
Wikipedia = "wine–whine merger",
display = "''wine''–''whine'' merger",
}
generate_non("wine-whine")
labels["yod-coalescence"] = {
aliases = {"yod coalescence"},
Wikipedia = true,
}
generate_non("yod-coalescence")
labels["NG-coalescence"] = {
aliases = {"NG coalescence","ng-coalescence","ng coalescence"},
Wikipedia = true,
}
generate_non("NG-coalescence")
labels["yod-dropping"] = {
aliases = {"yod dropping"},
Wikipedia = true,
}
generate_non("yod-dropping")
labels["æ-raising"] = {
aliases = {"æ-tensing", "/æ/ raising", "/æ/ tensing", "ae-raising", "ae-tensing"},
Wikipedia = "/æ/ raising",
}
generate_non("æ-raising")
return require("Module:labels").finalize_data(labels)
7mo6ni566d6na1y57e37g7vxjs0q278
392613
392612
2026-04-13T12:50:21Z
咽頭べさ
33
392613
Scribunto
text/plain
local labels = {}
------------------------------------ North America ------------------------------------
labels["North America"] = {
aliases = {"North American"},
display = "[[Canada|ခေန်နာဒါ]]၊ [[American English|အမေရိကာန်]]",
regional_categories = {"ခေန်နာဒါ", "အမေရိကာန်"},
}
labels["caricature Black"] = {
display = "caricatures of Black speech",
def = "any of various caricatures of Black speech by non-Black writers",
aliases = {"caricature black", "a caricature of Black speech", "caricatures of Black speech"},
plain_categories = "Caricatures of Black English",
form_of_display = "a caricature of Black"
-- for use in T:pronunciation spelling of. use in T:altform and T:altspell is not intended and looks bad.
}
------------- Canada -------------
labels["Canada"] = {
aliases = {"CA", "Canadian", "CanE", "Canadian English"},
Wikipedia = "en:Canadian English",
display = "ခေန်နာဒါ",
regional_categories = "ခေန်နာဒါ",
parent = "rawposcat:North American English,Commonwealth",
}
labels["Acadia"] = {
region = "colonial [[Acadia]]",
aliases = {"Acadian"},
Wikipedia = true,
regional_categories = "Acadian",
parent = "Canada",
}
labels["Alberta"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Atlantic Canada"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = "Atlantic Canadian",
parent = "Canada",
}
labels["British Columbia"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Canadian Prairies"] = {
the = true,
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Labrador"] = {
Wikipedia = true,
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Manitoba"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Multicultural Toronto English"] = {
def = "the {{w|multiethnolect|multi-ethnic dialect}} of {{catlink|Canadian English}} used in the {{w|Greater Toronto Area}}, particularly among young non-white working-class speakers",
aliases = {"MTE"},
display = "MTE",
Wikipedia = true,
plain_categories = true,
parent = "Ontario",
}
labels["New Brunswick"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Newfoundland"] = {
Wikipedia = "Newfoundland English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Northwest Territories"] = {
region = "the [[Northwest Territories]] of [[Canada]]",
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Northwestern Ontario"] = {
aliases = {"northwestern Ontario", "Northwest Ontario", "northwest Ontario"},
Wikipedia = true,
regional_categories = true,
parent = "Ontario",
}
labels["Nova Scotia"] = {
Wikipedia = "Atlantic Canadian English",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Nunavut"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Ontario"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Prince Edward Island"] = {
Wikipedia = true,
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Quebec"] = {
aliases = {"Québec"},
Wikipedia = "Quebec English",
regional_categories = true,
parent = "Canada",
}
labels["Saskatchewan"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canadian Prairies",
}
labels["Yukon"] = {
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
------------- US -------------
labels["US"] = {
region = "the [[United States]]",
aliases = {"U.S.", "United States", "United States of America", "USA", "US English", "U.S. English", "America", "American", "American English"},
Wikipedia = "en:American English",
display = "အမေရိကာန်",
regional_categories = "အမေရိကာန်",
parent = "rawposcat:North American English",
}
labels["African-American Vernacular"] = {
def = "the variety of [[English]] spoken, especially in urban communities, by most working-class and some middle-class [[African-American]]s",
addl = "It is a [[sociolect]] with significantly different grammatical characteristics from {{w|Standard English}}, especially in {{w|tense-aspect}} and [[negation]] constructions. Many African-American communities maintain [[diglossia]] between African-American Vernacular English (AAVE) and Standard English.",
aliases = {"AAVE", "African American Vernacular", "African American Vernacular English", "African-American Vernacular English", "BVE"},
Wikipedia = "African-American Vernacular English",
regional_categories = true,
parent = "African-American",
}
labels["African-American"] = {
prep = "by",
region = "[[African-American]]s in the [[United States]]",
aliases = {"AA", "African-American English", "African American", "African American English", "AAE"},
Wikipedia = "African-American English",
regional_categories = true,
parent = "US",
}
labels["Alabama"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Alaska"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northwestern US",
}
labels["Appalachia"] = {
aliases = {"Appalachian"},
Wikipedia = "en:Appalachian English",
display = "အေတ်ပလာချဳယျာ",
regional_categories = "အေတ်ပလာချဳယျာ",
parent = "US",
}
labels["Arizona"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southwestern US",
}
labels["Arkansas"] = {
Wikipedia = true,
regional_categories = "Arkansan",
parent = "South Midland US",
}
labels["Baltimore"] = {
Wikipedia = "Baltimore accent",
regional_categories = true,
parent = "Maryland",
}
labels["Boston"] = {
Wikipedia = "Boston accent",
regional_categories = true,
parent = "Massachusetts",
}
labels["Cajun"] = {
prep = "by",
region = "[[Cajun]]s in {{w|Acadiana|Southern Louisiana}}",
Wikipedia = "Cajun English",
regional_categories = true,
parent = "Louisiana",
}
labels["California"] = {
Wikipedia = "California English",
regional_categories = true,
parent = "Western US",
}
labels["Chicago"] = {
Wikipedia = {"Inland Northern American English", true},
regional_categories = true,
parent = "Illinois",
}
labels["Cincinnati"] = {
Wikipedia = "Midland American English#Cincinnati",
regional_categories = true,
parent = "Ohio,Kentucky",
}
labels["Colorado"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southwestern US",
}
labels["Connecticut"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["District of Columbia"] = {
region = "Washington, D.C.",
aliases = {"DC", "Washington, DC"},
Wikipedia = true,
regional_categories = "DC",
parent = "Mid-Atlantic US",
}
labels["Eastern New England"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["Florida"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Georgia (US)"] = {
region = "the state of [[Georgia]] in the [[United States]]",
display = "Georgia",
Wikipedia = "Georgia (U.S. state)",
regional_categories = true,
parent = "Southern US",
}
labels["Hawaii"] = {
Wikipedia = true,
regional_categories = "Hawaiian",
parent = "Western US",
}
labels["Illinois"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US,Northern US",
}
labels["Indiana"] = {
Wikipedia = "en:Indiana",
display = "အိန်ဒဳယျာနာ",
regional_categories = "အိန်ဒဳယျာနာ",
parent = "Midland US,Northern US",
}
labels["Kentucky"] = {
Wikipedia = true,
regional_categories = true,
parent = "South Midland US",
}
labels["Louisiana"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Maine"] = {
Wikipedia = "Maine accent",
regional_categories = true,
parent = "New England",
}
labels["Maryland"] = {
Wikipedia = true,
regional_categories = true,
parent = "Mid-Atlantic US",
}
labels["Massachusetts"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["Memphis"] = {
regional_categories = true,
parent = "Southern US",
}
labels["Michigan"] = {
Wikipedia = true,
regional_categories = true,
parent = "Upper Midwestern US",
}
labels["Mid-Atlantic US"] = {
region = "the [[Mid-Atlantic]] United States",
Wikipedia = "Mid-Atlantic American English",
regional_categories = true,
parent = "US",
}
labels["Midland US"] = {
region = "the American [[Midland]]",
Wikipedia = "Midland American English",
regional_categories = true,
parent = "Midwestern US",
}
labels["Midwestern US"] = {
region = "the [[Midwest]] of the [[United States]]",
aliases = {"Midwest US"},
Wikipedia = "Midwestern American English",
regional_categories = true,
parent = "US",
}
labels["Mississippi"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Missouri"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US",
}
labels["New England"] = {
Wikipedia = "en:New England English",
display = "အိန်ဂလာန်တၟိ",
regional_categories = "အိန်ဂလာန်တၟိ",
parent = "Northeastern US",
}
labels["New Jersey"] = {
Wikipedia = "en:New Jersey English",
display = "ဂျာသဳတၟိ",
regional_categories = "ဂျာသဳတၟိ",
parent = "Northeastern US",
}
labels["New Mexico"] = {
Wikipedia = "Western American English#New Mexico",
regional_categories = true,
parent = "Southwestern US",
}
labels["New Orleans"] = {
Wikipedia = "en:New Orleans English",
display = "နယူအေဝ်လေန်",
regional_categories = "နယူအေဝ်လေန်",
parent = "Louisiana",
}
labels["New York City"] = {
aliases = {"NYC"},
Wikipedia = "en:New York City English",
display = "ဍုၚ်နယူယံက်",
regional_categories = "ဍုၚ်နယူယံက်",
parent = "New York",
}
labels["New York"] = {
region = "the [[United States]] state of [[New York]]",
aliases = {"NY"},
Wikipedia = "en:New York English (disambiguation)",
display = "နယူယံက်",
regional_categories = "နယူယံက်",
parent = "Northeastern US",
}
labels["North Carolina"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
-- can be split off if enough entries in it arise; group with Midland US for now
labels["North Midland US"] = {
aliases = {"Northern Midland US"},
Wikipedia = "Midland American English",
regional_categories = "Midland US",
}
labels["Northeastern US"] = {
region = "the {{w|Northeastern United States}}",
aliases = {"Northeast US"},
Wikipedia = {"Northern American English#Northeastern American English"},
regional_categories = true,
parent = "Northern US",
}
-- can be split off if enough entries in it arise; group with California for now
labels["Northern California"] = {
Wikipedia = "California English",
regional_categories = "California",
}
labels["Northwestern US"] = {
region = "the {{w|Northwestern United States}}",
aliases = {"Northwest US", "Pacific Northwest"},
Wikipedia = {"Pacific Northwest English", "Northwestern United States"},
regional_categories = true,
parent = "Western US",
}
labels["Ohio"] = {
Wikipedia = true,
regional_categories = true,
parent = "Midland US,Northern US",
}
labels["Oklahoma"] = {
Wikipedia = true,
regional_categories = true,
parent = "South Midland US",
}
labels["Pennsylvania Dutch English"] = {
prep = "by",
region = "{{w|Pennsylvania Dutch}} people in south-central [[Pennsylvania]]",
Wikipedia = true,
plain_categories = true,
parent = "Pennsylvania",
}
labels["Pennsylvania"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northeastern US",
}
-- can be split off if enough entries in it arise; group with Pennsylvania for now
labels["Philadelphia"] = {
Wikipedia = "Philadelphia English",
regional_categories = true,
parent = "Pennsylvania,Mid-Atlantic US",
}
-- can be split off if enough entries in it arise; group with Western Pennsylvania for now
labels["Pittsburgh"] = {
Wikipedia = "Western Pennsylvania English",
regional_categories = "Western Pennsylvania",
parent = "Pennsylvania",
}
labels["Pittsburghese"] = {
Wikipedia = "Western Pennsylvania English",
regional_categories = "Western Pennsylvania",
parent = "Pennsylvania",
}
labels["Rhode Island"] = {
Wikipedia = true,
regional_categories = true,
parent = "New England",
}
labels["South Carolina"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
-- can be split off if enough entries in it arise; group with Midland US for now
labels["South Midland US"] = {
aliases = {"Southern Midland US"},
Wikipedia = "Midland American English",
regional_categories = "Midland US",
}
-- can be split off if enough entries in it arise; group with California for now
labels["Southern California"] = {
Wikipedia = "California English",
regional_categories = "California",
}
labels["Southern US"] = {
region = "the {{w|Southern United States}}",
aliases = {"Southern American English", "southern US", "US South"},
Wikipedia = "en:Southern American English",
display = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "US",
}
labels["Southwestern US"] = {
region = "the {{w|Southwestern United States}}",
aliases = {"southwestern US", "Southwest US", "southwest US"},
Wikipedia = {"Western American English", "Southwestern United States"},
regional_categories = true,
parent = "Western US",
}
labels["St. Louis"] = {
Wikipedia = "St. Louis dialect",
regional_categories = true,
parent = "Missouri,Illinois",
}
labels["St. Vincent"] = {
Wikipedia = "Saint Vincent (Saint Vincent and the Grenadines)",
regional_categories = "Saint Vincentian",
parent = "Caribbean",
}
labels["Texas"] = {
Wikipedia = "Texan English",
regional_categories = true,
parent = "Southern US,Southwestern US",
}
labels["Upper Midwestern US"] = {
region = "the {{w|Upper Midwest}} of the [[United States]]",
aliases = {"Upper Midwest US"},
Wikipedia = {"North-Central American English", "Upper Midwest"},
regional_categories = true,
parent = "Midwestern US,Northern US",
}
labels["Vermont"] = {
Wikipedia = {"New England English", "Vermont"},
regional_categories = true,
parent = "New England",
}
labels["Virginia"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern US",
}
labels["Western Pennsylvania"] = {
aliases = {"Western Pennsylvania English"},
Wikipedia = "Western Pennsylvania English",
regional_categories = true,
parent = "Pennsylvania",
}
labels["Western US"] = {
region = "the {{w|Western United States}}",
aliases = {"western US"},
Wikipedia = {"en:Western American English", "en:Western United States"},
display = "အမေရိကာန်လ္ပာ်ဖာပလိုတ်",
regional_categories = "အမေရိကာန်လ္ပာ်ဖာပလိုတ်",
parent = "US",
}
labels["Wisconsin"] = {
Wikipedia = true,
regional_categories = true,
parent = "Upper Midwestern US",
}
------------------------------------ Australia and New Zealand ------------------------------------
labels["Australian Aboriginal"] = {
prep = "by",
region = "[[Aboriginal]] people in [[Australia]]",
aliases = {"Australian aboriginal", "Australian Aboriginal English", "Australian aboriginal English", "Aboriginal Australian", "aboriginal Australian", "Aboriginal Australian English", "aboriginal Australian English"},
Wikipedia = "Australian Aboriginal English",
regional_categories = true,
parent = "Australia",
}
labels["Australia"] = {
aliases = {"Australian", "AU", "AuE", "Aus", "AusE", "General Australian"},
Wikipedia = "Australian English",
accent_Wikipedia = "Australian English phonology",
accent_display = "အမေရိကာန်နာနာသာ်",
regional_categories = "အဝ်သတြေလျာ",
parent = "Oceania,Commonwealth",
}
labels["Canberra"] = {
region = "the [[Australian Capital Territory]] ([[Canberra]])",
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["New South Wales"] = {
aliases = {"NSW"},
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["New Zealand"] = {
aliases = {"NZ", "NZE"},
Wikipedia = "en:New Zealand English",
accent_Wikipedia = "New Zealand English phonology",
display = "နယူဇြဳလာန်",
regional_categories = "နယူဇြဳလာန်",
parent = "Oceania,Commonwealth",
}
labels["Northern Territory"] = {
aliases = {"NT"},
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["Northern US"] = {
region = "the {{w|Northern United States}}",
aliases = {"Northern American English", "northern US", "US North"},
Wikipedia = "en:Northern American English",
display = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "US",
}
labels["Queensland"] = {
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = true,
parent = "Australia",
}
labels["South Australia"] = {
Wikipedia = "South Australian English",
regional_categories = "South Australian",
parent = "Australia",
}
labels["Tasmania"] = {
Wikipedia = {"Variation in Australian English#Regional variation", true},
regional_categories = "Tasmanian",
parent = "Australia",
}
labels["Victoria"] = {
Wikipedia = {"Variation in Australian English#Regional variation", "Victoria (state)"},
regional_categories = true,
parent = "Australia",
}
labels["Western Australia"] = {
Wikipedia = "Western Australian English",
regional_categories = "Western Australian",
parent = "Australia",
}
------------------------------------ Ireland ------------------------------------
labels["Cork"] = {
Wikipedia = {"South-West Irish English", "Cork (city)"},
regional_categories = "Munster",
}
labels["Dublin"] = {
Wikipedia = {"Dublin English", "Dublin", "DE"},
regional_categories = true,
parent = "Ireland",
}
labels["Ireland"] = {
aliases = {"Irish", "IE"},
Wikipedia = "Hiberno-English",
regional_categories = "Irish",
parent = "Europe",
}
labels["Munster"] = {
Wikipedia = {"South-West Irish English", "Munster"},
regional_categories = true,
parent = "Ireland",
}
------------------------------------ United Kingdom ------------------------------------
labels["British"] = {
region = "Great Britain",
addl = "Not to be confused with [[:Category:British English forms|British spellings]], a spelling system used in some English-speaking countries of the world.",
aliases = {"Britain", "Great Britain"},
Wikipedia = "en:British English",
display = "ဗြေတ်တိန်",
regional_categories = "ဗြေတ်တိန်",
parent = "Europe,Commonwealth",
country = "the United Kingdom",
}
labels["UK"] = {
aliases = {"United Kingdom"},
Wikipedia = "en:British English",
display = "ဗြေတ်တိန်",
regional_categories = "ဗြေတ်တိန်",
}
labels["Antrim"] = {
Wikipedia = "County Antrim",
regional_categories = "Northern Irish",
}
labels["Bedfordshire"] = {
Wikipedia = "Bedfordshire dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Berkshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Birmingham"] = {
Wikipedia = "Brummie dialect",
regional_categories = true,
parent = "West Midlands",
}
labels["Bristol"] = {
region = "[[Bristol]], [[England]]",
aliases = {"Bristolian"},
Wikipedia = "Bristolian dialect",
regional_categories = "Bristolian",
parent = "West Country",
}
labels["Caithness"] = {
Wikipedia = true,
regional_categories = true,
parent = "Scotland",
}
labels["Cambridge University"] = {
prep = "at",
region = "{{w|Cambridge University}} in [[Cambridge]]",
aliases = {"University of Cambridge", "Cantab"},
Wikipedia = "University of Cambridge",
regional_categories = true,
parent = "East Anglia",
othercat = "en:Universities",
}
labels["Channel Islands"] = {
the = true,
Wikipedia = "Channel Island English",
regional_categories = true,
parent = "Europe,Commonwealth",
}
labels["Cockney"] = {
prep = "by",
region = "working-class [[Londoner]]s, especially in the [[East End]]",
Wikipedia = "Cockney#Speech",
regional_categories = true,
parent = "London",
}
labels["Cornwall"] = {
aliases = {"Cornish"},
Wikipedia = "Cornish dialect",
regional_categories = "Cornish",
parent = "West Country",
}
labels["Cumbria"] = {
aliases = {"Cumbrian"},
Wikipedia = "Cumbrian dialect",
regional_categories = "Cumbrian",
parent = "Northern England",
}
labels["Derbyshire"] = {
region = "[[Derbyshire]], which is geographically in the East Midlands but whose dialect is sometimes classified as West Midlands",
Wikipedia = "Derbyshire dialect",
regional_categories = true,
parent = "East Midlands,West Midlands",
}
labels["Devon"] = {
aliases = {"Devonshire"},
Wikipedia = {"West Country English", true},
regional_categories = "Devonian",
parent = "West Country",
}
labels["Dorset"] = {
Wikipedia = "Dorset dialect",
regional_categories = true,
parent = "West Country",
}
labels["Dundee"] = {
Wikipedia = true,
regional_categories = true,
parent = "Scotland",
}
labels["Durham University"] = {
prep = "at",
region = "{{w|Durham University}} in [[Durham]]",
Wikipedia = true,
regional_categories = true,
parent = "Durham",
othercat = "en:Universities",
}
labels["Durham"] = {
Wikipedia = "County Durham",
regional_categories = true,
parent = "Northumbria",
}
labels["East Anglia"] = {
Wikipedia = "East Anglian English",
regional_categories = "East Anglian",
parent = "England",
}
labels["East Midlands"] = {
region = "the [[East Midlands]] of [[England]]",
Wikipedia = "East Midlands English",
regional_categories = true,
parent = "Midlands",
}
labels["England"] = {
aliases = {"English"},
Wikipedia = "en:English language in England",
display = "အိန်ဂလာန်",
regional_categories = "အၚ်္ဂလိက်",
parent = "British",
}
labels["England and Wales"] = {
aliases = {"E&W"},
Wikipedia = true,
regional_categories = {"English", "Welsh"},
}
labels["Essex"] = {
Wikipedia = "Essex dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Exmoor"] = {
Wikipedia = true,
regional_categories = {"Devonian", "Somerset"},
}
labels["Geordie"] = {
region = "Tyneside",
aliases = {"Geordie English", "Tyneside"},
Wikipedia = ":en:Geordie",
display = "ကျဝ်ဒဳ",
plain_categories = "ကျဝ်ဒဳ",
parent = "Northumbria",
}
labels["Gloucestershire"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
labels["Guernsey"] = {
prep = "on",
Wikipedia = "Channel Island English#Guernsey English",
regional_categories = true,
parent = "Channel Islands",
}
labels["Hartlepool"] = {
Wikipedia = "Smoggie",
regional_categories = "Teesside",
}
labels["Herefordshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "West Country",
}
labels["Isle of Man"] = {
prep = "on",
the = true,
aliases = {"Manx"},
Wikipedia = "Manx English",
regional_categories = "Manx",
parent = "British",
}
labels["Isle of Wight"] = {
prep = "on",
the = true,
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Jersey"] = {
prep = "on",
Wikipedia = "Channel Island English#Jersey English",
regional_categories = true,
parent = "Channel Islands",
}
labels["Kent"] = {
aliases = {"Kentish"},
Wikipedia = "Kentish dialect",
regional_categories = "Kentish",
parent = "Southern England",
}
labels["Lancashire"] = {
Wikipedia = "Lancashire dialect",
regional_categories = true,
parent = "Northern England",
}
labels["Lewis"] = {
prep = "on",
region = "the [[Isle of Lewis]]",
aliases = {"Isle of Lewis"},
Wikipedia = "Isle of Lewis",
regional_categories = true,
parent = "Scotland",
}
labels["Lincolnshire"] = {
Wikipedia = "Lincolnshire dialect",
regional_categories = true,
parent = "East Midlands",
}
labels["Liverpool"] = {
region = "the {{w|Liverpool City Region}}, comprising the [[metropolitan county]] of [[Merseyside]] and the [[Cheshire]] [[unitary authority]] of [[Halton]]",
aliases = {"Scouse"},
Wikipedia = "Scouse",
regional_categories = "Liverpudlian",
parent = "Northern England",
}
labels["London"] = {
Wikipedia = "Estuary English",
regional_categories = true,
parent = "Southern England",
}
labels["Manchester"] = {
aliases = {"Mancunian"},
Wikipedia = "Manchester dialect",
regional_categories = "Mancunian",
parent = "Northern England",
}
labels["Mid-Ulster"] = {
region = "central [[Ulster]]",
aliases = {"Mid-Ulster English"},
Wikipedia = "Mid-Ulster English",
regional_categories = true,
parent = "Ulster,Northern Ireland",
}
labels["Midlands"] = {
region = "the [[Midlands]] of [[England]]",
aliases = {"English Midlands", "South Midlands"},
Wikipedia = "Midlands English",
regional_categories = true,
parent = "England",
}
labels["Multicultural London English"] = {
prep = "by",
region = "young, working-class people in multicultural parts of [[London]]",
aliases = {"MLE"},
display = "MLE",
Wikipedia = true,
plain_categories = true,
parent = "London",
}
labels["Norfolk"] = {
Wikipedia = "Norfolk dialect",
regional_categories = true,
parent = "East Anglia",
}
labels["North Wales"] = {
Wikipedia = {"Welsh English", true},
regional_categories = true,
parent = "Wales",
}
labels["Northern England"] = {
aliases = {"northern England", "North England", "north England"},
Wikipedia = "en:English language in Northern England",
display = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "England",
}
labels["Northern Ireland"] = {
aliases = {"Northern Irish", "NI"},
Wikipedia = "Ulster English",
regional_categories = "Northern Irish",
parent = "Ulster",
}
labels["Northern Isles"] = {
display = "[[w:Orkney|Orkney]], [[w:Shetland|Shetland]]",
regional_categories = {"Orkney", "Shetland"},
}
labels["Northumberland"] = {
Wikipedia = {"Northumberland"},
regional_categories = true,
parent = "Northumbria",
}
labels["Northumbria"] = {
aliases = {"Northumbrian", "Northeast England", "North-East England", "North East England"},
Wikipedia = {"Northumbrian dialect", "Northumbria (modern)"},
regional_categories = "Northumbrian",
parent = "Northern England",
}
labels["Nottinghamshire"] = {
Wikipedia = "Nottinghamshire dialect",
regional_categories = true,
parent = "East Midlands",
}
labels["Orkney"] = {
prep = "on",
aliases = {"Orcadian"},
Wikipedia = {true, "Highland English"},
regional_categories = true,
parent = "Scotland",
}
labels["Oxbridge"] = {
Wikipedia = true,
regional_categories = {"Cambridge University", "Oxford University"},
}
labels["Oxford City"] = {
region = "the city of [[Oxford]] in [[England]]",
Wikipedia = true,
regional_categories = "Oxford",
parent = "Oxfordshire",
}
labels["Oxford University"] = {
prep = "at",
aliases = {"University of Oxford", "Oxon"},
Wikipedia = "University of Oxford",
regional_categories = true,
parent = "Oxford City",
othercat = "en:Universities",
}
labels["Oxfordshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "Southern England",
}
labels["Pitmatic"] = {
Wikipedia = true,
regional_categories = true,
parent = "Northumbria",
}
labels["Potteries"] = {
region = "Stoke-on-Trent",
Wikipedia = "Potteries dialect",
regional_categories = true,
parent = "West Midlands",
}
labels["Scotland"] = {
aliases = {"Scottish", "Scottish English", "ScE"},
Wikipedia = "Scottish English",
regional_categories = "Scottish",
parent = "British",
}
labels["Shetland"] = {
region = "the [[Shetland Islands]]",
aliases = {"Shetland Islands", "Shetlands"},
Wikipedia = {true, "Highland English"},
regional_categories = true,
parent = "Scotland",
}
labels["Shropshire"] = {
Wikipedia = true,
regional_categories = true,
parent = "West Midlands",
}
labels["Somerset"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
-- eventually maybe break this out into its own category
labels["South Midlands"] = {
Wikipedia = {"Midlands English", "South Midlands"},
regional_categories = "Midlands",
}
labels["South Wales"] = {
Wikipedia = {"Welsh English", true},
regional_categories = true,
parent = "Wales",
}
labels["Southern England"] = {
aliases = {"southern England", "South England", "south England", "Southern English"},
Wikipedia = "en:English in southern England",
display = "အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories ="အိန်ဂလာန်လ္ပာ်ဒိုဟ်သမၠုၚ်ကျာ",
parent = "England",
}
labels["Suffolk"] = {
Wikipedia = "Suffolk dialect",
regional_categories = true,
parent = "East Anglia",
}
labels["Sussex"] = {
Wikipedia = "Sussex dialect",
regional_categories = true,
parent = "Southern England",
}
labels["Teesside"] = {
Wikipedia = "Smoggie",
regional_categories = true,
parent = "Northumbria",
}
-- Tyneside: see Geordie
labels["Ulster"] = {
Wikipedia = "Ulster English",
regional_categories = true,
parent = "Ireland",
}
labels["Wales"] = {
aliases = {"Welsh"},
Wikipedia = "Welsh English",
regional_categories = "Welsh",
parent = "British",
}
labels["Wearside"] = {
Wikipedia = {"Mackem", true},
regional_categories = true,
parent = "Northumbria",
}
labels["West Country"] = {
the = true,
aliases = {"West England", "west England"},
Wikipedia = "West Country English",
regional_categories = true,
parent = "England",
}
-- can be split off if enough entries in it arise; group with Cumbria for now
labels["West Cumbria"] = {
Wikipedia = "Cumbrian dialect",
regional_categories = "Cumbrian",
}
labels["West Midlands"] = {
region = "the [[West Midlands]] of [[England]]",
Wikipedia = "West Midlands English",
regional_categories = true,
parent = "Midlands",
}
labels["Wiltshire"] = {
Wikipedia = {"West Country English", true},
regional_categories = true,
parent = "West Country",
}
labels["Yorkshire"] = {
Wikipedia = "Yorkshire dialect",
regional_categories = true,
parent = "Northern England",
}
-------------------------------- South Asia --------------------------------
labels["South Asia"] = {
aliases = {"Indic", "South Asian", "Desi", "Deshi"},
Wikipedia = "en:South Asian English",
accent_display = "အိန်ဒဳစ်",
regional_categories = "အာသျှဒိုဟ်သမၠုၚ်ကျာ",
parent = "Asia",
}
labels["Afghanistan"] = {
Wikipedia = true,
regional_categories = "Afghan",
parent = "South Asia",
}
labels["Bangladesh"] = {
Wikipedia = "Bangladeshi English",
regional_categories = "Bangladeshi",
parent = "South Asia,Commonwealth",
}
labels["Nepal"] = {
Wikipedia = "Nepalese English",
regional_categories = "Nepali",
parent = "South Asia,Commonwealth",
}
labels["Sri Lanka"] = {
aliases = {"Sri Lankan"},
Wikipedia = "Sri Lankan English",
regional_categories = "Sri Lankan",
parent = "South Asia,Commonwealth",
}
labels["Pakistan"] = {
aliases = {"Pakistani"},
Wikipedia = "Pakistani English",
regional_categories = "Pakistani",
parent = "South Asia,Commonwealth",
}
labels["British Pakistani"] = {
prep = "by",
region = "{{w|British Pakistanis}}, i.e. [[British]] citizens of [[Pakistani]] origin",
Wikipedia = "British Pakistanis",
regional_categories = true,
parent = "South Asia,British",
}
labels["British India"] = {
fulldef = "Anglo-Indian terms or senses in English as used formerly by Britishers in {{w|British India}}",
Wikipedia = "Indian English", -- The WP articles are strictly divided by geography, not historical period
regional_categories = true,
parent = "South Asia,British",
othercat = "English terms with historical senses",
}
labels["India"] = {
aliases = {"Indian", "Indian English", "InE"},
Wikipedia = "Indian English",
accent_Wikipedia = "Indian English#Phonology",
regional_categories = "Indian",
parent = "South Asia,Commonwealth",
}
labels["North India"] = {
Wikipedia = true,
regional_categories = "North Indian",
parent = "India",
}
labels["South India"] = {
aliases = {"South Indian"},
Wikipedia = true,
regional_categories = "South Indian",
parent = "India",
}
labels["West Bengal"] = {
Wikipedia = true,
accent_Wikipedia = "Regional differences and dialects in Indian English#Bengali English",
regional_categories = true,
parent = "India",
}
labels["Hinglish"] = {
def = "[[Hinglish]], an English-based [[creole]] incorporating many [[Hindi]] words; used informally in [[India]]",
Wikipedia = true,
plain_categories = true,
parent = "North India",
}
labels["Tamil Nadu"] = {
aliases = {"TN", "Tamilnadu"},
accent_Wikipedia = "Regional differences and dialects in Indian English#Southern Indian English",
parent="South India"
}
labels["Kerala"] = {
accent_Wikipedia = "Regional differences and dialects in Indian English#Malayali",
aliases = { "Malayalam", "Mallu" },
parent = "South India"
}
------------------------------------ World ------------------------------------
labels["Africa"] = {
aliases = {"African"},
Wikipedia = "African English",
regional_categories = "African",
parent = true,
}
labels["Antarctica"] = {
Wikipedia = "Antarctic English",
regional_categories = "Antarctic",
parent = true,
}
labels["Asia"] = {
Wikipedia = "Asian English",
regional_categories = "Asian",
parent = true,
}
labels["Bahamas"] = {
the = true,
Wikipedia = "Bahamian English",
regional_categories = "Bahaman",
parent = "Caribbean",
}
labels["Barbados"] = {
Wikipedia = "English in Barbados",
regional_categories = "Barbadian",
parent = "Caribbean",
}
labels["Belize"] = {
Wikipedia = "Belizean English",
regional_categories = "Belizean",
parent = "Caribbean,Central America",
}
labels["Benglish"] = {
def = "[[Benglish]], an English-based [[creole]] incorporating many [[Bengali]] words; used informally in [[Bangladesh]] and [[West Bengal]]",
aliases = {"Banglish"},
Wikipedia = true,
plain_categories = true,
parent = "Bangladesh,West Bengal",
}
labels["Bermuda"] = {
Wikipedia = "Bermudian English",
regional_categories = "Bermudian",
parent = "Caribbean,rawposcat:North American English,British",
}
labels["Botswana"] = {
Wikipedia = "Botswana English",
regional_categories = "Botswanan",
parent = "Africa",
}
labels["Brunei"] = {
Wikipedia = "Brunei English",
regional_categories = "Bruneian",
parent = "Southeast Asia",
}
labels["Cameroon"] = {
aliases = {"CM", "Cameroonian", "Cameroonian English", "en-CM"},
Wikipedia = "Cameroonian English",
regional_categories = "Cameroonian",
parent = "Africa",
}
labels["Caribbean"] = {
the = true,
aliases = {"West Indies"},
Wikipedia = "Caribbean English",
regional_categories = true,
parent = true,
}
labels["Cebu"] = {
Wikipedia = true,
regional_categories = true,
parent = "Philippines",
}
labels["Central America"] = {
Wikipedia = true,
regional_categories = "Central American",
parent = "rawposcat:North American English",
}
labels["Ceylon"] = {
Wikipedia = true,
regional_categories = "Sri Lankan",
}
labels["China"] = {
Wikipedia = "en:China",
display = "ဍုၚ်ကြုက်",
regional_categories = "ဂကူကြုက်",
parent = "East Asia",
}
labels["Chinese Filipino"] = {
verb = "used",
prep = "by",
region = "Chinese Filipinos",
aliases = {"Chinese-Filipino"}, -- Sociolect subset to Philippine English
-- may also see "Hokaglish" in Wikipedia, although Hokaglish is the codeswitching form with a Hokkien or Tagalog base, just like Philippine English to "Conyo" (English-based) and "Taglish" (Tagalog-based), whereas this is the English variant itself subset to Philippine English.
Wikipedia = "Chinese Filipino#Language",
regional_categories = true,
parent = "Philippines",
}
labels["Chinglish"] = {
def = "[[English]] that has been influenced by [[Chinese]]",
Wikipedia = true,
plain_categories = true,
parent = "China",
}
labels["Commonwealth"] = {
region = "the [[Commonwealth of Nations]]",
Wikipedia = "en:English in the Commonwealth of Nations",
display = "ဓနသဟာယ",
regional_categories = "ဓနသဟာယ",
parent = true,
}
labels["Cuba"] = {
Wikipedia = true,
regional_categories = "Cuban",
parent = "Caribbean",
}
labels["East Africa"] = {
Wikipedia = true,
regional_categories = "East African",
parent = "Africa",
}
labels["East Asia"] = {
Wikipedia = true,
regional_categories = "East Asian",
parent = "Asia",
}
labels["Egypt"] = {
Wikipedia = "en:Egypt",
display = "အဳဂျေပ်",
regional_categories = "ဍုၚ်အဳဂျေပ်",
parent = "Africa,Middle East",
}
labels["Europe"] = {
aliases = {"European"},
Wikipedia = "English language in Europe",
regional_categories = "European",
parent = true,
}
labels["Fiji"] = {
Wikipedia = "Fijian English",
regional_categories = "Fijian",
parent = "Oceania,Commonwealth",
}
labels["Ghana"] = {
Wikipedia = "Ghanaian English",
regional_categories = "Ghanaian",
parent = "West Africa",
}
labels["Guyana"] = {
Wikipedia = {"Guyanese English", "Guyana"},
regional_categories = "Guyanese",
parent = "Caribbean,South America",
}
labels["Hong Kong"] = {
aliases = {"HK"},
Wikipedia = "Hong Kong English",
regional_categories = true,
parent = "China",
}
labels["Hungary"] = {
Wikipedia = true,
regional_categories = "Hungarian",
parent = "Europe",
}
labels["Indonesia"] = {
Wikipedia = "Indonesian English",
regional_categories = "Indonesian",
parent = "Southeast Asia",
}
labels["Israel"] = {
Wikipedia = "Israeli English",
regional_categories = "Israeli",
parent = "Middle East",
}
labels["Japan"] = {
Wikipedia = "en:Japan",
display = "ဍုၚ်ဂျပါန်",
regional_categories = "ဂကူဂျပါန်",
parent = "East Asia",
}
labels["Jamaica"] = {
aliases = {"Jamaican English", "Jamaican"},
Wikipedia = "Jamaican English",
regional_categories = "Jamaican",
parent = "Caribbean,Commonwealth",
}
labels["Kenya"] = {
Wikipedia = "Kenyan English",
regional_categories = "Kenyan",
parent = "East Africa",
}
labels["Liberia"] = {
Wikipedia = "Liberian English",
regional_categories = "Liberian",
parent = "West Africa",
}
labels["Libya"] = {
Wikipedia = true,
regional_categories = "Libyan",
parent = "Africa",
}
labels["Macau"] = {
Wikipedia = true,
regional_categories = "Macanese",
parent = "China",
}
labels["Mainland China"] = {
aliases = {"Mainland", "mainland", "mainland China"},
Wikipedia = true,
regional_categories = true,
parent = "China",
}
labels["Malaysia"] = {
aliases = {"Malaysian"},
Wikipedia = "Malaysian English",
regional_categories = "Malaysian",
parent = "Southeast Asia,Commonwealth",
}
labels["Malta"] = {
Wikipedia = "Maltese English",
regional_categories = "Maltese",
parent = "Europe",
}
labels["Manglish"] = {
def = "[[Manglish]], an English-based [[creole]] incorporating [[Malay]], [[Chinese]], and [[Tamil]] words; used informally in [[Malaysia]]",
Wikipedia = true,
plain_categories = true,
parent = "Malaysia",
}
labels["Mexico"] = {
Wikipedia = {"Mexican English", "Mexico"},
regional_categories = "Mexican",
parent = "rawposcat:North American English",
}
labels["Middle East"] = {
the = true,
Wikipedia = true,
regional_categories = "Middle Eastern",
parent = true,
}
labels["Myanmar"] = {
aliases = {"Burma"},
Wikipedia = "en:Myanmar English",
display = "ဍုၚ်ဗၟာ",
regional_categories = "ဍုၚ်ဗၟာ",
parent = "Southeast Asia",
}
labels["Namibia"] = {
Wikipedia = "Namibian English",
regional_categories = "Namibian",
parent = "Africa",
}
labels["Natal"] = {
Wikipedia = "KwaZulu-Natal",
regional_categories = true,
parent = "South Africa",
}
labels["Nigeria"] = {
aliases = {"Nigerian"},
Wikipedia = "Nigerian English",
regional_categories = "Nigerian",
parent = "West Africa",
}
labels["Oceania"] = {
Wikipedia = "Oceanian English",
regional_categories = "Oceanian",
parent = true,
}
labels["Palestine"] = {
Wikipedia = true,
regional_categories = "Palestinian",
parent = "Middle East",
}
labels["Papua New Guinea"] = {
Wikipedia = "Papua New Guinean English",
regional_categories = "Papua New Guinean",
parent = "Oceania,Commonwealth",
}
labels["Philippines"] = {
the = true,
aliases = {"Philippine", "Philippine English"},
Wikipedia = "en:Philippine English",
display = "ဖိလေတ်ပေန်",
regional_categories = "ဖိလေတ်ပေန်",
parent = "Southeast Asia",
}
labels["Baguio"] = {
Wikipedia = true,
regional_categories = true,
parent = "Philippines",
}
labels["Réunion"] = {
Wikipedia = true,
regional_categories = true,
parent = "Africa",
}
labels["Rhodesia"] = {
region = "the historical state of [[Rhodesia]]",
Wikipedia = "Zimbabwean English",
regional_categories = "Rhodesian",
parent = "Africa",
}
labels["Rwanda"] = {
Wikipedia = true,
regional_categories = "Rwandan",
parent = "Africa",
}
labels["Singapore"] = {
aliases = {"SG", "Singaporean"},
Wikipedia = "Singapore English",
regional_categories = true,
parent = "Southeast Asia,Commonwealth",
}
labels["Singlish"] = {
def = "[[Singlish]], an English-based [[creole]] incorporating many words of [[Chinese]], [[Malay]] and [[Indian]] origin; used informally in [[Singapore]]",
Wikipedia = true,
plain_categories = true,
parent = "Singapore",
}
labels["Solomon Islands"] = {
the = true,
Wikipedia = "Solomon Islands English",
regional_categories = true,
parent = "Oceania",
}
labels["South Africa"] = {
aliases = {"South African", "South African English", "ZA"},
Wikipedia = "South African English",
accent_Wikipedia = "South African English phonology",
accent_display = "General South African",
regional_categories = "South African",
parent = "Africa,Commonwealth",
}
labels["South America"] = {
aliases = {"South American"},
Wikipedia = "en:South American English",
display = "အမေရိကာန်ဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "အမေရိကာန်ဒိုဟ်သမၠုၚ်ကျာ",
parent = true,
}
labels["South Korea"] = {
Wikipedia = "en:Korean English",
display = "ကိုဝ်ရဳယျာဒိုဟ်သမၠုၚ်ကျာ",
regional_categories = "ကိုဝ်ရဳယျာဒိုဟ်သမၠုၚ်ကျာ",
parent = "East Asia",
}
labels["Southeast Asia"] = {
aliases = {"Southeast Asian", "South-East Asia", "South-East Asian", "South-east Asia", "South-east Asian", "SEA"},
Wikipedia = "Southeast Asian English",
regional_categories = "Southeast Asian",
parent = "Asia",
}
labels["Taiwan"] = {
aliases = {"Taiwanese"},
Wikipedia = "en:Taiwan",
display = "ထာၚ်ဝါန်",
regional_categories = "ဍုၚ်ထာၚ်ဝါန်",
parent = "East Asia",
}
labels["Tanzania"] = {
aliases = {"Tanzanian"},
Wikipedia = true,
regional_categories = "Tanzanian",
parent = "East Africa",
}
labels["Thailand"] = {
Wikipedia = "en:Tinglish",
display = "ဍုၚ်သေံ",
regional_categories = "သေံ",
parent = "Southeast Asia",
}
labels["Trinidad and Tobago"] = {
aliases = {"Trinidad", "Tobago", "Trinidadian"},
Wikipedia = "Trinidadian and Tobagonian English",
regional_categories = true,
parent = "Caribbean",
}
labels["Uganda"] = {
Wikipedia = "Ugandan English",
regional_categories = "Ugandan",
parent = "Africa",
}
labels["Vanuatu"] = {
Wikipedia = "Vanuatuan English",
regional_categories = true,
parent = "Oceania",
}
labels["Vietnam"] = {
Wikipedia = "Vietglish",
regional_categories = "Vietnamese",
parent = "Southeast Asia",
}
labels["West Africa"] = {
aliases = {"West African"},
Wikipedia = true,
regional_categories = "West African",
parent = "Africa",
}
labels["Zimbabwe"] = {
Wikipedia = "Zimbabwean English",
regional_categories = true,
parent = "Africa",
}
------------------------------------ non-regional ------------------------------------
labels["DoggoLingo"] = {
def = "[[DoggoLingo]]",
display = "[[DoggoLingo]]",
noreg = true,
plain_categories = true,
othercat = "English internet slang",
parent = "internet slang",
}
labels["Early Modern"] = {
prep = "from",
region = "the late 15th to the mid-17th centuries",
noreg = true,
nolink = true,
aliases = {"Early Modern English", "EME"},
Wikipedia = "Early Modern English",
regional_categories = true,
parent = true,
}
labels["Late Modern"] = {
prep = "from",
region = "the mid-17th to the end of the 19th centuries",
noreg = true,
nolink = true,
aliases = {"Late Modern English", "LME"},
Wikipedia = "Late Modern English",
regional_categories = true,
parent = true,
}
-- ideally this would sit at [[Module:category tree/pragmatic properties]] so it can be used for all languages, but those cats needs to begin with the language name...
labels["non-native speakers' English"] = {
display = "[[non-native speaker]]s' English",
noreg = true,
aliases = {"NNES", "NNSE"},
regional_categories = "Non-native speakers'",
Wikipedia = "English as a second or foreign language",
accent_Wikipedia = "Non-native pronunciations of English",
othercat = "English nonstandard terms,English terms by usage,English terms by orthographic property",
}
labels["Polari"] = {
def = "a form of cant slang used in [[Britain]] by some actors, circus and fairground showmen, professional wrestlers, merchant navy sailors, criminals, prostitutes, and the gay subculture",
noreg = true,
country = "the United Kingdom",
Wikipedia = true,
plain_categories = true,
othercat = "British slang,English cant,English gay slang",
parent = true,
}
-- Thieves' Cant is English-only, for other languages, use "criminal slang"
labels["thieves' cant"] = {
fulldef = "A secret language formerly used by thieves, beggars and hustlers of various kinds in [[Great Britain]] and to a lesser extent in other English-speaking countries",
noreg = true,
aliases = {"Thieves' Cant", "Thieves' cant", "thieves cant", "thieves'", "thieves"},
Wikipedia = true,
-- FIXME: Currently pos_categories aren't recognized.
-- pos_categories = "Thieves' Cant",
plain_categories = "English Thieves' Cant",
parent = true,
othercat = "English cant",
}
------------------------------------ English-specific qualifier labels ------------------------------------
labels["attributive"] = {
display = "[[Appendix:English nouns#Attributive|attributive]]",
}
labels["attributively"] = {
display = "[[Appendix:English nouns#Attributive|attributively]]",
}
------------------------------------ supporting [[Template:standard spelling of]] et al. ------------------------------------
labels["American spelling"] = {
aliases = {"American form", "US spelling", "US form",
-- As in "color" vs. "colour"
"or form", "-or form",
"or spelling", "-or spelling",
-- As in "meter" vs. "metre"
"er form", "-er form",
"er spelling", "-er spelling"
},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "အမေရိကာန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်",
}
labels["Australian spelling"] = {
aliases = {"Australian form"},
Wikipedia = "en:Australian English#Spelling and style",
form_of_display = "အမေရိကာန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်",
}
labels["British spelling"] = {
aliases = {"British form", "UK spelling", "UK form"},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "ဗြေတ်တိန်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["Commonwealth spelling"] = {
aliases = {"Commonwealth form",
-- As in "color" vs. "colour"
"our form", "-our form", "our spelling", "-our spelling",
-- As in "meter" vs. "metre"
"re form", "-re form", "re spelling", "-re spelling"
},
Wikipedia = "en:American and British English spelling differences",
form_of_display = "ဓနသဟာယ",
plain_categories = {"ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်", "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ခေန်နာဒါ", "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်"},
}
labels["Canadian spelling"] = {
aliases = {"Canadian form"},
Wikipedia = "en:Canadian spelling",
form_of_display = "ခေန်နာဒါ",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ခေန်နာဒါ",
}
labels["Oxford British spelling"] = {
aliases = {"Oxford", "Oxford form", "Oxford spelling", "en-GB-oxendict",},
display = "[[British English|အၚ်္ဂလိက်ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]",
plain_categories = "ခ္ဍံက်လိက်အံက်ဖှဝ်ဒ်",
}
labels["non-Oxford British spelling"] = {
aliases = {"Non-Oxford British spelling", "non-Oxford British form", "Non-Oxford British form", "non-Oxford form", "Non-Oxford form", "non-Oxford", "Non-Oxford", "not Oxford", "Not Oxford"},
display = "[[British English|အၚ်္ဂလိက်ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]-ဟွံသေၚ်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["ise spelling"] = {
aliases = {
"ise", "-ise", "ise form", "-ise form", "-ise spelling", "isation", "-isation", "isation form", "-isation form", "isation spelling", "-isation spelling",
"ise-form" -- backwards compatability
},
display = "non-[[w:Oxford spelling|Oxford]] [[w:American and British English spelling differences|British spelling]]",
form_of_display = "[[w:en:American and British English spelling differences|ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]-ဟွံသေၚ်",
plain_categories = "ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်ဗြေတ်တိန်",
}
labels["ize spelling"] = {
aliases = {
"ize", "-ize", "ize form", "-ize form", "-ize spelling", "ization", "-ization", "ization form", "-ization form", "ization spelling", "-ization spelling",
"ize-form" -- backwards compatability
},
display = "[[w:American and British English spelling differences|American]] and [[w:Oxford spelling|Oxford]] [[British English|British spelling]]",
form_of_display = "[[w:en:American and British English spelling differences|အမေရိကာန်]] ကဵု [[British English|ဗြေတ်တိန်]][[w:en:Oxford spelling|အံက်ဖှဝ်ဒ်]]",
plain_categories = {"ဗီုပြၚ်အၚ်္ဂလိက်ဍုၚ်အမေရိကာန်", "ခ္ဍံက်လိက်အံက်ဖှဝ်ဒ်"},
}
------------------------------------ supporting [[Template:inflection of]] ------------------------------------
-- This is added to an inflection line when something like {{infl of|en|make||th-form}} is used. Specifically, the form-of
-- tag 'th-form' is a shortcut for '3-th|s|spres|ind' (see [[Module:form of/lang-data/en]]); the tag '3-th' displays as
-- "third-person" (see [[Module:form of/lang-data/en]]) and attaches the following label (see [[Module:form of/cats]]).
labels["archaic third singular"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "archaic third-person singular forms",
}
-- This is added to an inflection line when something like {{infl of|en|make||st-form}} is used. See above.
labels["archaic second singular present"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "second-person singular forms",
}
-- This is added to an inflection line when something like {{infl of|en|make||st-past-form}} is used. See above.
labels["archaic second singular past"] = {
display = "archaic",
Wikipedia = "English verbs#Archaic forms",
pos_categories = "second-person singular past tense forms",
}
------------------------------------ accent qualifiers ------------------------------------
-- Generate the inverse of a sound change. In general, we should do this for sound changes that are either
-- extremely common (e.g. 'cot-caught') or dominant ('horse-hoarse', 'wine-whine') or are at least locally
-- dominant (e.g. 'cheer-chair'). The idea is that when presenting the pronunciation of an area with a locally
-- dominant pronunciation, we may want to also present the alternative pronunciation lacking the change, as long
-- as it is found at least somewhere in the area. Hence, for New Zealand, which typically has the cheer-chair
-- merger, we might might to present the non-merger pronunciation as well; but for a change like card-cord that
-- is recessive everywhere, it's unlikely we'll need to specifically highlight the inverse pronunciation (which
-- would be the standard, already covered elsewhere), and we can save memory and time by omitting the label.
local function generate_non(key, display)
if not labels[key] then
error(("Internal error: No label definition for key '%s'"):format(key))
end
local labval = mw.clone(labels[key])
labels["non-" .. key] = labval
if labval.aliases then
for i, alias in ipairs(labval.aliases) do
labval.aliases[i] = "non-" .. alias
end
end
if not display then
display = labval.display or key
if display:find("ing$") or display:find("[st]ion$") then
-- e.g. "Canadian raising", "t-glottalization"
display = "without " .. display
else
-- e.g. "cot-caught merger"
display = "without the " .. display
end
end
labval.display = display
end
labels["Anglicised"] = {
aliases = {"Anglicized"},
Wikipedia = "Anglicisation#Anglicisation of non-English-language vocabulary and names",
}
labels["Canadian raising"] = {
aliases = {"North American raising"},
Wikipedia = true,
}
generate_non("Canadian raising")
labels["Canadian Shift"] = {
aliases = {"Canadian Vowel Shift", "Canadian shift", "Canadian vowel shift"},
Wikipedia = true,
display = "Canadian Vowel Shift",
}
generate_non("Canadian Shift")
labels["card-cord"] = {
Wikipedia = "Card-cord merger",
display = "''card''–''cord'' merger",
}
labels["cheer-chair"] = {
aliases = {"near-square"},
Wikipedia = "near-square merger",
display = "''cheer''–''chair'' merger",
}
generate_non("cheer-chair")
labels["cot-caught"] = {
aliases = {"caught-cot"},
Wikipedia = "en:Cot–caught merger",
display = "''ခါတ်''–''ပံၚ်စပ်အာ''ပရေၚ်ဒုၚ်ရပ်ကေတ်မာန်",
}
generate_non("cot-caught")
labels["cure-fir"] = {
aliases = {"cure-nurse"},
Wikipedia = "Cure-nurse merger",
display = "''cure''–''fir'' merger",
}
generate_non("cure-fir")
labels["doll-dole"] = {
Wikipedia = "Doll-dole merger",
display = "''doll''–''dole'' merger",
}
labels["dough-door"] = {
Wikipedia = "Dough-door merger",
display = "''dough''–''door'' merger",
}
generate_non("dough-door")
labels["Estuary English"] = {
Wikipedia = true,
}
labels["fair-fur"] = {
aliases = {"square-nurse"},
Wikipedia = "Square-nurse merger",
display = "''fair''–''fur'' merger",
}
generate_non("fair-fur")
labels["father-bother"] = {
Wikipedia = "Father–bother merger",
display = "''father''-''bother'' merger",
}
generate_non("father-bother")
labels["fern-fir-fur"] = {
aliases = {"nurse merger"},
Wikipedia = "Fern-fir-fur merger",
display = "''fern''–''fir''–''fur'' merger",
}
generate_non("fern-fir-fur")
labels["t-flapping"] = {
Wikipedia = true,
}
generate_non("t-flapping")
labels["foot-goose"] = {
Wikipedia = "Foot-goose merger",
display = "''foot''-''goose'' merger",
}
-- Most labels of the form 'foo-bar' are mergers. Since this is rather a split, include the word "split"
-- for clarity.
labels["foot-strut split"] = {
Wikipedia = "Phonological history of English close back vowels#FOOT–STRUT split",
display = "''foot''-''strut'' split",
}
generate_non("foot-strut split")
labels["g-dropping"] = {
aliases = {"g dropping"},
Wikipedia = "G-dropping",
display = "''g''-dropping",
}
generate_non("g-dropping")
labels["General American"] = {
aliases = {"GenAm", "GA"},
Wikipedia = "en:General American English",
display = "အမေရိကာန်နာနာသာ်",
}
labels["glottalized"] = {
aliases = {"glottalization", "glottalised", "glottalisation"},
Wikipedia = "Phonological history of English consonant clusters#Glottalization",
}
labels["goose split"] = {
-- Phonemic split in some Southeastern England English variants.
Wikipedia = "English-language vowel changes before historic /l/#Goose_split",
display = "''goose'' split",
}
labels["gulf-golf"] = {
Wikipedia = "English-language vowel changes before historic /l/#Gulf-golf merger",
display = "''gulf''-''golf'' merger",
}
labels["h-dropping"] = {
Wikipedia = "H-dropping",
display = "''h''-dropping",
}
generate_non("h-dropping")
labels["happy-tensing"] = {
aliases = {"happy tensing"},
Wikipedia = "Happy tensing",
display = "''happy''-tensing",
}
generate_non("happy-tensing")
labels["horse-hoarse"] = {
Wikipedia = "horse–hoarse merger",
display = "''horse''–''hoarse'' merger",
}
generate_non("horse-hoarse")
labels["hurry-furry"] = {
Wikipedia = "hurry-furry merger",
display = "''hurry''–''furry'' merger",
}
generate_non("hurry-furry")
labels["Inland Northern US"] = {
aliases = {"Great Lakes", "Inland Northern", "Inland North", "Inland Northern American", "Inland Northern American English", "Inland Northern English", "Northern Cities Vowel Shift", "US Inland North", "northern cities vowel shift"},
Wikipedia = "Inland Northern American English",
display = "Inland Northern American",
}
labels["intrusive r"] = {
Wikipedia = "Intrusive r",
display = "intrusive R",
}
generate_non("intrusive r", "without intrusive R")
labels["laxing"] = {
Wikipedia = "Trisyllabic laxing"
}
generate_non("laxing")
labels["linking w"] = {
Wiktionary = "Appendix:English_pronunciation#Linking_semivowels",
display="linking W"
}
labels["linking y"] = {
Wiktionary = "Appendix:English_pronunciation#Linking_semivowels",
display="linking Y"
}
labels["l-vocalization"] = {
aliases = {"l-vocalisation"},
Wikipedia = "L-vocalization#Modern English",
display = "''l''-vocalization",
}
generate_non("l-vocalization")
labels["Latinate"] = {
Wikipedia = "Latin#Phonology",
}
labels["lot-cloth split"] = {
Wikipedia = true,
display = "''lot''–''cloth'' split",
}
generate_non("lot-cloth split")
labels["Mary-marry-merry"] = {
aliases = {"Mmmm"},
Wikipedia = "Mary–marry–merry merger",
display = "''Mary''–''marry''–''merry'' merger",
}
generate_non("Mary-marry-merry")
table.insert(labels["non-Mary-marry-merry"].aliases, "nMmmm")
labels["merry-Murray"] = {
aliases = {"Merry-Murray"},
Wikipedia = "Merry–Murray merger",
display = "''merry''–''Murray'' merger",
}
labels["mirror-nearer"] = {
aliases = {"Sirius-serious"},
Wikipedia = "Mirror-nearer merger",
display = "''mirror''–''nearer'' merger",
}
generate_non("mirror-nearer")
labels["nt-flapping"] = {
Wikipedia = "Flapping#Distribution",
display = "''nt''-flapping",
}
generate_non("nt-flapping")
labels["pane-pain"] = {
Wikipedia = "Pane–pain merger",
display = "''pane''–''pain'' merger"
}
generate_non("pane-pain")
labels["paw-poor"] = {
Wikipedia = "Rhoticity in English#/ɔː/–/ʊər/ merger",
display = "''paw''–''poor'' merger",
}
labels["pin-pen"] = {
aliases = {"pen-pin"},
Wikipedia = "pin–pen merger",
display = "''pin''–''pen'' merger",
}
labels["pour-poor"] = {
aliases = {"poor-pour", "cure-force"},
Wikipedia = "Cure–force merger",
display = "''pour''–''poor'' merger",
}
generate_non("pour-poor")
labels["r-dissimilation"] = {
Wikipedia = "Dissimilation",
display = "''r''-dissimilation",
}
labels["rhotic"] = {
Wikipedia = "Rhoticity in English",
}
labels["non-rhotic"] = {
aliases = {"nonrhotic"},
Wikipedia = "Rhoticity in English",
}
labels["Received Pronunciation"] = {
aliases = {"RP"},
Wikipedia = "en:Received Pronunciation",
display = "ဗီုပ္တိတ်ရမျာၚ်မဒုၚ်တဲလဝ်",
}
labels["salary-celery"] = {
Wikipedia = "Salary–celery merger",
display = "''salary''–''celery'' merger",
}
labels["show-sure"] = {
Wikipedia = "Show-sure merger",
display = "''show''–''sure'' merger",
}
labels["Standard Southern British English"] = {
aliases = {"SSB", "SSBE", "Standard Southern British"},
Wikipedia = "Standard Southern British",
display = "Standard Southern British",
}
labels["stressed"] = {
Wikipedia = "Stress and vowel reduction in English#Weak and strong forms of function words",
display = "stressed form",
}
labels["tar-tire"] = {
Wikipedia = "/aɪər/–/ɑr/ merger",
display = "tar-tire merger",
}
labels["tar-tire-tower"] = {
Wikipedia = "English-language vowel changes before historic /r/#/aɪə/–/aʊə/–/ɑː/ merger",
display = "tar-tire-tower merger",
}
labels["t-glottalization"] = {
aliases = {"t-glottaling", "t-glottalisation"},
Wikipedia = "T-glottalization",
display = "''t''-glottalization",
}
generate_non("t-glottalization")
labels["th-fronting"] = {
Wikipedia = true,
display = "''th''-fronting",
}
labels["th-stopping"] = {
Wikipedia = true,
display = "''th''-stopping",
}
labels['toe-tow'] = {
Wikipedia = "Phonological history of English diphthongs#Toe–tow merger",
display = "''toe''–''tow'' merger"
}
generate_non("toe-tow")
labels["trap-bath split"] = {
Wikipedia = "trap–bath split",
display = "''trap''–''bath'' split",
}
generate_non("trap-bath split")
labels["triphthong smoothing"] = {
Wikipedia = "Triphthong smoothing",
display = "triphthong smoothing",
}
generate_non("triphthong smoothing")
labels["unstressed"] = {
Wikipedia = "Stress and vowel reduction in English#Weak and strong forms of function words",
display = "unstressed form",
}
labels["weak vowel"] = {
aliases = {"weak vowel merger"},
Wikipedia = "Weak vowel merger",
display = "weak vowel merger",
}
generate_non("weak vowel", "weak vowel distinction")
labels["wine-whine"] = {
Wikipedia = "wine–whine merger",
display = "''wine''–''whine'' merger",
}
generate_non("wine-whine")
labels["yod-coalescence"] = {
aliases = {"yod coalescence"},
Wikipedia = true,
}
generate_non("yod-coalescence")
labels["NG-coalescence"] = {
aliases = {"NG coalescence","ng-coalescence","ng coalescence"},
Wikipedia = true,
}
generate_non("NG-coalescence")
labels["yod-dropping"] = {
aliases = {"yod dropping"},
Wikipedia = true,
}
generate_non("yod-dropping")
labels["æ-raising"] = {
aliases = {"æ-tensing", "/æ/ raising", "/æ/ tensing", "ae-raising", "ae-tensing"},
Wikipedia = "/æ/ raising",
}
generate_non("æ-raising")
labels["dialects of Canada"] = {
Wikipedia = "en:List of dialects of English",
display = "အရေဝ်ဒေသဍုၚ်ခေန်နာဒါ",
}
labels["dialects of the US"] = {
Wikipedia = "en:List of dialects of English",
display = "အရေဝ်ဒေသဍုၚ်အမေရိကာန်",
}
return require("Module:labels").finalize_data(labels)
q2wn0e59ct4gj470axdkq6475o3b94y
မဝ်ဂျူ:labels/data/lang/fr
828
108842
392663
384392
2026-04-13T15:06:09Z
咽頭べさ
33
392663
Scribunto
text/plain
local labels = {}
labels["Acadia"] = {
aliases = {"Acadian", "acd"},
Wikipedia = "Acadian French",
regional_categories = "Acadian",
parent = "Canada",
}
labels["Africa"] = {
aliases = {"African"},
Wikipedia = "African French",
regional_categories = "African",
parent = true,
}
labels["Algeria"] = {
aliases = {"Algerian"},
Wikipedia = {"French language in Algeria", "African French#Algerian French"},
regional_categories = "Algerian",
parent = "Africa",
}
labels["Alsace"] = {
Wikipedia = true,
regional_categories = "Alsatian",
parent = "France",
}
labels["Antilles"] = {
aliases = {"West Indies", "win"},
region = "the {{w|French Antilles}}",
Wikipedia = "French West Indies",
regional_categories = true,
parent = "Caribbean",
}
labels["Aosta"] = {
region = "the [[Aosta Valley]] in northwestern [[Italy]]",
aliases = {"Aostan", "aos"},
Wikipedia = "Aostan French",
regional_categories = "Aostan",
parent = "Europe",
}
-- included because we have many audio files from here
labels["Aquitaine"] = {
Wikipedia = {"Meridional French", true},
regional_categories = "Meridional French",
}
labels["Asia"] = {
aliases = {"Asian"},
Wikipedia = true,
regional_categories = "Asian",
parent = true,
}
labels["Atlantic Canada"] = {
aliases = {"Atlantic Canadian"},
Wikipedia = "French language in Canada#The Maritimes",
regional_categories = "Atlantic Canadian",
parent = "Canada",
}
labels["Belgium"] = {
aliases = {"Belgian", "bel"},
Wikipedia = "Belgian French",
regional_categories = "Belgian",
parent = "Europe",
}
labels["Benin"] = {
Wikipedia = true,
regional_categories = "Beninese",
parent = "West Africa",
}
labels["Brétigny-sur-Orge"] = {
Wikidata = "Q837748",
}
labels["Cajun"] = {
prep = "by",
region = "[[Cajun]]s in [[Louisiana]]",
aliases = {"Cajun French", "caj"},
Wikipedia = "Cajun French",
regional_categories = true,
parent = "Louisiana",
}
labels["Cambodia"] = {
aliases = {"Cambodian French", "Cambodian", "cam"},
Wikipedia = "French language in Cambodia",
regional_categories = "Cambodian",
parent = "Asia",
}
labels["Canada"] = {
aliases = {"Canadian"},
Wikipedia = "en:Canadian French",
display = "ခမ်နာဒါ",
regional_categories = "ခမ်နာဒါ",
parent = "North America",
}
labels["Caribbean"] = {
the = true,
Wikipedia = true,
regional_categories = true,
parent = "North America",
}
labels["Congo"] = {
region = "<country>",
aliases = {"Congolese"},
Wikipedia = {"African French#Kinshasa French", "Languages of the Democratic Republic of the Congo#French"},
regional_categories = "Congolese",
country = "the [[Democratic Republic of the Congo]],the [[Republic of the Congo]]",
parent = "Africa",
}
labels["Corsica"] = {
parent = "France",
display = "[[Corsica]]"
}
-- Currently categorizes the same as "Congo" and "Republic of the Congo".
labels["Democratic Republic of the Congo"] = {
aliases = {"Democratic Republic of Congo", "DR Congo", "Congo-Kinshasa"},
Wikipedia = {"African French#Kinshasa French", "Languages of the Democratic Republic of the Congo#French"},
regional_categories = "Congolese",
}
labels["double verlan"] = {
def = "a double application of verlan, a kind of backslang reordering syllables in a word",
noreg = true,
alises = {"double Verlan", "veul"},
Wikipedia = "Verlan#Double verlan",
plain_categories = true,
parent = "Verlan",
}
labels["Europe"] = {
aliases = {"European", "European French"},
Wikipedia = "European French",
regional_categories = "European",
parent = true,
}
labels["France"] = {
aliases = {"French"},
Wikipedia = "en:French of France",
display = "ဍုၚ်ရးပြၚ်သေတ်",
regional_categories = "ဍုၚ်ရးပြၚ်သေတ်", -- FIXME, rename to "France French",
parent = "Europe",
}
labels["French Guiana"] = {
aliases = {"Guianese", "gui", "French Guyana"},
Wikipedia = true,
regional_categories = "Guianese",
parent = "Caribbean",
}
labels["Frenchville"] = {
Wikipedia = "Frenchville French",
regional_categories = true,
parent = "US",
}
labels["Grenoble"] = {
Wikidata = "Q1289",
}
labels["Guadeloupe"] = {
Wikipedia = true,
regional_categories = true,
parent = "Antilles",
}
labels["Haiti"] = {
Wikipedia = true,
regional_categories = "Haitian",
parent = "Caribbean",
}
labels["Hérault"] = {
Wikidata = "Q12545",
}
labels["Île-de-France"] = {
aliases = {"Île-de-France French"},
Wikipedia = true,
regional_categories = true,
parent = "France",
}
labels["India"] = {
aliases = {"Indian", "Indian French", "ind"},
Wikipedia = "Indian French",
regional_categories = "Indian",
parent = "Asia",
}
labels["Ivory Coast slang"] = {
aliases = {"nouchi", "Nouchi", "noussi", "Noussi", "Ivory Coast French slang", "Côte d’Ivoire slang", "Côte d'Ivoire slang", "Cote d’Ivoire slang", "Cote d'Ivoire slang", "Ivorian slang"},
Wikipedia = "fr:Nouchi",
regional_categories = "Ivorian",
}
labels["Ivory Coast"] = {
the = true,
aliases = {"Ivory Coast French", "Côte d’Ivoire", "Côte d'Ivoire", "Cote d’Ivoire", "Cote d'Ivoire", "Ivorian"},
Wikipedia = "African French#Abidjan French",
regional_categories = "Ivorian",
parent = "West Africa",
}
labels["Jersey Legal"] = {
def = "a form of written [[French]] used in some [[law]]s, [[contract]]s and other documents in [[Jersey]]",
aliases = {"Jersey Legal French", "jer"},
Wikipedia = "Jersey Legal French",
regional_categories = true,
parent = "Europe",
}
labels["Laos"] = {
aliases = {"Lao", "Lao French", "Laotian", "Laotian French", "lao"},
Wikipedia = "French language in Laos",
regional_categories = "Lao",
parent = "Asia",
}
labels["Lorraine"] = {
Wikipedia = true,
regional_categories = true,
parent = "France",
}
labels["Louisiana"] = {
aliases = {"Louisiana French", "LA French", "New Orleans", "lou"},
Wikipedia = "Louisiana French",
regional_categories = true,
parent = "US",
}
labels["Luxembourg"] = {
aliases = {"Luxembourgish", "Luxemburg", "Luxemburgish"},
Wikipedia = true,
regional_categories = "Luxembourgish",
parent = "Europe",
}
labels["Lyon"] = {
Wikipedia = "en:Lyon",
display = "လဳယောန်",
regional_categories = "လဳယောန်",
parent = "France",
}
labels["Mali"] = {
aliases = {"Malian"},
Wikipedia = "Malians in France",
regional_categories = "Malian",
parent = "West Africa",
}
labels["Marseille"] = {
Wikipedia = true,
regional_categories = true,
parent = "France",
}
labels["Martinique"] = {
Wikipedia = true,
regional_categories = true,
parent = "Antilles",
}
labels["Massy"] = {
Wikidata = "Q274249",
}
labels["Meridional"] = {
region = "{{w|Southern France}}, especially [[Marseille]], [[Avignon]] and [[Toulouse]]",
aliases = {"mer", "Occitanie", "Occitania", "Midi", "Southern France"},
Wikipedia = "Meridional French",
regional_categories = true,
parent = "France",
}
labels["Métis"] = {
prep = "by",
region = "the {{w|Métis#Métis people in Canada|Métis people}} in [[Canada]]",
aliases = {"Metis"},
Wikipedia = "Métis French",
regional_categories = true,
parent = "Canada",
}
labels["Missouri"] = {
aliases = {"Missouri French", "Missourian French", "MO French", "Missourian", "St Louis, Missouri", "St. Louis, Missouri", "mis"},
Wikipedia = "Missouri French",
regional_categories = true,
parent = "US",
}
labels["Montreal"] = {
aliases = {"Montréal"},
Wikipedia = true,
regional_categories = true,
parent = "Canada",
}
labels["Morocco"] = {
aliases = {"Moroccan"},
Wikipedia = "French language in Morocco",
regional_categories = "Moroccan",
parent = "Africa",
}
labels["Muskrat"] = {
prep = "by",
region = "the {{w|Muskrat French}} people in southeastern [[Michigan]], northern [[Ohio]] along the shores of [[Lake Erie]], and southwestern [[Ontario]]",
Wikipedia = "Muskrat French",
regional_categories = true,
parent = "US",
}
labels["Nancy"] = {
Wikipedia = "Nancy, France",
regional_categories = true,
parent = "France",
}
labels["New Brunswick"] = {
Wikipedia = {"French language in Canada#The Maritimes", "Brayon"},
regional_categories = true,
parent = "Atlantic Canada",
}
labels["New Caledonia"] = {
aliases = {"New Caledonian", "cal"},
Wikipedia = "Caldoche",
regional_categories = "New Caledonian",
parent = true,
}
labels["New England"] = {
aliases = {"nwe"},
Wikipedia = "New England French",
regional_categories = true,
parent = "US",
}
labels["Newfoundland"] = {
aliases = {"nfl"},
Wikipedia = "Newfoundland French",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Normandy"] = {
Wikipedia = true,
regional_categories = true,
parent = "France",
}
labels["North America"] = {
aliases = {"North American"},
Wikipedia = "American French",
regional_categories = "North American",
parent = true,
}
labels["Northern"] = {
region = "Nord-Pas-de-Calais",
aliases = {"northern"},
Wikipedia = "Nord-Pas-de-Calais",
regional_categories = true,
parent = "France",
}
labels["Nova Scotia"] = {
aliases = {"Nova Scotian"},
Wikipedia = "French language in Canada#The Maritimes",
regional_categories = true,
parent = "Atlantic Canada",
}
labels["Ontario"] = {
Wikipedia = "Ontario French",
regional_categories = true,
parent = "Canada",
}
labels["Paris"] = {
aliases = {"Parisian"},
Wikipedia = "Parisian French",
regional_categories = "Parisian",
parent = "Île-de-France",
}
labels["Picardy"] = {
aliases = {"Picard"},
Wikipedia = true,
regional_categories = "Picard",
parent = "France",
}
labels["Prince Edward Island"] = {
Wikipedia = "French language in Canada#The Maritimes",
regional_categories = true,
parent = "Atlantic Canada",
}
--don't add Provençal as an alias
labels["Provence"] = {
Wikipedia = true,
regional_categories = true,
parent = "France",
}
labels["Quebec"] = {
aliases = {"Québec", "que"},
Wikipedia = "Quebec French",
regional_categories = true,
parent = "Canada",
}
-- Currently categorizes the same as "Congo" and "Democratic Republic of the Congo".
labels["Republic of the Congo"] = {
aliases = {"Republic of Congo", "Congo Republic", "Congo-Brazzaville"},
Wikipedia = {"African French#Kinshasa French", "Languages of the Republic of the Congo"},
regional_categories = "Congolese",
}
labels["Réunion"] = {
prep = "on",
Wikipedia = true,
regional_categories = true,
parent = "Africa",
}
labels["Rwanda"] = {
aliases = {"Rwandan"},
Wikipedia = true,
regional_categories = "Rwandan",
parent = "Africa",
}
labels["Saint-Barthélemy"] = {
aliases = {"St. Barts"},
Wikipedia = "Saint-Barthélemy French",
regional_categories = true,
parent = "Antilles",
}
labels["Saint-Étienne"] = {
Wikidata = "Q42716",
}
labels["Saint-Maurice-de-Beynost"] = {
Wikidata = "Q11981",
}
labels["Shawinigan"] = {
Wikidata = "Q141980",
display = "ဍုၚ်သျှဝနဳဂါန်",
}
labels["Somain"] = {
Wikidata = "Q626382",
display = "သဝ်မေန်",
}
labels["Switzerland"] = {
aliases = {"Swiss", "Swiss French", "swi"},
Wikipedia = "en:Swiss French",
display = "သွေတ်ဇြာလာန်",
regional_categories = "သွေတ်",
parent = "Europe",
}
labels["T-V"] = {
display = "T–V distinction",
Wikipedia = "T–V distinction",
}
-- included because we have many audio files from here
labels["Toulouse"] = {
Wikipedia = {"en:Meridional French", true},
display = "တူလေုတ်",
regional_categories = "မဳရဳဒဳနောန်",
}
labels["Tunisia"] = {
aliases = {"Tunisian"},
Wikipedia = "Languages of Tunisia#French",
regional_categories = "Tunisian",
parent = "Africa",
}
labels["US"] = {
region = "the [[United States]]",
aliases = {"U.S.", "American"},
Wikipedia = "en:United States",
display = "အမေရိကာန်",
regional_categories = "အမေရိကာန်",
parent = "North America",
}
labels["Valais"] = {
Wikipedia = "en:Valais",
display = "ဝလေဝ်သ်",
}
labels["Verlan"] = {
def = "a type of backslang used in [[French]], in which the order of the syllables of words is changed, usually with the last syllable coming first",
noreg = true,
aliases = {"verlan"},
Wikipedia = true,
plain_categories = true,
parent = true,
othercat = "French back slang",
}
labels["Vietnam"] = {
aliases = {"Vietnamese", "vie"},
Wikipedia = "French language in Vietnam",
regional_categories = "Vietnamese",
parent = "Asia",
}
-- included because we have many audio files from here
labels["Vosges"] = {
Wikipedia = "en:Vosges",
display = "ဗောတ်စ်ဂျေတ်စ်",
regional_categories = "ဠောရိန်",
}
labels["West Africa"] = {
aliases = {"West African"},
Wikipedia = true,
regional_categories = "West African",
parent = "Africa",
}
labels["post-1990"] = {
aliases = {"post-1990 spelling"},
display = "[[:en:Appendix:French spelling reforms of 1990|ခ္ဍံက်လိက်ကဆံၚ်သၞာံ ၁၉၉၀]]",
}
labels["pre-1990"] = {
aliases = {"pre-1990 spelling"},
display = "[[:en:Appendix:French spelling reforms of 1990|ခ္ဍံက်လိက်ကၠာနူသၞာံ ၁၉၉၀]]",
}
return require("Module:labels").finalize_data(labels)
spl3c7emqkbz8tredhfs7cdv1ioxyzc
မဝ်ဂျူ:attention
828
118146
392695
152569
2026-04-14T08:57:53Z
咽頭べさ
33
392695
Scribunto
text/plain
local export = {}
local format_categories = require("Module:utilities").format_categories
local html_create = mw.html.create
local insert = table.insert
local process_params = require("Module:parameters").process
function export.show(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, type = "language"},
[2] = true,
["id"] = true,
["sort"] = true,
})
local lang = args[1]
local lang_code = lang:getCode()
local title = args[2]
local id = args["id"] or ""
-- local categories = {"Requests for attention concerning " .. lang:getCanonicalName()}
if not title then
-- insert(categories, {cat = "attention lacking explanation", sort_key = "-"})
end
-- mw.html escapes special characters in the id and title attributes.
local ret = html_create("span")
:addClass("attentionseeking")
:attr("data-lang", lang_code)
if id ~= "" then
ret = ret:attr("id", "attentionseeking" .. lang_code .. id)
end
if title then
ret = ret:attr("title", title)
end
return tostring(ret) .. format_categories(categories, lang, args.sort)
end
return export
bz4n7krfjcxscu3y36j1e5wa6bj9ift
392697
392695
2026-04-14T09:00:55Z
咽頭べさ
33
392697
Scribunto
text/plain
local export = {}
local format_categories = require("Module:utilities").format_categories
local html_create = mw.html.create
local insert = table.insert
local process_params = require("Module:parameters").process
function export.show(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, type = "language"},
[2] = true,
["id"] = true,
["sort"] = true,
})
local lang = args[1]
local lang_code = lang:getCode()
local title = args[2]
local id = args["id"] or ""
-- local categories = {"Requests for attention concerning " .. lang:getCanonicalName()}
if not title then
insert(categories, {cat = "attention lacking explanation", sort_key = "-"})
end
-- mw.html escapes special characters in the id and title attributes.
local ret = html_create("span")
:addClass("attentionseeking")
:attr("data-lang", lang_code)
if id ~= "" then
ret = ret:attr("id", "attentionseeking" .. lang_code .. id)
end
if title then
ret = ret:attr("title", title)
end
return tostring(ret) .. format_categories(categories, lang, args.sort)
end
return export
opaup24q5irr7fqdg301n7khrnbb6nk
392698
392697
2026-04-14T09:02:33Z
咽頭べさ
33
392698
Scribunto
text/plain
local export = {}
local format_categories = require("Module:utilities").format_categories
local html_create = mw.html.create
local insert = table.insert
local process_params = require("Module:parameters").process
function export.show(frame)
local args = process_params(frame:getParent().args, {
[1] = {required = true, type = "language"},
[2] = true,
["id"] = true,
["sort"] = true,
})
local lang = args[1]
local lang_code = lang:getCode()
local title = args[2]
local id = args["id"] or ""
local categories = {"Requests for attention concerning " .. lang:getCanonicalName()}
if not title then
insert(categories, {cat = "attention lacking explanation", sort_key = "-"})
end
-- mw.html escapes special characters in the id and title attributes.
local ret = html_create("span")
:addClass("attentionseeking")
:attr("data-lang", lang_code)
if id ~= "" then
ret = ret:attr("id", "attentionseeking" .. lang_code .. id)
end
if title then
ret = ret:attr("title", title)
end
return tostring(ret) .. format_categories(categories, lang, args.sort)
end
return export
q3y41ve83j8zdz4ho0m280bteqe8ugg
黔
0
154752
392675
218275
2026-04-13T23:51:54Z
Apisite
133
392675
wikitext
text/x-wiki
{{character info}}
==မအရေဝ်ပံၚ်ကောံ==
==အက္ခရ်ကြုက်==
{{Han char|rn=203|rad=黑|as=04|sn=16|four=68327|canj=WFOIN|ids=⿰黑今}}
===နိဿဲ===
* {{Han ref|kx=1519.040|dkj=48056|dj=2052.170|hdz=74744.190|uh=9ED4|ud=40660|bh=C072|bd=49266}}
hlaplqso50yjw6yexdvb2xbt252e3vc
မဝ်ဂျူ:xkz-IPA
828
212972
392689
292771
2026-04-14T08:47:24Z
咽頭べさ
33
392689
Scribunto
text/plain
local find = mw.ustring.find
local rsub = mw.ustring.gsub
local m_a = require("Module:accent qualifier")
local u = require("Module:string/char")
local export = {}
local m_IPA = require("Module:IPA")
local lang = require("Module:languages").getByCode("xkz")
local function format_accent(qual)
return m_a.format_qualifiers(lang, {qual})
end
local function phonetic(text, col)
text = rsub(text, "thr", "trh")
text = rsub(text, "â", "aː")
text = rsub(text, "ê", "eː")
text = rsub(text, "î", "iː")
text = rsub(text, "ô", "oː")
text = rsub(text, "û", "uː")
text = rsub(text, "^", "H")
text = rsub(text, " ", " H")
text = rsub(text, "H'([bpdtgkmnrlczswyh]+)([aeiouöü])", "%1'%2")
text = rsub(text, "H(t?[ptcksh]r?[sh]?[rylw]?)([aeiouöü])", "%1'%2")
text = rsub(text, "H([bdjgz][zhr]?[rylw]?)([aeiouöü])", "%1!%2")
text = rsub(text, "Hlh([aeiou])", "lh'%1")
text = rsub(text, "H([mnrlyw][ygr]?)([áéíóúöü])", "%1'%2")
text = rsub(text, "H([mnrlyw][ygr]?)([aeiouöü])", "%1!%2")
text = rsub(text, "H([aeiouöü])", "!%1")
text = rsub(text, "([ai])u", "%1u̯")
text = rsub(text, "([auo])i", "%1i̯")
text = rsub(text, "%!([aeiouöü])", "%1G")
text = rsub(text, "%'([aeiouöü])", "%1A")
text = rsub(text, "a", "ɐ")
text = rsub(text, "ng", "ŋ")
text = rsub(text, "lh", "l̥")
text = rsub(text, "ny", "ɲ")
text = rsub(text, "tr", "ʈ")
text = rsub(text, "dr", "ɖ")
text = rsub(text, "j", "ɟ")
text = rsub(text, "y", "j")
text = rsub(text, "([ptʈck]s?)h", "%1ʰ")
text = rsub(text, "[sz]h", "ç")
text = rsub(text, "c", "c͡ɕ")
text = rsub(text, "ɟ", "ɟ͡ʑ")
text = rsub(text, "ts", "t͡s")
text = rsub(text, "ʈ", "ʈ(r)")
text = rsub(text, "ɖ", "ɖ(r)")
text = rsub(text, "pj", "(p)c")
text = rsub(text, "mj([ɐeiouöü])", "(m)ɲ%1")
text = rsub(text, "b%.", "p.")
text = rsub(text, "b ", "p ")
text = rsub(text, "b$", "p$")
text = rsub(text, "d%.", "t.")
text = rsub(text, "d ", "t ")
text = rsub(text, "d$", "t$")
text = rsub(text, "g%.", "k.")
text = rsub(text, "g ", "k ")
text = rsub(text, "g$", "k$")
text = rsub(text, "g", "ɡ")
text = rsub(text, "t", "t̪")
text = rsub(text, "d", "d̪")
text = rsub(text, "%(r%)ʰ", "ʰ(r)")
text = rsub(text, "H", "")
if col == 1 then
text = rsub(text, "ü", "u")
text = rsub(text, "ö", "o")
elseif col == 2 then
text = rsub(text, "ü([AG]?)", "u%1i̯")
text = rsub(text, "ö([AG]?)", "o%1i̯")
end
text = rsub(text, "ü([AG]?)", "y%1ː")
text = rsub(text, "ö([AG]?)", "ø%1ː")
text = rsub(text, " $", "")
text = rsub(text, "^ ", "")
text = rsub(text, "G", "̀")
text = rsub(text, "A", "́")
text = rsub(text, "^([ɐeiouøy])", "ʔ%1")
text = rsub(text, " ([ɐeiouøy])", "ʔ%1")
return text
end
function export.IPA(frame)
local words = {}
for _, word in ipairs(frame:getParent().args) do
word = rsub(word, "་", ".")
word = require("Module:Tibt-translit").tr(word, "xkz", 'Tibt')
table.insert(words, word)
local test = word
word = rsub(word, "k ", "ː ")
word = rsub(word, "k$", "ː")
word = rsub(word, "s ", "ː ")
word = rsub(word, "s$", "ː")
word = rsub(word, "nː", "ng")
if word ~= test then
table.insert(words, word)
end
end
if #words == 0 then
word = rsub(mw.loadData("Module:headword/data").pagename, "་", ".")
word = require("Module:Tibt-translit").tr(word, "xkz", 'Tibt')
table.insert(words, word)
local test = word
word = rsub(word, "k ", "ː ")
word = rsub(word, "k$", "ː")
word = rsub(word, "s ", "ː ")
word = rsub(word, "s$", "ː")
word = rsub(word, "nː", "ng")
if word ~= test then
table.insert(words, word)
end
end
local IPA_results = {}
local IPA_col = {}
local IPA_edu = {}
for _, word in ipairs(words) do
if mw.ustring.match(word, "ü") or mw.ustring.match(word, "ö") then
table.insert(IPA_col, { pron = "[" .. phonetic(word, 1) .. "]" })
table.insert(IPA_edu, { pron = "[" .. phonetic(word, 2) .. "]" })
table.insert(IPA_edu, { pron = "[" .. phonetic(word, 3) .. "]" })
else
table.insert(IPA_results, { pron = "[" .. phonetic(word, 3) .. "]" })
end
end
if #IPA_col == 0 and #IPA_edu == 0 then
return m_IPA.format_IPA_full { lang = lang, items = IPA_results }
else
return "*" .. format_accent("colloquial") .. " " .. m_IPA.format_IPA_full { lang = lang, items = IPA_col } .. "\n*" ..
format_accent("educated") .. " " .. m_IPA.format_IPA_full { lang = lang, items = IPA_edu }
end
end
return export
tnxfic6xvyuzpiasxsqvzsjx2w03zpx
monishes
0
292810
392608
2026-04-13T12:02:00Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monish||s-verb-form}}"
392608
wikitext
text/x-wiki
=={{=en=}}==
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monish||s-verb-form}}
18uu0pniccfgsy05ryzauz973ebhyja
monishing
0
292811
392609
2026-04-13T12:02:32Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monish||ing-form}}"
392609
wikitext
text/x-wiki
=={{=en=}}==
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monish||ing-form}}
bb39y5anavb9ewapsv2y4c983v342ur
monished
0
292812
392610
2026-04-13T12:03:06Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monish||ed-form}}"
392610
wikitext
text/x-wiki
=={{=en=}}==
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monish||ed-form}}
3tq6s6kseefzacy692uk22b4m19cvb4
monitor
0
292813
392611
2026-04-13T12:32:59Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|Monitor|monitör}} =={{=en=}}== [[File:Monitor Lizard.jpg|right|thumb|A '''monitor''' lizard]] [[Image:Monitor LG.jpg|right|thumb|A CRT computer '''monitor''']] [[File:HMSMarshalNeyUnderwayPortsideView1915.jpg|right|thumb|HMS ''Marshal Ney'', a '''monitor''' (warship)]] [[File:Co monitor.JPG|right|thumb|A blood oxygen saturation '''monitor''']] ===ပွံၚ်နဲတၞဟ်=== * {{l|en|monitour}} {{qual..."
392611
wikitext
text/x-wiki
{{also|Monitor|monitör}}
=={{=en=}}==
[[File:Monitor Lizard.jpg|right|thumb|A '''monitor''' lizard]]
[[Image:Monitor LG.jpg|right|thumb|A CRT computer '''monitor''']]
[[File:HMSMarshalNeyUnderwayPortsideView1915.jpg|right|thumb|HMS ''Marshal Ney'', a '''monitor''' (warship)]]
[[File:Co monitor.JPG|right|thumb|A blood oxygen saturation '''monitor''']]
===ပွံၚ်နဲတၞဟ်===
* {{l|en|monitour}} {{qualifier|obsolete}}
===နိရုတ်===
{{root|en|ine-pro|*men-|id=think}}
ဝေါဟာကၠုၚ်နူ {{uder|en|la|monitor}}
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|en|/ˈmɒn.ɪ.tə/|a=RP}}
** {{audio|en|LL-Q1860 (eng)-Vealhurl-monitor.wav|a=Southern England}}
* {{IPA|en|/ˈmɑ.nɪ.tɚ/|[ˈmɑ.nɪ.ɾɚ]|/ˈmɑ.nə.tɚ/|[ˈmɑ.nə.ɾɚ]|a=cot-caught,GA,dialects of Canada}}
** {{audio|en|LL-Q1860 (eng)-Wodencafe-monitor.wav|a=Texas}}
* {{IPA|en|/ˈmɒn.ɪ.tɚ/|[ˈmɒn.ɪ.ɾɚ]|a=cot-caught,CA,dialects of the US}}
* {{IPA|en|/ˈmɔn.ɪ.tə/|[ˈmɔn.ɪ.ɾə]|a=AU}}
* {{IPA|en|/ˈmɒn.ə.tə/|[ˈmɔ̟n.ə.ɾə]|a=NZ}}
===နာမ်===
{{en-noun}}
# မဝ်နဳတာ။
# ကွးဘာအ္စာမကဵုလဝ်တာလျိုၚ်ပ္ဍဲတန်။
# မၞိဟ်သ္ဒးပလံၚ်ပရိုၚ်,ရပ်ကေတ်ပရိုၚ် နူကဵုဍုၚ်သအာၚ်ဗလးလဝ်ပရိုၚ်တံဂှ်။
===မဒုၚ်လွဳစ===
* {{desc|th|มอนิเตอร์|bor=1}}
===ကြိယာ===
{{en-verb}}
# ရပ်ကေတ်ရမျှာၚ်။
# သကဵုရံၚ်စံၚ်၊ သကဵုမၚ်မွဲ။
===ဝေါဟာလွာ===
* {{anagrams|en|a=imnoort|montoir|tromino}}
==လပ်တေန်==
===ဗွဟ်ရမ္သာၚ်===
* {{la-IPA|monitor}}
===နာမ်===
{{la-noun|monitor<3>}}
# ညးမကဵုကသပ်၊ အ္စာဥပ္ပဇ္ဇာဲ။
# ညးမဆဝ်ပ္ၚုဟ်၊ ညးမကဵုသတိ။
===မဒုၚ်လွဳစ===
* {{desc|ca|monitor}}
* {{desc|en|monitor}}
* {{desc|de|Monitor}}
* {{desc|it|monitore}}
* {{desc|pt|monitor}}
* {{desc|ru|монито́р}}
* {{desc|es|monitor}}
7ngsycftv2si7qjrg2bz9cfp7dbsdol
monitors
0
292814
392614
2026-04-13T13:02:22Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|Monitors}} =={{=en=}}== ===နာမ်=== {{head|en|noun form}} # {{plural of|en|monitor}} ===နာမ် ၂=== {{en-noun|p}} # စက်ကလၚ်က္တောဝ်မဝ်နဳတာမစုတ်ပ္ဍဲက္တောဝ်။ ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monitor||s-verb-form}} ===ဝေါဟာလွာ=== * {{anagrams|en|a=imnoorst|Ormiston|ion storm|mo..."
392614
wikitext
text/x-wiki
{{also|Monitors}}
=={{=en=}}==
===နာမ်===
{{head|en|noun form}}
# {{plural of|en|monitor}}
===နာမ် ၂===
{{en-noun|p}}
# စက်ကလၚ်က္တောဝ်မဝ်နဳတာမစုတ်ပ္ဍဲက္တောဝ်။
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monitor||s-verb-form}}
===ဝေါဟာလွာ===
* {{anagrams|en|a=imnoorst|Ormiston|ion storm|montoirs|trominos}}
2scd2iuqmo5crmndre99mr2aw8vnehj
Monitors
0
292815
392615
2026-04-13T13:04:12Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitors}} =={{=de=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{audio|de|De-Monitors.ogg|a=<<Germany>> (<<Berlin>>)}} ===နာမ်=== {{head|de|noun form}} # {{inflection of|de|Monitor||gen|s}}"
392615
wikitext
text/x-wiki
{{also|monitors}}
=={{=de=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{audio|de|De-Monitors.ogg|a=<<Germany>> (<<Berlin>>)}}
===နာမ်===
{{head|de|noun form}}
# {{inflection of|de|Monitor||gen|s}}
gklrb6xdlb7v2sxg1h0d4jine0vd1z7
Monitor
0
292816
392616
2026-04-13T13:10:16Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitor}} =={{=en=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{hyphenation|en|Mo|ni|tor}} ===နာမ်မကိတ်ညဳ=== {{en-proper noun}} # မဝ်နဳတာ။ =={{=de=}}== ===နိရုတ်=== {{bor+|de|en|monitor}} ===ဗွဟ်ရမ္သာၚ်=== * {{IPA|de|[ˈmoːnitoːɐ̯]}} * {{audio|de|De-Monitor.ogg|a=<<Germany>> (<<Berlin>>)}} ===နာမ်=== {{de-noun|m,,en:e}..."
392616
wikitext
text/x-wiki
{{also|monitor}}
=={{=en=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{hyphenation|en|Mo|ni|tor}}
===နာမ်မကိတ်ညဳ===
{{en-proper noun}}
# မဝ်နဳတာ။
=={{=de=}}==
===နိရုတ်===
{{bor+|de|en|monitor}}
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|de|[ˈmoːnitoːɐ̯]}}
* {{audio|de|De-Monitor.ogg|a=<<Germany>> (<<Berlin>>)}}
===နာမ်===
{{de-noun|m,,en:e}}
# ပရေၚ်မမၚ်မွဲ။
#: {{syn|de|Bildschirm}}
888z4zggxejjl50cauj9cwg4va1ayqx
392621
392616
2026-04-13T13:31:51Z
咽頭べさ
33
392621
wikitext
text/x-wiki
{{also|monitor}}
=={{=en=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{hyphenation|en|Mo|ni|tor}}
===နာမ်မကိတ်ညဳ===
{{en-proper noun}}
# မဝ်နဳတာ။
=={{=de=}}==
===နိရုတ်===
{{bor+|de|en|monitor}}
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|de|[ˈmoːnitoːɐ̯]}}
* {{audio|de|De-Monitor.ogg|a=<<Germany>> (<<Berlin>>)}}
===နာမ်===
{{de-noun|m,,en:e}}
# ပရေၚ်မမၚ်မွဲ။
#: {{syn|de|Bildschirm}}
avwwgnmny9f7wdjl22epidx3egzag27
Monitoren
0
292817
392619
2026-04-13T13:26:24Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoren}} =={{=de=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{audio|de|De-Monitoren.ogg|a=<<Germany>> (<<Berlin>>)}} ===နာမ်=== {{head|de|noun form|g=m}} # {{plural of|de|Monitor}}"
392619
wikitext
text/x-wiki
{{also|monitoren}}
=={{=de=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{audio|de|De-Monitoren.ogg|a=<<Germany>> (<<Berlin>>)}}
===နာမ်===
{{head|de|noun form|g=m}}
# {{plural of|de|Monitor}}
ja8xtqnlynzg419xq70yt62wlo3xgha
monitoren
0
292818
392620
2026-04-13T13:30:52Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|Monitoren}} ==ဒါတ်== ===ဗွဟ်ရမ္သာၚ်=== * {{audio|nl|Nl-monitoren.ogg}} ===ကြိယာ=== {{nl-verb}} # သကဵုရပ်ကေတ်ရမျာၚ်။"
392620
wikitext
text/x-wiki
{{also|Monitoren}}
==ဒါတ်==
===ဗွဟ်ရမ္သာၚ်===
* {{audio|nl|Nl-monitoren.ogg}}
===ကြိယာ===
{{nl-verb}}
# သကဵုရပ်ကေတ်ရမျာၚ်။
ko9y5em3xw4uixso41yxs8vfmm5s81z
Monitore
0
292819
392629
2026-04-13T14:02:59Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitore|monitoré}} =={{=de=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{audio|de|De-Monitore.ogg|a=<<Germany>> (<<Berlin>>)}} ===နာမ်=== {{head|de|noun form}} # {{inflection of|de|Monitor||nom//acc//gen|p}}"
392629
wikitext
text/x-wiki
{{also|monitore|monitoré}}
=={{=de=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{audio|de|De-Monitore.ogg|a=<<Germany>> (<<Berlin>>)}}
===နာမ်===
{{head|de|noun form}}
# {{inflection of|de|Monitor||nom//acc//gen|p}}
qhyjsbvavf0r76bugnbyoptuel0ix8t
monitoré
0
292820
392630
2026-04-13T14:03:57Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitore|Monitore}} =={{=fr=}}== ===ကြိယာ=== {{fr-past participle}} # {{past participle of|fr|monitorer}}"
392630
wikitext
text/x-wiki
{{also|monitore|Monitore}}
=={{=fr=}}==
===ကြိယာ===
{{fr-past participle}}
# {{past participle of|fr|monitorer}}
qp59whryl00s44ij1xol0fwvlgdckbg
monitorée
0
292821
392631
2026-04-13T14:04:47Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoree|monitoreé}} =={{=fr=}}== ===ကြိယာ=== {{head|fr|past participle form|g=f-s}} # {{feminine singular of|fr|monitoré}}"
392631
wikitext
text/x-wiki
{{also|monitoree|monitoreé}}
=={{=fr=}}==
===ကြိယာ===
{{head|fr|past participle form|g=f-s}}
# {{feminine singular of|fr|monitoré}}
3p2ajbd1fmhj0qn67upvrwourmhl9x6
monitoreé
0
292822
392632
2026-04-13T14:06:28Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoree|monitorée}} =={{=es=}}== ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392632
wikitext
text/x-wiki
{{also|monitoree|monitorée}}
=={{=es=}}==
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
i7d085rrtu3nhuuycy51j1phqjfmyl4
monitorear
0
292823
392633
2026-04-13T14:07:56Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===ကြိယာ=== {{es-verb}} # သကဵုရပ်ကေတ်ရမျာၚ်။ #: {{syn|es|monitorizar}}"
392633
wikitext
text/x-wiki
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===ကြိယာ===
{{es-verb}}
# သကဵုရပ်ကေတ်ရမျာၚ်။
#: {{syn|es|monitorizar}}
csphbd4hagv9n1r2qkkkkdamxl9rud6
monitoreo
0
292824
392634
2026-04-13T14:10:49Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoreó}} =={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===နာမ်=== {{es-noun|m}} # ပရေၚ်ရပ်ကေတ်ရမျာၚ်။ ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392634
wikitext
text/x-wiki
{{also|monitoreó}}
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===နာမ်===
{{es-noun|m}}
# ပရေၚ်ရပ်ကေတ်ရမျာၚ်။
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
4yrok1xggn389p17gscj83b6q49hj4u
monitoreos
0
292825
392635
2026-04-13T14:11:37Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===နာမ်=== {{head|es|noun form}} # {{plural of|es|monitoreo}}"
392635
wikitext
text/x-wiki
=={{=es=}}==
===နာမ်===
{{head|es|noun form}}
# {{plural of|es|monitoreo}}
hq13qcesy5cn2t7d91rm54z1q6jy3zc
monitoreó
0
292826
392636
2026-04-13T14:12:26Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoreo}} =={{=es=}}== ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392636
wikitext
text/x-wiki
{{also|monitoreo}}
=={{=es=}}==
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
tcykpmnykcw88eph0lue8sdjli9vtgv
monitoreado
0
292827
392637
2026-04-13T14:13:56Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===ကြိယာ=== {{es-past participle}} # {{past participle of|es|monitorear}}"
392637
wikitext
text/x-wiki
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===ကြိယာ===
{{es-past participle}}
# {{past participle of|es|monitorear}}
hzpzsw9pnn49atfbnlchydyi162qc2w
ကဏ္ဍ:ဝေါဟာသပုၚ်ဝဏ္ဏ ၆ မ-ဂမၠိုၚ်
14
292828
392638
2026-04-13T14:18:02Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ကာရန်:သပုၚ်/ado]]"
392638
wikitext
text/x-wiki
[[ကဏ္ဍ:ကာရန်:သပုၚ်/ado]]
ef6iip3k1z5wqtmdrl1g2ipcqrtsy6h
monitoreada
0
292829
392639
2026-04-13T14:19:09Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===ကြိယာ=== {{head|es|past participle form|g=f-s}} # {{feminine singular of|es|monitoreado}}"
392639
wikitext
text/x-wiki
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===ကြိယာ===
{{head|es|past participle form|g=f-s}}
# {{feminine singular of|es|monitoreado}}
jytd062hodginu7jbolo758q6omotwl
monitoreados
0
292830
392640
2026-04-13T14:19:49Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===ကြိယာ=== {{head|es|past participle form|g=m-p}} # {{masculine plural of|es|monitoreado}}"
392640
wikitext
text/x-wiki
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===ကြိယာ===
{{head|es|past participle form|g=m-p}}
# {{masculine plural of|es|monitoreado}}
4nqbq81ly65suwvqli78283hprm67vf
monitoreadas
0
292831
392641
2026-04-13T14:20:39Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=es=}}== ===ဗွဟ်ရမ္သာၚ်=== {{es-pr}} ===ကြိယာ=== {{head|es|past participle form|g=m-p}} # {{masculine plural of|es|monitoreado}}"
392641
wikitext
text/x-wiki
=={{=es=}}==
===ဗွဟ်ရမ္သာၚ်===
{{es-pr}}
===ကြိယာ===
{{head|es|past participle form|g=m-p}}
# {{masculine plural of|es|monitoreado}}
4nqbq81ly65suwvqli78283hprm67vf
monitoree
0
292832
392642
2026-04-13T14:21:43Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoreé|monitorée}} =={{=es=}}== ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392642
wikitext
text/x-wiki
{{also|monitoreé|monitorée}}
=={{=es=}}==
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
0yvi31etgrzn8y6ldxyblmyufiwtmel
monitorés
0
292833
392643
2026-04-13T14:26:25Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitores}} =={{=fr=}}== ===ကြိယာ=== {{head|fr|past participle form|g=m-p}} # {{masculine plural of|fr|monitoré}}"
392643
wikitext
text/x-wiki
{{also|monitores}}
=={{=fr=}}==
===ကြိယာ===
{{head|fr|past participle form|g=m-p}}
# {{masculine plural of|fr|monitoré}}
58jn9eox1j5g87p5tyypfyypzbj7trm
monitores
0
292834
392644
2026-04-13T14:27:38Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitorés}} =={{=fr=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{homophones|fr|monitore|monitorent}} ===ကြိယာ=== {{head|fr|verb form}} # {{inflection of|fr|monitorer||2|s|pres|ind//sub}}"
392644
wikitext
text/x-wiki
{{also|monitorés}}
=={{=fr=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{homophones|fr|monitore|monitorent}}
===ကြိယာ===
{{head|fr|verb form}}
# {{inflection of|fr|monitorer||2|s|pres|ind//sub}}
aeyrxsgoshwbyanuegmpxqu8gpx7x1d
monitorer
0
292835
392645
2026-04-13T14:31:37Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===နာမ်=== {{en-noun}} # ညးမမၚ်မွဲအရာမွဲမွဲသာ်ဂမၠိုၚ်။ #: {{synonyms|en|monitor}} =={{=fr=}}== ===နိရုတ်=== ဝေါဟာကၠုၚ်နူ {{uder|fr|en|-}} ''နကဵု'' {{m|en|monitor}} ===ဗွဟ်ရမ္သာၚ်=== * {{fr-IPA}} * {{audio|fr|LL-Q150 (fra)-Lyokoï-auto-monitorer.wav}} * {{audio|fr|LL-Q150..."
392645
wikitext
text/x-wiki
=={{=en=}}==
===နာမ်===
{{en-noun}}
# ညးမမၚ်မွဲအရာမွဲမွဲသာ်ဂမၠိုၚ်။
#: {{synonyms|en|monitor}}
=={{=fr=}}==
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{uder|fr|en|-}} ''နကဵု'' {{m|en|monitor}}
===ဗွဟ်ရမ္သာၚ်===
* {{fr-IPA}}
* {{audio|fr|LL-Q150 (fra)-Lyokoï-auto-monitorer.wav}}
* {{audio|fr|LL-Q150 (fra)-Lyokoï-monitorer.wav|a=<<France>> (<<Lyon>>)}}
* {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-monitorer.wav|a=<<France>> (<<Somain>>)}}
===ကြိယာ===
{{fr-verb}}
# သကဵုရပ်ကေတ်ရမျာၚ်။
#: {{syn|fr|contrôler|surveiller}}
b6lho870az35yyz2n8wclqap5v6o5py
monitorers
0
292836
392646
2026-04-13T14:32:19Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===နာမ်=== {{head|en|noun form}} # {{plural of|en|monitorer}}"
392646
wikitext
text/x-wiki
=={{=en=}}==
===နာမ်===
{{head|en|noun form}}
# {{plural of|en|monitorer}}
qndyri4xuh0v0b5ndfhhojy0rjb9ndg
monitorées
0
292837
392647
2026-04-13T14:33:37Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitorees|monitoreés}} =={{=fr=}}== ===ကြိယာ=== {{head|fr|past participle form|g=f-p}} # {{feminine plural of|fr|monitoré}}"
392647
wikitext
text/x-wiki
{{also|monitorees|monitoreés}}
=={{=fr=}}==
===ကြိယာ===
{{head|fr|past participle form|g=f-p}}
# {{feminine plural of|fr|monitoré}}
9y2ubt5qum03okwhpce1faufonkcaf8
monitoreés
0
292838
392648
2026-04-13T14:34:23Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitorees|monitorées}} =={{=es=}}== ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392648
wikitext
text/x-wiki
{{also|monitorees|monitorées}}
=={{=es=}}==
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
fah6gwhbsnih3lbz0x20kmm9gzhe0dr
monitorees
0
292839
392649
2026-04-13T14:35:11Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monitoreés|monitorées}} =={{=es=}}== ===ကြိယာ=== {{head|es|verb form}} # {{es-verb form of|monitorear}}"
392649
wikitext
text/x-wiki
{{also|monitoreés|monitorées}}
=={{=es=}}==
===ကြိယာ===
{{head|es|verb form}}
# {{es-verb form of|monitorear}}
nyr0q1oiogmdg4fmqdveubxvu1hync7
monitore
0
292840
392650
2026-04-13T14:39:51Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|Monitore|monitoré}} ==ဗက်ခ်== ===နိရုတ်=== {{bor+|eu|es|monitor}} ===ဗွဟ်ရမ္သာၚ်=== {{eu-pr}} ===နာမ်=== {{eu-noun|both}} # ပရေၚ်မမၚ်မွဲ (ကပေါတ်ကရိယာ)။ # ညးမစၞောန်ထ္ၜး၊ ညးမဗ္တောန်ထ္ၜးကဵု။"
392650
wikitext
text/x-wiki
{{also|Monitore|monitoré}}
==ဗက်ခ်==
===နိရုတ်===
{{bor+|eu|es|monitor}}
===ဗွဟ်ရမ္သာၚ်===
{{eu-pr}}
===နာမ်===
{{eu-noun|both}}
# ပရေၚ်မမၚ်မွဲ (ကပေါတ်ကရိယာ)။
# ညးမစၞောန်ထ္ၜး၊ ညးမဗ္တောန်ထ္ၜးကဵု။
n1j9sqm2ayqldupy84uz78d06ltcfso
ကဏ္ဍ:ကာရန်:ဗက်ခ်/e
14
292841
392651
2026-04-13T14:40:53Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "စရၚ်မဆေၚ်စပ်ကဵုဝေါဟာ[[:ကဏ္ဍ:ဘာသာဗက်ခ်|ဗက်ခ်]]မနွံကာရန် e ဂမၠိုၚ်။ [[ကဏ္ဍ:ကာရန်:ဗက်ခ်|e]]"
392651
wikitext
text/x-wiki
စရၚ်မဆေၚ်စပ်ကဵုဝေါဟာ[[:ကဏ္ဍ:ဘာသာဗက်ခ်|ဗက်ခ်]]မနွံကာရန် e ဂမၠိုၚ်။
[[ကဏ္ဍ:ကာရန်:ဗက်ခ်|e]]
9o67on1pkokleigfojsv22xf9dxjbhh
ကဏ္ဍ:ကာရန်:ဗက်ခ်/oɾe
14
292842
392652
2026-04-13T14:42:00Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "စရၚ်မဆေၚ်စပ်ကဵုဝေါဟာ[[:ကဏ္ဍ:ဘာသာဗက်ခ်|ဗက်ခ်]]မနွံကာရန် oɾe ဂမၠိုၚ်။ [[ကဏ္ဍ:ကာရန်:ဗက်ခ်|oɾe]]"
392652
wikitext
text/x-wiki
စရၚ်မဆေၚ်စပ်ကဵုဝေါဟာ[[:ကဏ္ဍ:ဘာသာဗက်ခ်|ဗက်ခ်]]မနွံကာရန် oɾe ဂမၠိုၚ်။
[[ကဏ္ဍ:ကာရန်:ဗက်ခ်|oɾe]]
4t7t7cf3eyqupytnvxua8axixqioqie
monitoring
0
292843
392653
2026-04-13T14:45:38Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|Monitoring}} =={{=en=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{IPA|en|/ˈmɑnɪtɚɪŋ/|a=GA,CA}} * {{audio|en|LL-Q1860 (eng)-Vealhurl-monitoring.wav|a=Southern England}} ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monitor||ing-form}} ===နာမ်=== {{en-noun|-|s}} # ဒဒှ်မရပ်ကေတ်ရမျှာၚ်နူကဵုရုၚ်ဗလးရမျှာၚ်..."
392653
wikitext
text/x-wiki
{{also|Monitoring}}
=={{=en=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|en|/ˈmɑnɪtɚɪŋ/|a=GA,CA}}
* {{audio|en|LL-Q1860 (eng)-Vealhurl-monitoring.wav|a=Southern England}}
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monitor||ing-form}}
===နာမ်===
{{en-noun|-|s}}
# ဒဒှ်မရပ်ကေတ်ရမျှာၚ်နူကဵုရုၚ်ဗလးရမျှာၚ်ဍုၚ်သအာၚ်။
p5ojjy784khfar6othl22e3a1ffig12
monitorings
0
292844
392654
2026-04-13T14:46:22Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===နာမ်=== {{head|en|noun form}} # {{plural of|en|monitoring}}"
392654
wikitext
text/x-wiki
=={{=en=}}==
===နာမ်===
{{head|en|noun form}}
# {{plural of|en|monitoring}}
0t12xsm6r2x5dfm5bbkhhl9qgkdpcsq
monitored
0
292845
392655
2026-04-13T14:47:27Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===ကြိယာ=== {{head|en|verb form}} # {{infl of|en|monitor||ed-form}}"
392655
wikitext
text/x-wiki
=={{=en=}}==
===ကြိယာ===
{{head|en|verb form}}
# {{infl of|en|monitor||ed-form}}
tu4i9y90kenlkw6yzlum7gv9ec2iqxq
monitoris
0
292846
392656
2026-04-13T14:48:30Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==လပ်တေန်== ===နာမ်=== {{head|la|noun form|head=monitōris}} # {{inflection of|la|monitor||gen|s}}"
392656
wikitext
text/x-wiki
==လပ်တေန်==
===နာမ်===
{{head|la|noun form|head=monitōris}}
# {{inflection of|la|monitor||gen|s}}
9z47ot9oajhglo8poee2bw0xidyyzbd
monitour
0
292847
392657
2026-04-13T14:49:36Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===နာမ်=== {{en-noun}} # {{obsolete form of|en|monitor}}"
392657
wikitext
text/x-wiki
=={{=en=}}==
===နာမ်===
{{en-noun}}
# {{obsolete form of|en|monitor}}
2004rilim2lbrpoxjlvgv6f98m6tr46
monitours
0
292848
392658
2026-04-13T14:50:01Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=en=}}== ===နာမ်=== {{head|en|noun form}} # {{plural of|en|monitour}}"
392658
wikitext
text/x-wiki
=={{=en=}}==
===နာမ်===
{{head|en|noun form}}
# {{plural of|en|monitour}}
jzhz45m33d164kpgjf8n60ayvw7sykb
monitör
0
292849
392659
2026-04-13T14:51:47Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==တူရကဳ== ===နိရုတ်=== {{bor+|tr|fr|moniteur}} ===ဗွဟ်ရမ္သာၚ်=== * {{IPA|tr|/mo.niˈtœɾ/}} * {{hyphenation|tr|mo|ni|tör}} ===နာမ်=== {{tr-noun|ü|ler}} # ပရေၚ်မမၚ်မွဲ။ #: {{syn|tr|ekran|göstergeç|q2=rare}}"
392659
wikitext
text/x-wiki
==တူရကဳ==
===နိရုတ်===
{{bor+|tr|fr|moniteur}}
===ဗွဟ်ရမ္သာၚ်===
* {{IPA|tr|/mo.niˈtœɾ/}}
* {{hyphenation|tr|mo|ni|tör}}
===နာမ်===
{{tr-noun|ü|ler}}
# ပရေၚ်မမၚ်မွဲ။
#: {{syn|tr|ekran|göstergeç|q2=rare}}
edr89sfadvtve13ukvdedtrxz3efvt6
monitörler
0
292850
392660
2026-04-13T14:52:23Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==တူရကဳ== ===နာမ်=== {{head|tr|noun form}} # {{inflection of|tr|monitör||nom|p}}"
392660
wikitext
text/x-wiki
==တူရကဳ==
===နာမ်===
{{head|tr|noun form}}
# {{inflection of|tr|monitör||nom|p}}
9m4t6bc8qb2mwirs5i8yci118rof0oo
monitörü
0
292851
392661
2026-04-13T14:52:37Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==တူရကဳ== ===နာမ်=== {{head|tr|noun form}} # {{inflection of|tr|monitör||nom|p}}"
392661
wikitext
text/x-wiki
==တူရကဳ==
===နာမ်===
{{head|tr|noun form}}
# {{inflection of|tr|monitör||nom|p}}
9m4t6bc8qb2mwirs5i8yci118rof0oo
moniteur
0
292852
392662
2026-04-13T15:00:20Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=fr=}}== ===နိရုတ်=== ဝေါဟာကၠုၚ်နူ {{uder|fr|la|monitor}} ===ဗွဟ်ရမ္သာၚ်=== * {{fr-IPA}} * {{audio|fr|Fr-moniteur.ogg}} * {{audio|fr|LL-Q150 (fra)-DSwissK-moniteur.wav|a=<<Switzerland>> (<<Valais>>)}} * {{audio|fr|LL-Q150 (fra)-LoquaxFR-moniteur.wav|a=<<France>> (<<Vosges>>)}} * {{audio|fr|LL-Q150 (fra)-Poslovitch-moniteur.wav|a=<<France>> (<<Vosges>>)}}..."
392662
wikitext
text/x-wiki
=={{=fr=}}==
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{uder|fr|la|monitor}}
===ဗွဟ်ရမ္သာၚ်===
* {{fr-IPA}}
* {{audio|fr|Fr-moniteur.ogg}}
* {{audio|fr|LL-Q150 (fra)-DSwissK-moniteur.wav|a=<<Switzerland>> (<<Valais>>)}}
* {{audio|fr|LL-Q150 (fra)-LoquaxFR-moniteur.wav|a=<<France>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-moniteur.wav|a=<<France>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-WikiLucas00-moniteur.wav|a=<<France>> (<<Lyon>>)}}
===နာမ်===
{{fr-noun|m|f=+}}
# ပရေၚ်မမၚ်မွဲ (ညးမၚ်မွဲဒၟံၚ်လ္တူအရာမွဲမွဲသာ်)။
# ပရေၚ်ဗ္တောန်ထ္ၜး (ညးမစၞောန်ထ္ၜး၊ အ္စာဘာဗ္တောန်လိက်၊ ညးမကောပ်ကာဲ)။
# ပရေၚ်ဗလးရုပ်ဓာတ် (ဒဒ္ၚောဝ်ခမ်ပျူတာ)။
b9av57tp8rbrbr3gtfo20zfj6v61u9w
moniteurs
0
292853
392664
2026-04-13T15:07:07Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|monniteurs}} =={{=fr=}}== ===နာမ်=== {{head|fr|noun form|g=m}} # {{plural of|fr|moniteur}}"
392664
wikitext
text/x-wiki
{{also|monniteurs}}
=={{=fr=}}==
===နာမ်===
{{head|fr|noun form|g=m}}
# {{plural of|fr|moniteur}}
1hsn3tb9twr5of9vnon64u51vftlrmo
monniteurs
0
292854
392665
2026-04-13T15:07:52Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|moniteurs}} ==နဝ်မေံ== ===နာမ်=== {{head|nrf|noun form|g=m-p}} # {{plural of|nrf|monniteu}}"
392665
wikitext
text/x-wiki
{{also|moniteurs}}
==နဝ်မေံ==
===နာမ်===
{{head|nrf|noun form|g=m-p}}
# {{plural of|nrf|monniteu}}
eh71vt5xnqjel3simfuwjy0bu19df70
monniteu
0
292855
392666
2026-04-13T15:08:52Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==နဝ်မေံ== ===နိရုတ်=== ဝေါဟာကၠုၚ်နူ {{bor|nrf|la|monitor}}. ===နာမ်=== {{nrf-noun|m|pl=monniteurs}} # ပရေၚ်မမၚ်မွဲ။"
392666
wikitext
text/x-wiki
==နဝ်မေံ==
===နိရုတ်===
ဝေါဟာကၠုၚ်နူ {{bor|nrf|la|monitor}}.
===နာမ်===
{{nrf-noun|m|pl=monniteurs}}
# ပရေၚ်မမၚ်မွဲ။
1pq15rbj2prr1idxs1hhkslzdh4s4jc
monitrice
0
292856
392667
2026-04-13T15:11:53Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=fr=}}== ===ဗွဟ်ရမ္သာၚ်=== * {{fr-IPA}} * {{audio|fr|LL-Q150 (fra)-Poslovitch-monitrice.wav|a=<<France>> (<<Vosges>>)}} * {{audio|fr|LL-Q150 (fra)-WikiLucas00-monitrice.wav|a=<<France>> (<<Lyon>>)}} ===နာမ်=== {{fr-noun|f}} # {{female equivalent of|fr|moniteur}}"
392667
wikitext
text/x-wiki
=={{=fr=}}==
===ဗွဟ်ရမ္သာၚ်===
* {{fr-IPA}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-monitrice.wav|a=<<France>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-WikiLucas00-monitrice.wav|a=<<France>> (<<Lyon>>)}}
===နာမ်===
{{fr-noun|f}}
# {{female equivalent of|fr|moniteur}}
gqxdfhvomifodniqf1vhqgyvsm6f8hv
monitrices
0
292857
392668
2026-04-13T15:12:34Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=fr=}}== ===နာမ်=== {{head|fr|noun form|g=f}} # {{plural of|fr|monitrice}}"
392668
wikitext
text/x-wiki
=={{=fr=}}==
===နာမ်===
{{head|fr|noun form|g=f}}
# {{plural of|fr|monitrice}}
j4zk8e9jtv3nlrcop0u8e9drh5lkxo2
ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/moneō
118
292858
392669
2026-04-13T15:17:33Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/monēō}} {{reconstructed}} ==အခိုက်ကၞာ-မလိက်ဒစေၚ်== ===နိရုတ်=== {{root|itc-pro|ine-pro|*men-|id=think}} ဝေါဟာကၠုၚ်နူ {{inh|itc-pro|ine-pro|*monéyeti|*moné-ye-ti}}၊ နူကဵုဝေါဟာ {{inh|itc-pro|ine-pro|*monéyeti|..."
392669
wikitext
text/x-wiki
{{also|ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/monēō}}
{{reconstructed}}
==အခိုက်ကၞာ-မလိက်ဒစေၚ်==
===နိရုတ်===
{{root|itc-pro|ine-pro|*men-|id=think}}
ဝေါဟာကၠုၚ်နူ {{inh|itc-pro|ine-pro|*monéyeti|*moné-ye-ti}}၊ နူကဵုဝေါဟာ {{inh|itc-pro|ine-pro|*monéyeti|*mon-éye-}}
===ကြိယာ===
{{itc-verb}}
# သကဵု ကဵုသတိ၊ သကဵု ကဵုကသပ်ဂၞန်။
===မဒုၚ်လွဳစ===
* {{desc|la|moneō}}
87o0bxyp6pxmrq2zv364p4hbbm2zhc5
ဗီုပြၚ်သိုၚ်တၟိ:အိန်ဒဝ်-ယူရဝ်ပဳယာန်-အခိုက်ကၞာ/monéyeti
118
292859
392670
2026-04-13T15:21:29Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{reconstructed}} ==အိန်ဒဝ်-ယူရဝ်ပဳယာန်-အခိုက်ကၞာ== ===ကြိယာ=== {{ine-verb}} # သကဵုက္တဵုဒှ်ကၠုၚ်နကဵုမချပ်၊ မသ္ပပရေၚ်ချပ်။ ===မဒုၚ်လွဳစ=== * {{desc|itc-pro|*moneō}} * {{desc|iir-pro|*mānáyati}} ** {{desc|inc-pro|*mānáyati}} *** {{desc|sa|मा॒न..."
392670
wikitext
text/x-wiki
{{reconstructed}}
==အိန်ဒဝ်-ယူရဝ်ပဳယာန်-အခိုက်ကၞာ==
===ကြိယာ===
{{ine-verb}}
# သကဵုက္တဵုဒှ်ကၠုၚ်နကဵုမချပ်၊ မသ္ပပရေၚ်ချပ်။
===မဒုၚ်လွဳစ===
* {{desc|itc-pro|*moneō}}
* {{desc|iir-pro|*mānáyati}}
** {{desc|inc-pro|*mānáyati}}
*** {{desc|sa|मा॒नय॑ति}}
** {{desc|ira-pro}}
*** {{desc|ae|𐬨𐬁𐬥𐬀𐬌𐬌𐬈𐬌𐬙𐬍}}
* {{desc|ine-bsl-pro|*mánīˀtei}}
* {{desc|unc=1|cel-pro|-}}
** {{desc|obt|guomonim|der=1|unc=1}}
1rye4lzy1e4rlyo9jl4dkfqcmmcnz3i
ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/monēō
118
292860
392671
2026-04-13T15:25:05Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/moneō}} {{reconstructed}} ==အခိုက်ကၞာ-မလိက်ဒစေၚ်== ===ကြိယာ=== {{itc-verb}} # သကဵုမံၚ်၊ မံၚ်ဒၟံၚ်အတိုၚ်ဂှ်။ ===မဒုၚ်လွဳစ=== * {{desc|la|maneō}}"
392671
wikitext
text/x-wiki
{{also|ဗီုပြၚ်သိုၚ်တၟိ:အခိုက်ကၞာ-မလိက်ဒစေၚ်/moneō}}
{{reconstructed}}
==အခိုက်ကၞာ-မလိက်ဒစေၚ်==
===ကြိယာ===
{{itc-verb}}
# သကဵုမံၚ်၊ မံၚ်ဒၟံၚ်အတိုၚ်ဂှ်။
===မဒုၚ်လွဳစ===
* {{desc|la|maneō}}
ca3whzdn71e06hmwnh838pqehli6lhv
yat
0
292861
392672
2026-04-13T23:28:59Z
Apisite
133
ခၞံကၠောန်လဝ် မုက်လိက် နကု "==ဝဝ်လပုက်== ===နာမ်=== {{vo-noun}} # [[ပြိပ်]]၊ သၞဒမျိုၚ်။"
392672
wikitext
text/x-wiki
==ဝဝ်လပုက်==
===နာမ်===
{{vo-noun}}
# [[ပြိပ်]]၊ သၞဒမျိုၚ်။
594g4adrc3ag8pcp8rf7kc90b74gdr7
မဝ်ဂျူ:bo-pron/doc
828
292862
392684
2026-04-14T08:30:20Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "Pronunciation module for Tibetan. See {{temp|bo-IPA}}. <includeonly> {{module cat|bo}} </includeonly>"
392684
wikitext
text/x-wiki
Pronunciation module for Tibetan. See {{temp|bo-IPA}}.
<includeonly>
{{module cat|bo}}
</includeonly>
2vsutxdvaadiusf2fdnpyyjbp359oll
ကဏ္ဍ:မဝ်ဂျူတိဗိတ်ဂမၠိုၚ်
14
292863
392685
2026-04-14T08:32:27Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာတိဗိတ်|တိဗိတ်]] » '''မဝ်ဂျူဂမ..."
392685
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာတိဗိတ်|တိဗိတ်]] » '''မဝ်ဂျူဂမၠိုၚ်'''
:[[:ကဏ္ဍ:မဝ်ဂျူဂမၠိုၚ်|မဝ်ဂျူ]]ဘာသာတိဗိတ်၊ မနွံကဵုလုပ်အဝေါၚ်ကုဒ် Lua နကဵုမကၠောန်ဗဒှ် ကဵု မစဳရေၚ်ယဵုဒုၚ်သ္ပမာန်ဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာတိဗိတ်]][[ကဏ္ဍ:မဝ်ဂျူဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|တ]]
33q4dzlw7te836skr6imci1bzsntwbq
မဝ်ဂျူ:bo-common/doc
828
292864
392687
2026-04-14T08:35:30Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "This module does various things related to Tibetan. See {{temp|bo-new}}. <includeonly> {{module cat|bo}} </includeonly>"
392687
wikitext
text/x-wiki
This module does various things related to Tibetan. See {{temp|bo-new}}.
<includeonly>
{{module cat|bo}}
</includeonly>
53upwd86uz7smmnfre44f64yf3db6fv
မဝ်ဂျူ:xkz-IPA/doc
828
292865
392690
2026-04-14T08:48:33Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{documentation needed}}<!-- Replace this with a short description of the purpose of the module, and how to use it. --> <includeonly> {{module cat|xkz}} </includeonly>"
392690
wikitext
text/x-wiki
{{documentation needed}}<!-- Replace this with a short description of the purpose of the module, and how to use it. -->
<includeonly>
{{module cat|xkz}}
</includeonly>
1rkpcohgc5c30jz3tvr8add7lqht4bj
ကဏ္ဍ:မဝ်ဂျူခူတာတ်ဂမၠိုၚ်
14
292866
392691
2026-04-14T08:49:54Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာခူတာတ်|ခူတာတ်]] » '''မဝ်ဂျူဂမ..."
392691
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာခူတာတ်|ခူတာတ်]] » '''မဝ်ဂျူဂမၠိုၚ်'''
:[[:ကဏ္ဍ:မဝ်ဂျူဂမၠိုၚ်|မဝ်ဂျူ]]ဘာသာခူတာတ်၊ မနွံကဵုလုပ်အဝေါၚ်ကုဒ် Lua နကဵုမကၠောန်ဗဒှ် ကဵု မစဳရေၚ်ယဵုဒုၚ်သ္ပမာန်ဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာခူတာတ်]][[ကဏ္ဍ:မဝ်ဂျူဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|ခ]]
0pnv69ghd6g82oa19nzxbbo0bb1sycz
ထာမ်ပလိက်:attn
10
292867
392693
2026-04-14T08:51:45Z
咽頭べさ
33
咽頭べさ ပြံင်ပဆုဲလဝ် မုက်လိက် [[ထာမ်ပလိက်:attn]] ဇရေင် [[ထာမ်ပလိက်:attention]] နကု မကလေင်ပညုင်
392693
wikitext
text/x-wiki
#REDIRECT [[ထာမ်ပလိက်:attention]]
mrjt19k2q4myofy6rpqdyakpxpna0x4
ထာမ်ပလိက်:attention/documentation
10
292868
392694
2026-04-14T08:54:27Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{documentation subpage}} {{shortcut|Template:attn}} {{uses lua|Module:attention}} ==Examples== Adds entry to [[:Category:Requests for attention concerning French]]: : {{temp|attention|fr|is this example sentence missing a word?}} {{attention|fr|is this example sentence missing a word?}} ==Usage== {{tl|attention}} places an entry in {{cl|Requests for attention concerning <var>Language</var>}}. This template is no..."
392694
wikitext
text/x-wiki
{{documentation subpage}}
{{shortcut|Template:attn}}
{{uses lua|Module:attention}}
==Examples==
Adds entry to [[:Category:Requests for attention concerning French]]:
: {{temp|attention|fr|is this example sentence missing a word?}}
{{attention|fr|is this example sentence missing a word?}}
==Usage==
{{tl|attention}} places an entry in {{cl|Requests for attention concerning <var>Language</var>}}.
This template is normally invisible. However, you can make it visible by turning on the '''Catch My Attention''' gadget in your [[Special:Preferences#mw-prefsection-gadgets|gadget preferences]] (for logged-in users) or [[Wiktionary:Preferences for users without an account]] (for logged-out users).
Parameters:
; {{para|1|req=1}}
: The language code (see [[Wiktionary:Languages]]).
; {{para|2|opt=1}}
: A comment explaining why this entry needs attention.
; {{para|sort|opt=1}}
: A sortkey for the tagged entry.
; {{para|id|opt=1}}
: A value that refers unambiguously to the calling template, to be used when {{tl|attention}} is called by another template.
==Categories==
Categories populated using the template {{temp|attention}} (see [[:Category:Requests for attention by language]] for more):
* [[:Category:Requests for attention concerning Ancient Greek]]
* [[:Category:Requests for attention concerning Chinese]]
* [[:Category:Requests for attention concerning English]]
* [[:Category:Requests for attention concerning Spanish]]
* ... etc.
==Visibility==
As noted above, the easiest way to make the {{tl|attention}} tag visible is by turning on the Catch My Attention gadget.
However, users can finely customise the appearance of {{tl|attention}} by adding [[WT:CSS|CSS rules]] to [[Special:MyPage/common.css]]. (Turn off the Catch My Attention gadget before using these rules.)
The following code will cause browsers to display "Text goes here" where {{temp|attention}} is.
<syntaxhighlight lang="css">
.attentionseeking:before {
content: "Text goes here";
}
</syntaxhighlight>
When the tag is visible, the comment in parameter {{para|2}}, if any, can also be viewed by hovering over the tag with your mouse.
It is easily customizable; the following code will cause browsers to display a bold, red "<span style="color: red; font-size: larger; font-weight: bolder;">!!</span>" where {{temp|attention}} is.
<syntaxhighlight lang="css">
.attentionseeking:before {
content: "!!";
color: red;
font-size: larger;
font-weight: bolder;
}
</syntaxhighlight>
{{temp|attention}} tags for certain languages can be specifically targeted:
<syntaxhighlight lang="css">
[lang|=he].attentionseeking:before {
content: "!! Hebrew request for attention !!";
color: red;
font-size: larger;
font-weight: bolder;
}
</syntaxhighlight>
<includeonly>
[[ကဏ္ဍ:ထာမ်ပလိက်မထိၚ်ဒက်လဝ်ဂမၠိုၚ်]]
[[ကဏ္ဍ:ထာမ်ပလိက်အာတ်မိက်ဂမၠိုၚ်]]
</includeonly>
7rkvqgpmrmhml2aphmywkzr7vm6tglp
မဝ်ဂျူ:attention/doc
828
292869
392696
2026-04-14T08:59:08Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "This module implements the template {{tl|attention}}. <includeonly> [[ကဏ္ဍ:မဝ်ဂျူမထိၚ်ဒက်လဝ်ဂမၠိုၚ်]] </includeonly>"
392696
wikitext
text/x-wiki
This module implements the template {{tl|attention}}.
<includeonly>
[[ကဏ္ဍ:မဝ်ဂျူမထိၚ်ဒက်လဝ်ဂမၠိုၚ်]]
</includeonly>
066jgzzragf96iqol9kcomwvs2tj5j0
ကဏ္ဍ:နာမ်သေတ်ကဳမဳသ်ဂမၠိုၚ်
14
292870
392699
2026-04-14T09:05:12Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » :..."
392699
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » [[:ကဏ္ဍ:ဝေါဟာအဓိကသေတ်ကဳမဳသ်ဂမၠိုၚ်|ဝေါဟာတံသ္ဇိုၚ်]] » '''နာမ်ဂမၠိုၚ်'''
:ဝေါဟာသေတ်ကဳမဳသ်ပွမစၞောန်ထ္ၜးပူဂဵုအတေံ၊ မက္တဵုဒှ်ဂမၠိုၚ်၊ ဌာန်ဒတန်ဂမၠိုၚ်၊ ဥပပါတ်ဂမၠိုၚ်၊ ကဆံၚ်ဂုန်သတ္တိ ဝါ ကိုန်စဳရေၚ်ဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]][[ကဏ္ဍ:နာမ်ဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]
6s8iibwyfjlqjqlickwpwuur0gzll2p
ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်
14
292871
392700
2026-04-14T09:06:58Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:အရေဝ်ဘာသာ|သ]][[ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|သ]]"
392700
wikitext
text/x-wiki
[[ကဏ္ဍ:အရေဝ်ဘာသာ|သ]][[ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|သ]]
onvwhxmjbylk8axjmspe7w8i01xm3md
ကဏ္ဍ:ဝေါဟာသေတ်ကဳမဳသ်ကၠုၚ်နူဝေါဟာကြုက်-တိဗိတ်-အခိုက်ကၞာဂမၠိုၚ်
14
292872
392701
2026-04-14T09:08:57Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]"
392701
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]
4yct1oxinegpf19qn65pauefr22akc7
ကဏ္ဍ:ဝေါဟာသေတ်ကဳမဳသ်ဂွံလဝ်အာဲကၟာဲနူဝေါဟာကြုက်-တိဗိတ်-အခိုက်ကၞာဂမၠိုၚ်
14
292873
392702
2026-04-14T09:10:42Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]"
392702
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]
4yct1oxinegpf19qn65pauefr22akc7
ကဏ္ဍ:အက္ခရ်သေတ်ကဳမဳသ်ဂမၠိုၚ်
14
292874
392703
2026-04-14T09:12:13Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]"
392703
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]]
4yct1oxinegpf19qn65pauefr22akc7
ကဏ္ဍ:ဝေါဟာအဓိကသေတ်ကဳမဳသ်ဂမၠိုၚ်
14
292875
392704
2026-04-14T09:13:41Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » '''..."
392704
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » '''ဝေါဟာတံသ္ဇိုၚ်ဂမၠိုၚ်'''
:ဝေါဟာတံသ္ဇိုၚ်ဘာသာသေတ်ကဳမဳသ်၊ ကဏ္ဍနူကဵုမပါ်ပရံဒကုတ်မဆေၚ်စပ်ကဵုမအရေဝ်ဝေါဟာ။
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]][[ကဏ္ဍ:ဝေါဟာအဓိကဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]
ezlbp32o9owmis0rze0mgswnpkkuojr
ကဏ္ဍ:ဝေါဟာသေတ်ကဳမဳသ်ပ္တိတ်ရမျာၚ် IPA ဂမၠိုၚ်
14
292876
392705
2026-04-14T09:15:27Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » '''..."
392705
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်|သေတ်ကဳမဳသ်]] » '''{{PAGENAME}}'''
:ဝေါဟာသေတ်ကဳမဳသ်လုပ်အဝေါၚ်မဆေၚ်စပ်မပ္တိတ်ရမျာၚ်ပ္ဍဲနကဵုဗီုပြၚ် IPA။
သွက်မအာတ်မိက်ဆေၚ်စပ်ကဵုကဏ္ဍတဏအ်၊ ဗဵုရံၚ် ကဏ္ဍ:မအာတ်မိက်သွက်ရမျာၚ်ပ္ဍဲစရၚ်သေတ်ကဳမဳသ်ဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာသေတ်ကဳမဳသ်]][[ကဏ္ဍ:ဝေါဟာမနွံကဵုမပတိတ်ရမျာၚ် IPA ဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]
iuj4c8lgou7v97pbx09enm3ieh74mh9
ကဏ္ဍ:အက္ခရ်သှေပါဂမၠိုၚ်
14
292877
392706
2026-04-14T09:17:13Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာသှေပါ]]"
392706
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာသှေပါ]]
4dihr5bcrbyoxyhwfdrsazpmbqpk270
ကဏ္ဍ:ဝေါဟာသှေပါပ္တိတ်ရမျာၚ် IPA ဂမၠိုၚ်
14
292878
392707
2026-04-14T09:18:54Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသှေပါ|သှေပါ]] » '''{{PAGENAME}}''' :ဝေါဟ..."
392707
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာသှေပါ|သှေပါ]] » '''{{PAGENAME}}'''
:ဝေါဟာသှေပါလုပ်အဝေါၚ်မဆေၚ်စပ်မပ္တိတ်ရမျာၚ်ပ္ဍဲနကဵုဗီုပြၚ် IPA။
သွက်မအာတ်မိက်ဆေၚ်စပ်ကဵုကဏ္ဍတဏအ်၊ ဗဵုရံၚ် ကဏ္ဍ:မအာတ်မိက်သွက်ရမျာၚ်ပ္ဍဲစရၚ်သှေပါဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာသှေပါ]][[ကဏ္ဍ:ဝေါဟာမနွံကဵုမပတိတ်ရမျာၚ် IPA ဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|သ]]
2y9ppeivj6yaw6oytpxz1abukxmgf4w
ကဏ္ဍ:အက္ခရ်လာဒါခဳဂမၠိုၚ်
14
292879
392708
2026-04-14T09:20:28Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာလာဒါခဳ]]"
392708
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာလာဒါခဳ]]
ji527fze56emq63gyx3fnygerb8dwhx
ကဏ္ဍ:ဘာသာလာဒါခဳ
14
292880
392709
2026-04-14T09:24:49Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:အရေဝ်ဘာသာ|လ]][[ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|လ]]"
392709
wikitext
text/x-wiki
[[ကဏ္ဍ:အရေဝ်ဘာသာ|လ]][[ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|လ]]
cig6m0nxzvfyxq1pouwhvwiu1qx5ob2
ကဏ္ဍ:ဝေါဟာလာဒါခဳပ္တိတ်ရမျာၚ် IPA ဂမၠိုၚ်
14
292881
392710
2026-04-14T09:26:29Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာလာဒါခဳ|လာဒါခဳ]] » '''{{PAGENAME}}''' :ဝေ..."
392710
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာလာဒါခဳ|လာဒါခဳ]] » '''{{PAGENAME}}'''
:ဝေါဟာလာဒါခဳလုပ်အဝေါၚ်မဆေၚ်စပ်မပ္တိတ်ရမျာၚ်ပ္ဍဲနကဵုဗီုပြၚ် IPA။
သွက်မအာတ်မိက်ဆေၚ်စပ်ကဵုကဏ္ဍတဏအ်၊ ဗဵုရံၚ် ကဏ္ဍ:မအာတ်မိက်သွက်ရမျာၚ်ပ္ဍဲစရၚ်လာဒါခဳဂမၠိုၚ်။
[[ကဏ္ဍ:ဘာသာလာဒါခဳ]][[ကဏ္ဍ:ဝေါဟာမနွံကဵုမပတိတ်ရမျာၚ် IPA ဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|လ]]
1ze12wht0jfcutjbwm5uag6za34vd6l
ကဏ္ဍ:ဝေါဟာအဓိကလာဒါခဳဂမၠိုၚ်
14
292882
392711
2026-04-14T09:27:59Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာလာဒါခဳ|လာဒါခဳ]] » '''ဝေါဟာတံသ..."
392711
wikitext
text/x-wiki
[[:ကဏ္ဍ:ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်|ဒၞာဲလုပ်အဝေါၚ်ကဵုပၟိက်]] » [[:ကဏ္ဍ:အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်|အရေဝ်ဘာသာအိုတ်သီုဂမၠိုၚ်]] » [[:ကဏ္ဍ:ဘာသာလာဒါခဳ|လာဒါခဳ]] » '''ဝေါဟာတံသ္ဇိုၚ်ဂမၠိုၚ်'''
:ဝေါဟာတံသ္ဇိုၚ်ဘာသာလာဒါခဳ၊ ကဏ္ဍနူကဵုမပါ်ပရံဒကုတ်မဆေၚ်စပ်ကဵုမအရေဝ်ဝေါဟာ။
[[ကဏ္ဍ:ဘာသာလာဒါခဳ]][[ကဏ္ဍ:ဝေါဟာအဓိကဗက်အလိုက်အရေဝ်ဘာသာဂမၠိုၚ်|လ]]
835ngpw948cz8q6eb9nuh3kuacvmo2f
ကဏ္ဍ:အက္ခရ်သောၚ်ခါဂမၠိုၚ်
14
292883
392712
2026-04-14T09:29:07Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာသောၚ်ခါ]]"
392712
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာသောၚ်ခါ]]
togrp1wh0ynqpfnxhsv2wxn1doxdygg
ကဏ္ဍ:အက္ခရ်ဗဝ်လ်တဳဂမၠိုၚ်
14
292884
392713
2026-04-14T09:30:44Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဘာသာဗဝ်လ်တဳ]]"
392713
wikitext
text/x-wiki
[[ကဏ္ဍ:ဘာသာဗဝ်လ်တဳ]]
ey5tip3574op3r3bcfeu8lvjd1i6o6b
ကဏ္ဍ:ဗျဉ်အက္ခရ်တိဗိတ်ဂမၠိုၚ်
14
292885
392714
2026-04-14T09:31:45Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "[[ကဏ္ဍ:ဒၞာဲအခဝ်ယူနဳကုဒ်ဂမၠိုၚ်]]"
392714
wikitext
text/x-wiki
[[ကဏ္ဍ:ဒၞာဲအခဝ်ယူနဳကုဒ်ဂမၠိုၚ်]]
ak38aisd37thdp65kqkgyaqadjtvgs8
ဗီုပြၚ်သိုၚ်တၟိ:ကြုက်-တိဗိတ်-အခိုက်ကၞာ/s-ŋja
118
292886
392715
2026-04-14T09:39:07Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{reconstructed}} ==ကြုက်-တိဗိတ်-အခိုက်ကၞာ== [[File:Common carp.jpg|thumb|260px|{{w|Common carp}} ({{taxfmt|Cyprinus carpio|species}}).]] ===နာမ်=== {{head|sit-pro|noun|head=*{{SUBPAGENAME}}}} # [[က]]။ ===မဒုၚ်လွဳစ=== {{Sinoxenic|魚|ぎょ|gyo|어|eo|ngư}} **** {{desc|kzq|ngā}} **** {{desc|tsj|ང}} **** {{desc|twm|ȵᴀ¹³}} ***** {{desc|dz|..."
392715
wikitext
text/x-wiki
{{reconstructed}}
==ကြုက်-တိဗိတ်-အခိုက်ကၞာ==
[[File:Common carp.jpg|thumb|260px|{{w|Common carp}} ({{taxfmt|Cyprinus carpio|species}}).]]
===နာမ်===
{{head|sit-pro|noun|head=*{{SUBPAGENAME}}}}
# [[က]]။
===မဒုၚ်လွဳစ===
{{Sinoxenic|魚|ぎょ|gyo|어|eo|ngư}}
**** {{desc|kzq|ngā}}
**** {{desc|tsj|ང}}
**** {{desc|twm|ȵᴀ¹³}}
***** {{desc|dz|ཉ}}
***** {{desc|xsr|ཉ}}
***** {{desc|sip|ཉ}}
***** {{desc|bo|ཉ}}
***** {{desc|xkz|ཉ}}
*** {{desc|lep|ᰅᰫ|sc=Lepc|tr=ngú}}
**** {{desc|taj|'tar '''ŋa'''}}
**** {{desc|gvr|'ta '''ŋa'''}}
**** {{desc|nmm|dar² '''ŋa²'''}}
**** {{desc|ths|tɔr '''ŋɔ'''}}
*** {{desc|new|ङ|q1=Dolakhali|q2=Kathmandu|ञ}}
**** {{desc|brd|नङा}}
**** {{desc|thf|नाङा}}
***** {{desc|lif|ᤏᤠ᤺|sc=Limb|tr=naː}}
***** {{desc|ybi|ङा|t=fish}}
***** {{desc|lbr|ङाः|tr=ŋa}}
***** {{desc|aph|'''ŋa''' sa}}
***** {{desc|dus|ङु|tr=ŋu|t=fish}}
***** {{desc|klr|ङो़|tr=ngö|t=fish}}
***** {{desc|bhj|ŋa}}
***** {{desc|tdh|ŋoː}}
***** {{desc|bap|na}}
***** {{desc|kle|ŋa}}
***** {{desc|rab|'''nga'''sa}}
***** {{desc|apt|ŋúi}}
***** {{desc|njz|ŋu-i}}
***** {{desc|adi|o-ŋoː}}
***** {{desc|adl|ŋoi}}
***** {{desc|mrg|ŋui}}
***** {{desc|njz|ngui}}
***** {{desc|mxj|ɑ³¹ ŋɑ⁵⁵}}
***** {{desc|clk|ŋa}}
***** {{desc|csy|ngā sā}}
***** {{desc|tcz|ngâa}}
***** {{desc|ctd|nga¹}}
***** {{desc|csh|ngó}}
***** {{desc|cnb|ŋo}}
***** {{desc|mwq|nga}}
***** {{desc|cnk|ngoo}}
***** {{desc|hlt|ŋa}}
***** {{desc|dao|ŋá}}
***** {{desc|cnh|ŋàa}}
***** {{desc|cfm|ŋâa}}
***** {{desc|lus|hŋa}}
***** {{desc|mrh|ngá}}
***** {{desc|clt|ngaa}}
* {{desc|sit-aao-pro|*a-hŋaʔ}}
** {{desc|njo|ango|ts=³a ¹ŋuʔ}}
** {{desc|njh|¹o ²ŋo(ʔ)}}
** {{desc|nsa|ngu}}
** {{desc|yim|thü ngü}}
** {{desc|npo|anga}}
** {{desc|nni|anga}}
** {{desc|nbu|ŋa}}
* {{desc|mni|ꯉꯥ}}
** {{desc|brx|ना|ts=naʔ}}
** {{desc|grt|na·-}}
** {{desc|aot|na•}}
** {{desc|dis|na}}
** {{desc|njb|ŋaʔ}}
** {{desc|nst|ŋaʔ}}
** {{desc|nbc|ŋàu}}
** {{desc|kix|¹ŋo̥ᴜʔ}}
** {{desc|nbe|nya}}
** {{desc|nph|ñaʔ}}
** {{desc|nnp|nya}}
** {{desc|kac|nga|ts=ŋa⁵⁵}}
** {{desc|ckh|tə'''na'''}}
** {{desc|ers|ȵæ³⁵}}
** {{desc|gqi|tʃɿ⁵³ '''ȵi⁵³'''}}
** {{desc|qvy|ȵa¹³}}
** {{desc|sxg|ʔu⁵⁵}}
** {{desc|nun|ŋuɑ⁵⁵}}
** {{desc|raw|ŋɑ³³}}
** {{desc|duu|'''ŋɑ⁵⁵''' pɿɑ̆ʔ⁵⁵}}
** {{desctree|sit-nas-pro|*ŋi}}
**** {{desc|my|ငါး}}
***** {{desc|rmz|ŋá}}
**** {{desc|hpo|tă '''ŋàh'''}}
**** {{desc|bxd|'''ŋə̆''' ta³¹}}
**** {{desc|mhx|'''ŋə̆³¹''' tsɔ³¹}}
**** {{desc|atb|'''ŋŏ²¹''' tso²¹}}
**** {{desc|lsi|'''ŋə̆³¹''' tso³³}}
**** {{desc|tbq-ngo|oeng}}
**** {{desc|kaf|'''ŋa³¹''' mɛ⁴⁴}}
**** {{desc|nuf|ŋɑ⁵⁵}}
**** {{desc|jiu|ŋɔ³³}}
**** {{desc|jiy|'''ŋɔ⁴⁴''' tɤ³¹}}
**** {{desc|lkc|ŋʌ³¹}}
**** {{desc|lhu|ŋâ}}
**** {{desc|lis|ŋuɑ⁵⁵}}
**** {{desc|ysn|ŋɒ⁵⁵}}
**** {{desc|ahk|ŋà}} → {{m|ahk|ŋà sjhà}}
**** {{desc|enu|'''ŋà''' shà}}
**** {{desc|hni|'''ŋa³¹''' de⁵⁵}}
**** {{desc|byo|'''ŋa³¹''' ɕa³¹}}
**** {{desc|ktp|'''ŋò''' shɔ̀}}
**** {{desc|how|'''ŋɔ³¹''' ʃɔ³¹}}
**** {{desc|mpz|ŋo²}}
**** {{desc|aza|a³³ '''ŋɔ²²'''}}
**** {{desc|ymc|'''ŋa⁵⁵''' mjɛ⁵⁵}}
**** {{desc|ypg|'''ŋɑ³¹''' zɨ̠²³}}
**** {{desc|yhl|'''ŋa³³''' ɡɯ²¹}}
**** {{desc|phh|ŋaʔ³⁵}}
**** {{desc|ypz|'''ŋa³³''' za³³}}
** {{desc|ksw|tr=ȵa³¹}}
** {{desc|bfc|ŋu⁵⁵}}
** {{desc|bfs|ŋv³⁵}}
** {{desc|bca|ŋv⁵⁵}}
===နာမ် ၂ ===
{{head|sit-pro|noun|head=*{{SUBPAGENAME}}}}
# ဂၞေဟ်၊ ၚေတ်။
kukl2zs8kf5zjspq2bq3trq0yixboc7
ဗီုပြၚ်သိုၚ်တၟိ:သေံ-အခိုက်ကၞာ/ʰmanᴬ
118
292887
392718
2026-04-14T09:50:37Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{reconstruction}} ==သေံ-အခိုက်ကၞာ== ===နာမဝိသေသန=== {{head|tai-pro|နာမဝိသေသန}} # မဆက်ၜံၚ်ကောန်ဇာတ်ဟွံမာန်။"
392718
wikitext
text/x-wiki
{{reconstruction}}
==သေံ-အခိုက်ကၞာ==
===နာမဝိသေသန===
{{head|tai-pro|နာမဝိသေသန}}
# မဆက်ၜံၚ်ကောန်ဇာတ်ဟွံမာန်။
sardpnsdk6l7ud8btbq1cfh1r3zckpn
気圏
0
292888
392719
2026-04-14T10:24:04Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=ja=}}== {{ja-kanjitab|き|けん|yomi=o}} ===ဗွဟ်ရမ္သာၚ်=== * {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}} ===နာမ်=== {{ja-noun|きけん}} # ပရေၚ်အကာဲအရာပွဳပွိုၚ်ဝုတ်ဒိုဟ်။ ==={{References}}=== <references/>"
392719
wikitext
text/x-wiki
=={{=ja=}}==
{{ja-kanjitab|き|けん|yomi=o}}
===ဗွဟ်ရမ္သာၚ်===
* {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}}
===နာမ်===
{{ja-noun|きけん}}
# ပရေၚ်အကာဲအရာပွဳပွိုၚ်ဝုတ်ဒိုဟ်။
==={{References}}===
<references/>
r5m2t5d1tavveisoxdl8thvf5tyl9n8
帰県
0
292889
392720
2026-04-14T10:27:47Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=ja=}}== {{ja-kanjitab|き|けん|yomi=o}} ===ဗွဟ်ရမ္သာၚ်=== * {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}} ===နာမ်=== {{ja-noun|きけん}} # ပွမကလေၚ်စိုပ်မသ္ဍိုက်မၠိုက်။ ==={{References}}=== <references/>"
392720
wikitext
text/x-wiki
=={{=ja=}}==
{{ja-kanjitab|き|けん|yomi=o}}
===ဗွဟ်ရမ္သာၚ်===
* {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}}
===နာမ်===
{{ja-noun|きけん}}
# ပွမကလေၚ်စိုပ်မသ္ဍိုက်မၠိုက်။
==={{References}}===
<references/>
q5b4zhffu4kj1b78ct0agp6lcs21wz9
貴顕
0
292890
392721
2026-04-14T10:30:35Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=ja=}}== {{ja-kanjitab|き|けん|yomi=o}} ===ဗွဟ်ရမ္သာၚ်=== * {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}} ===နာမ်=== {{ja-noun|きけん}} # ပူဂဵုမတီကၠိုဟ်ခၠၚ်လဝ်တၚ်မတၞဟ်ခြာခိုဟ်ခိုဟ်။ ==={{References}}=== <references/>"
392721
wikitext
text/x-wiki
=={{=ja=}}==
{{ja-kanjitab|き|けん|yomi=o}}
===ဗွဟ်ရမ္သာၚ်===
* {{ja-pron|きけん|acc=0|dev=1|acc_ref=DJR,NHK}}
===နာမ်===
{{ja-noun|きけん}}
# ပူဂဵုမတီကၠိုဟ်ခၠၚ်လဝ်တၚ်မတၞဟ်ခြာခိုဟ်ခိုဟ်။
==={{References}}===
<references/>
8379e1wfhmba8u4jcp6mvapy7e0ri2e
棄権
0
292891
392722
2026-04-14T10:35:57Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=ja=}}== {{wp|ja:}} {{ja-kanjitab|き|けん|yomi=o}} ===ဗွဟ်ရမ္သာၚ်=== {{ja-pron|きけん|acc=0|acc_ref=DJR}} ===နာမ်=== {{ja-noun|きけん}} # ပွမကေတ်တိုန်မဍာံပြမွဲသာ်ဂမၠိုၚ်။ ===ကြိယာ=== {{ja-verb-suru|きけん|tr=transitive}} # သကဵုပွမတိုန်ကေတ်မဍာံပြမွ..."
392722
wikitext
text/x-wiki
=={{=ja=}}==
{{wp|ja:}}
{{ja-kanjitab|き|けん|yomi=o}}
===ဗွဟ်ရမ္သာၚ်===
{{ja-pron|きけん|acc=0|acc_ref=DJR}}
===နာမ်===
{{ja-noun|きけん}}
# ပွမကေတ်တိုန်မဍာံပြမွဲသာ်ဂမၠိုၚ်။
===ကြိယာ===
{{ja-verb-suru|きけん|tr=transitive}}
# သကဵုပွမတိုန်ကေတ်မဍာံပြမွဲသာ်ဂမၠိုၚ်။
==={{References}}===
<references/>
3bddtnkknuzwv399706jti1vs1nxv91
棄權
0
292892
392723
2026-04-14T10:47:56Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|弃权|棄権}} =={{=zh=}}== {{zh-forms|s=弃权}} ===ဗွဟ်ရမ္သာၚ်=== {{zh-pron |m=qìquán |c=hei3 kyun4 |h=pfs=hi-khièn/khi-khièn;hrs=h:hiˇ kien |mn=qz,twv,xm,zz:khí-koân/tw:khí-khoân |w=sh:5chi jioe |cat=v }} ===ကြိယာ=== {{head|zh|ကြိယာ}} # သကဵုဒုၚ်ကျမဍာံပြမွဲသာ်ဂမၠိုၚ်။ # သကဵုဝေၚ်..."
392723
wikitext
text/x-wiki
{{also|弃权|棄権}}
=={{=zh=}}==
{{zh-forms|s=弃权}}
===ဗွဟ်ရမ္သာၚ်===
{{zh-pron
|m=qìquán
|c=hei3 kyun4
|h=pfs=hi-khièn/khi-khièn;hrs=h:hiˇ kien
|mn=qz,twv,xm,zz:khí-koân/tw:khí-khoân
|w=sh:5chi jioe
|cat=v
}}
===ကြိယာ===
{{head|zh|ကြိယာ}}
# သကဵုဒုၚ်ကျမဍာံပြမွဲသာ်ဂမၠိုၚ်။
# သကဵုဝေၚ်ပါဲ၊ သကဵုပါဲကၠေံကဵုဆန္ဒမာဲမွဲသာ်။
# သကဵုဆုတ်ထောံနအလိုက်ဆန္ဒဇကုနူပရေၚ်ပြိုၚ်ပ္ကာန်ကဆံၚ်တုပ်၊ သကဵုဒုၚ်ဝန် ဝါ သီကေတ်အနေဒဒှ်ဒုဟ်ဒန်။
=={{=ja=}}==
{{ja-kanjitab|き|けん|yomi=o}}
{{ja-gv|棄権}}
=={{=ko=}}==
{{ko-hanjatab}}
===နာမ်===
{{ko-noun|hangeul=기권}}
# {{hanja form of|기권|}}
sqg39aai5405lyazzzul6ubcpbd9i6b
qìquán
0
292893
392724
2026-04-14T10:48:49Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|qīquán|qíquán}} ==မာန်ဒါရေဝ်== ===ဗီုအက္ခရ်ရောမ=== {{cmn-pinyin}} # {{cmn-pinyin of|棄權}}"
392724
wikitext
text/x-wiki
{{also|qīquán|qíquán}}
==မာန်ဒါရေဝ်==
===ဗီုအက္ခရ်ရောမ===
{{cmn-pinyin}}
# {{cmn-pinyin of|棄權}}
pz57qlmrm1wja2sqpbh0zj9zy69fnzo
qīquán
0
292894
392725
2026-04-14T10:49:36Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|qíquán|qìquán}} ==မာန်ဒါရေဝ်== ===ဗီုအက္ခရ်ရောမ=== {{cmn-pinyin}} # {{cmn-pinyin of|期權}}"
392725
wikitext
text/x-wiki
{{also|qíquán|qìquán}}
==မာန်ဒါရေဝ်==
===ဗီုအက္ခရ်ရောမ===
{{cmn-pinyin}}
# {{cmn-pinyin of|期權}}
pd36typfyhqnfv06xl1bqy4d7edttwi
期權
0
292895
392726
2026-04-14T10:51:43Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=zh=}}== {{zh-forms|s=期权}} {{wp|zh:}} ===ဗွဟ်ရမ္သာၚ်=== {{zh-pron |m=期quán |c=kei4 kyun4 |cat=n }} ===နာမ်=== {{head|zh|နာမ်}} # အခေါၚ်မရုဲပိုၚ်။"
392726
wikitext
text/x-wiki
=={{=zh=}}==
{{zh-forms|s=期权}}
{{wp|zh:}}
===ဗွဟ်ရမ္သာၚ်===
{{zh-pron
|m=期quán
|c=kei4 kyun4
|cat=n
}}
===နာမ်===
{{head|zh|နာမ်}}
# အခေါၚ်မရုဲပိုၚ်။
2ignids8fdohhb7suxe7ndi5qg3ogkz
qíquán
0
292896
392727
2026-04-14T10:52:26Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|qīquán|qìquán}} ==မာန်ဒါရေဝ်== ===ဗီုအက္ခရ်ရောမ=== {{cmn-pinyin}} # {{cmn-pinyin of|齊全}} # {{cmn-pinyin of|期權}}"
392727
wikitext
text/x-wiki
{{also|qīquán|qìquán}}
==မာန်ဒါရေဝ်==
===ဗီုအက္ခရ်ရောမ===
{{cmn-pinyin}}
# {{cmn-pinyin of|齊全}}
# {{cmn-pinyin of|期權}}
o4bfto8bn8gp2k6ikh9m7zlo59c47bd
齊全
0
292897
392728
2026-04-14T10:58:44Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|齐全}} =={{=zh=}}== {{zh-forms|s=齐全}} {{was wotd|၂၀၂၆|ဨပြဳ|၁၅}} ===ဗွဟ်ရမ္သာၚ်=== {{zh-pron |m=qíquán |ma=Zh-qíquán.ogg |c=cai4 cyun4 |mn=chê-choân/xm:chôe-choân/qz:chôe-chn̂g/twv:chê-chn̂g/yl:chê-chûiⁿ |mn-t=ci5 cuang5 |w=sz:6zi2 zie2 |cat=a }} ===နာမဝိသေသန=== {{head|zh|နာမဝိသေသန}} # မဍိုက်ပေ..."
392728
wikitext
text/x-wiki
{{also|齐全}}
=={{=zh=}}==
{{zh-forms|s=齐全}}
{{was wotd|၂၀၂၆|ဨပြဳ|၁၅}}
===ဗွဟ်ရမ္သာၚ်===
{{zh-pron
|m=qíquán
|ma=Zh-qíquán.ogg
|c=cai4 cyun4
|mn=chê-choân/xm:chôe-choân/qz:chôe-chn̂g/twv:chê-chn̂g/yl:chê-chûiⁿ
|mn-t=ci5 cuang5
|w=sz:6zi2 zie2
|cat=a
}}
===နာမဝိသေသန===
{{head|zh|နာမဝိသေသန}}
# မဍိုက်ပေၚ်၊ ဖ္ဍိုက်ဗပေၚ်ကဵုပၟိက်ပရေၚ်မဒးရး။
===ဗွဟ်ရမ္သာၚ်===
{{zh-pron
|mn=xm,tw:chiâu-chn̂g/qz,jj,ph:châu-chn̂g
|cat=a
}}
===နာမဝိသေသန===
{{head|zh|နာမဝိသေသန}}
# ဍိုက်ဍိုက်ပေၚ်ပေၚ်၊ ဖအိုတ်။
bwmleowhdof7kaec04gx4wvwtddpltw
齐全
0
292898
392729
2026-04-14T10:59:39Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{also|齊全}} =={{=zh=}}== {{zh-see|齊全}}"
392729
wikitext
text/x-wiki
{{also|齊全}}
=={{=zh=}}==
{{zh-see|齊全}}
njjnjfuzmd1ht9z7au2q2z7a2qk582t
ဝိက်ရှေန်နရဳ:မအရေဝ်သွက်တ္ၚဲဏအ်/၂၀၂၆/ဨပြဳ ၁၅
4
292899
392730
2026-04-14T11:01:27Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "{{WOTD|齊全|နာမဝိသေသန| မဍိုက်ပေၚ်၊ ဖ္ဍိုက်ဗပေၚ်ကဵုပၟိက်ပရေၚ်မဒးရး။ # ဍိုက်ဍိုက်ပေၚ်ပေၚ်၊ ဖအိုတ်။|audio=Zh-qíquán.ogg|ဨပြဳ|၁၅}}"
392730
wikitext
text/x-wiki
{{WOTD|齊全|နာမဝိသေသန| မဍိုက်ပေၚ်၊ ဖ္ဍိုက်ဗပေၚ်ကဵုပၟိက်ပရေၚ်မဒးရး။
# ဍိုက်ဍိုက်ပေၚ်ပေၚ်၊ ဖအိုတ်။|audio=Zh-qíquán.ogg|ဨပြဳ|၁၅}}
ocsmi4wrsaenwfv7pr0jlo1f9kz1ach
기권
0
292900
392731
2026-04-14T11:04:32Z
咽頭べさ
33
ခၞံကၠောန်လဝ် မုက်လိက် နကု "=={{=ko=}}== ===ဗွဟ်ရမ္သာၚ်=== {{ko-IPA}} ===နာမ်=== {{ko-noun}} # မံၚ်ထောံအကြာ။"
392731
wikitext
text/x-wiki
=={{=ko=}}==
===ဗွဟ်ရမ္သာၚ်===
{{ko-IPA}}
===နာမ်===
{{ko-noun}}
# မံၚ်ထောံအကြာ။
kak62d32b8dijoeqtlad0i9w6focuxe