ဝိက်ရှေန်နရဳ 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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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 &nbsp; ''([[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